Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: ftmac100: add multicast filtering possibility

If netdev_mc_count() is not zero and not IFF_ALLMULTI, filter
incoming multicast packets. The chip has a Multicast Address Hash Table
for allowed multicast addresses, so we fill it.

Implement .ndo_set_rx_mode and recalculate multicast hash table. Also
observe change of IFF_PROMISC and IFF_ALLMULTI netdev flags.

Signed-off-by: Sergei Antonov <saproj@gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Sergei Antonov and committed by
David S. Miller
7a1c3821 6231e47b

+45 -5
+45 -5
drivers/net/ethernet/faraday/ftmac100.c
··· 149 149 iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR); 150 150 } 151 151 152 + static void ftmac100_setup_mc_ht(struct ftmac100 *priv) 153 + { 154 + struct netdev_hw_addr *ha; 155 + u64 maht = 0; /* Multicast Address Hash Table */ 156 + 157 + netdev_for_each_mc_addr(ha, priv->netdev) { 158 + u32 hash = ether_crc(ETH_ALEN, ha->addr) >> 26; 159 + 160 + maht |= BIT_ULL(hash); 161 + } 162 + 163 + iowrite32(lower_32_bits(maht), priv->base + FTMAC100_OFFSET_MAHT0); 164 + iowrite32(upper_32_bits(maht), priv->base + FTMAC100_OFFSET_MAHT1); 165 + } 166 + 167 + static void ftmac100_set_rx_bits(struct ftmac100 *priv, unsigned int *maccr) 168 + { 169 + struct net_device *netdev = priv->netdev; 170 + 171 + /* Clear all */ 172 + *maccr &= ~(FTMAC100_MACCR_RCV_ALL | FTMAC100_MACCR_RX_MULTIPKT | 173 + FTMAC100_MACCR_HT_MULTI_EN); 174 + 175 + /* Set the requested bits */ 176 + if (netdev->flags & IFF_PROMISC) 177 + *maccr |= FTMAC100_MACCR_RCV_ALL; 178 + if (netdev->flags & IFF_ALLMULTI) 179 + *maccr |= FTMAC100_MACCR_RX_MULTIPKT; 180 + else if (netdev_mc_count(netdev)) { 181 + *maccr |= FTMAC100_MACCR_HT_MULTI_EN; 182 + ftmac100_setup_mc_ht(priv); 183 + } 184 + } 185 + 152 186 #define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \ 153 187 FTMAC100_MACCR_RCV_EN | \ 154 188 FTMAC100_MACCR_XDMA_EN | \ ··· 216 182 if (netdev->mtu > ETH_DATA_LEN) 217 183 maccr |= FTMAC100_MACCR_RX_FTL; 218 184 219 - /* Add other bits as needed */ 220 - if (netdev->flags & IFF_PROMISC) 221 - maccr |= FTMAC100_MACCR_RCV_ALL; 222 - if (netdev->flags & IFF_ALLMULTI) 223 - maccr |= FTMAC100_MACCR_RX_MULTIPKT; 185 + ftmac100_set_rx_bits(priv, &maccr); 224 186 225 187 iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); 226 188 return 0; ··· 1097 1067 return 0; 1098 1068 } 1099 1069 1070 + static void ftmac100_set_rx_mode(struct net_device *netdev) 1071 + { 1072 + struct ftmac100 *priv = netdev_priv(netdev); 1073 + unsigned int maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR); 1074 + 1075 + ftmac100_set_rx_bits(priv, &maccr); 1076 + iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); 1077 + } 1078 + 1100 1079 static const struct net_device_ops ftmac100_netdev_ops = { 1101 1080 .ndo_open = ftmac100_open, 1102 1081 .ndo_stop = ftmac100_stop, ··· 1114 1075 .ndo_validate_addr = eth_validate_addr, 1115 1076 .ndo_eth_ioctl = ftmac100_do_ioctl, 1116 1077 .ndo_change_mtu = ftmac100_change_mtu, 1078 + .ndo_set_rx_mode = ftmac100_set_rx_mode, 1117 1079 }; 1118 1080 1119 1081 /******************************************************************************