/** * et131x_multicast - The handler to configure multicasting on the interface * @netdev: a pointer to a net_device struct representing the device */ void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); uint32_t PacketFilter = 0; unsigned long flags; struct dev_mc_list *mclist; int i; spin_lock_irqsave(&adapter->Lock, flags); /* Before we modify the platform-independent filter flags, store them * locally. This allows us to determine if anything's changed and if * we even need to bother the hardware */ PacketFilter = adapter->PacketFilter; /* Clear the 'multicast' flag locally; becuase we only have a single * flag to check multicast, and multiple multicast addresses can be * set, this is the easiest way to determine if more than one * multicast address is being set. */ PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; /* Check the net_device flags and set the device independent flags * accordingly */ if (netdev->flags & IFF_PROMISC) { adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS; } else { adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; } if (netdev->flags & IFF_ALLMULTI) { adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev_mc_count(netdev) > NIC_MAX_MCAST_LIST) { adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev_mc_count(netdev) < 1) { adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; } else { adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST; } /* Set values in the private adapter struct */ i = 0; netdev_for_each_mc_addr(mclist, netdev) { if (i == NIC_MAX_MCAST_LIST) break; memcpy(adapter->MCList[i++], mclist->dmi_addr, ETH_ALEN); } adapter->MCAddressCount = i; /* Are the new flags different from the previous ones? If not, then no * action is required * * NOTE - This block will always update the MCList with the hardware, * even if the addresses aren't the same. */ if (PacketFilter != adapter->PacketFilter) { /* Call the device's filter function */ et131x_set_packet_filter(adapter); } spin_unlock_irqrestore(&adapter->Lock, flags); }
/** * et131x_multicast - The handler to configure multicasting on the interface * @netdev: a pointer to a net_device struct representing the device */ void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); uint32_t PacketFilter = 0; uint32_t count; unsigned long lockflags; struct dev_mc_list *mclist = netdev->mc_list; DBG_ENTER(et131x_dbginfo); spin_lock_irqsave(&adapter->Lock, lockflags); /* Before we modify the platform-independent filter flags, store them * locally. This allows us to determine if anything's changed and if * we even need to bother the hardware */ PacketFilter = adapter->PacketFilter; /* Clear the 'multicast' flag locally; becuase we only have a single * flag to check multicast, and multiple multicast addresses can be * set, this is the easiest way to determine if more than one * multicast address is being set. */ PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; /* Check the net_device flags and set the device independent flags * accordingly */ DBG_VERBOSE(et131x_dbginfo, "MULTICAST ADDR COUNT: %d\n", netdev->mc_count); if (netdev->flags & IFF_PROMISC) { DBG_VERBOSE(et131x_dbginfo, "Request: PROMISCUOUS MODE ON\n"); adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS; } else { DBG_VERBOSE(et131x_dbginfo, "Request: PROMISCUOUS MODE OFF\n"); adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; } if (netdev->flags & IFF_ALLMULTI) { DBG_VERBOSE(et131x_dbginfo, "Request: ACCEPT ALL MULTICAST\n"); adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev->mc_count > NIC_MAX_MCAST_LIST) { DBG_WARNING(et131x_dbginfo, "ACCEPT ALL MULTICAST for now, as there's more Multicast " "addresses than the HW supports\n"); adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev->mc_count < 1) { DBG_VERBOSE(et131x_dbginfo, "Request: REJECT ALL MULTICAST\n"); adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; } else { DBG_VERBOSE(et131x_dbginfo, "Request: SET MULTICAST FILTER(S)\n"); adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST; } /* Set values in the private adapter struct */ adapter->MCAddressCount = netdev->mc_count; if (netdev->mc_count) { if (mclist->dmi_addrlen != ETH_ALEN) { DBG_WARNING(et131x_dbginfo, "Multicast addrs are not ETH_ALEN in size\n"); } else { count = netdev->mc_count - 1; memcpy(adapter->MCList[count], mclist->dmi_addr, ETH_ALEN); } } /* Are the new flags different from the previous ones? If not, then no * action is required * * NOTE - This block will always update the MCList with the hardware, * even if the addresses aren't the same. */ if (PacketFilter != adapter->PacketFilter) { /* Call the device's filter function */ DBG_VERBOSE(et131x_dbginfo, "UPDATE REQUIRED, FLAGS changed\n"); et131x_set_packet_filter(adapter); } else { DBG_VERBOSE(et131x_dbginfo, "NO UPDATE REQUIRED, FLAGS didn't change\n"); } spin_unlock_irqrestore(&adapter->Lock, lockflags); DBG_LEAVE(et131x_dbginfo); }