/**
 * 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);
}
示例#2
0
/**
 * 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);
}