static void sr9700_set_multicast(struct net_device *netdev) { struct usbnet *dev = netdev_priv(netdev); /* We use the 20 byte dev->data for our 8 byte filter buffer * to avoid allocating memory that is tricky to free later */ u8 *hashes = (u8 *)&dev->data; /* rx_ctl setting : enable, disable_long, disable_crc */ u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG; memset(hashes, 0x00, SR_MCAST_SIZE); /* broadcast address */ hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG; if (netdev->flags & IFF_PROMISC) { rx_ctl |= RCR_PRMSC; } else if (netdev->flags & IFF_ALLMULTI || netdev_mc_count(netdev) > SR_MCAST_MAX) { rx_ctl |= RCR_RUNT; } else if (!netdev_mc_empty(netdev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, netdev) { u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } }
static void qf9700_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); /* We use the 20 byte dev->data for our 8 byte filter buffer * to avoid allocating memory that is tricky to free later */ u8 *hashes = (u8 *) & dev->data; u8 rx_ctl = 0x31; // enable, disable_long, disable_crc memset(hashes, 0x00, QF_MCAST_SIZE); hashes[QF_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ if (net->flags & IFF_PROMISC) { rx_ctl |= 0x02; } else if (net->flags & IFF_ALLMULTI || netdev_mc_count(net) > QF_MCAST_MAX) { rx_ctl |= 0x04; } else if (netdev_mc_empty(net)) { /* just broadcast and directed */ } else { /* We use the 20 byte dev->data * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ struct netdev_hw_addr *ha; u32 crc_bits; memset(hashes, 0, QF_MCAST_SIZE); /* Build the multicast hash filter. */ netdev_for_each_mc_addr(ha, net) { crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc_bits >> 3] |= 1 << (crc_bits & 7); } }
static void dwmac100_set_filter(struct net_device *dev) { void __iomem *ioaddr = (void __iomem *) dev->base_addr; u32 value = readl(ioaddr + MAC_CONTROL); if (dev->flags & IFF_PROMISC) { value |= MAC_CONTROL_PR; value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) || (dev->flags & IFF_ALLMULTI)) { value |= MAC_CONTROL_PM; value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); writel(0xffffffff, ioaddr + MAC_HASH_HIGH); writel(0xffffffff, ioaddr + MAC_HASH_LOW); } else if (netdev_mc_empty(dev)) { value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else { u32 mc_filter[2]; struct netdev_hw_addr *ha; value |= MAC_CONTROL_HP; value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(ha, dev) { int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); } writel(mc_filter[0], ioaddr + MAC_HASH_LOW); writel(mc_filter[1], ioaddr + MAC_HASH_HIGH); }
static void set_multicast (struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->ioaddr; u32 hash_table[2]; u16 rx_mode = 0; hash_table[0] = hash_table[1] = 0; /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ hash_table[1] |= 0x02000000; if (dev->flags & IFF_PROMISC) { /* Receive all frames promiscuously. */ rx_mode = ReceiveAllFrames; } else if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > multicast_filter_limit)) { /* Receive broadcast and multicast frames */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; /* Receive broadcast frames and multicast frames filtering by Hashtable */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; netdev_for_each_mc_addr(ha, dev) { int bit, index = 0; int crc = ether_crc_le(ETH_ALEN, ha->addr); /* The inverted high significant 6 bits of CRC are used as an index to hashtable */ for (bit = 0; bit < 6; bit++) if (crc & (1 << (31 - bit))) index |= (1 << bit); hash_table[index / 32] |= (1 << (index % 32)); } } else {
static void smsnet_set_multicast_list(struct net_device *dev) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) int mc_count = netdev_mc_count(dev); sms_info("mc count %d", mc_count); if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, dev) sms_info( "%02x %02x %02x %02x %02x %02x %02x %02x", ha->addr[0], ha->addr[1], ha->addr[2], ha->addr[3], ha->addr[4], ha->addr[5], ha->addr[6], ha->addr[7] ); } #else sms_info("mc count %d", dev->mc_count); if (dev->mc_count) { struct dev_mc_list *p; for (p = dev->mc_list; p; p = p->next) sms_info( "%d %02x %02x %02x %02x %02x %02x %02x %02x", p->dmi_addrlen, p->dmi_addr[0], p->dmi_addr[1], p->dmi_addr[2], p->dmi_addr[3], p->dmi_addr[4], p->dmi_addr[5], p->dmi_addr[6], p->dmi_addr[7] ); } #endif }
static void set_multicast (struct net_device *dev) { long ioaddr = dev->base_addr; u32 hash_table[2]; u16 rx_mode = 0; struct netdev_private *np = netdev_priv(dev); hash_table[0] = hash_table[1] = 0; /* */ hash_table[1] |= 0x02000000; if (dev->flags & IFF_PROMISC) { /* */ rx_mode = ReceiveAllFrames; } else if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > multicast_filter_limit)) { /* */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; /* */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; netdev_for_each_mc_addr(ha, dev) { int bit, index = 0; int crc = ether_crc_le(ETH_ALEN, ha->addr); /* */ for (bit = 0; bit < 6; bit++) if (crc & (1 << (31 - bit))) index |= (1 << bit); hash_table[index / 32] |= (1 << (index % 32)); } } else {
static void dwmac1000_set_filter(struct net_device *dev) { unsigned long ioaddr = dev->base_addr; unsigned int value = 0; DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", __func__, netdev_mc_count(dev), netdev_uc_count(dev)); if (dev->flags & IFF_PROMISC) value = GMAC_FRAME_FILTER_PR; else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) || (dev->flags & IFF_ALLMULTI)) { value = GMAC_FRAME_FILTER_PM; /* pass all multi */ writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); writel(0xffffffff, ioaddr + GMAC_HASH_LOW); } else if (!netdev_mc_empty(dev)) { u32 mc_filter[2]; struct dev_mc_list *mclist; /* Hash filter for multicast */ value = GMAC_FRAME_FILTER_HMC; memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(mclist, dev) { /* The upper 6 bits of the calculated CRC are used to index the contens of the hash table */ int bit_nr = bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26; /* The most significant bit determines the register to * use (H/L) while the other 5 bits determine the bit * within the register. */ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); }
static void eth_set_mcast_list(struct net_device *dev) { struct port *port = netdev_priv(dev); struct dev_mc_list *mclist; u8 diffs[ETH_ALEN], *addr; int i; if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) { __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN, &port->regs->rx_control[0]); return; } memset(diffs, 0, ETH_ALEN); addr = NULL; netdev_for_each_mc_addr(mclist, dev) { if (!addr) addr = mclist->dmi_addr; /* first MAC address */ for (i = 0; i < ETH_ALEN; i++) diffs[i] |= addr[i] ^ mclist->dmi_addr[i]; } for (i = 0; i < ETH_ALEN; i++) { __raw_writel(addr[i], &port->regs->mcast_addr[i]); __raw_writel(~diffs[i], &port->regs->mcast_mask[i]); } __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN, &port->regs->rx_control[0]); }
static void do_mc32_set_multicast_list(struct net_device *dev, int retry) { struct mc32_local *lp = netdev_priv(dev); u16 filt = (1<<2); /* Save Bad Packets, for stats purposes */ if ((dev->flags&IFF_PROMISC) || (dev->flags&IFF_ALLMULTI) || netdev_mc_count(dev) > 10) /* Enable promiscuous mode */ filt |= 1; else if (!netdev_mc_empty(dev)) { unsigned char block[62]; unsigned char *bp; struct netdev_hw_addr *ha; if(retry==0) lp->mc_list_valid = 0; if(!lp->mc_list_valid) { block[1]=0; block[0]=netdev_mc_count(dev); bp=block+2; netdev_for_each_mc_addr(ha, dev) { memcpy(bp, ha->addr, 6); bp+=6; }
/*********************************************************** * eth_set_multicast_list -- * * Add multicast addresses or set promiscuous mode. * * This function should have been but was not included * * by Marvell. -bbozarth * ***********************************************************/ void mv_eth_set_multicast_list(struct net_device *dev) { mv_eth_priv *priv = MV_ETH_PRIV(dev); int queue = ETH_DEF_RXQ; int i; if (dev->flags & IFF_PROMISC) { mvEthRxFilterModeSet(priv->hal_priv, 1); } else if (dev->flags & IFF_ALLMULTI) { mvEthRxFilterModeSet(priv->hal_priv, 0); mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue); mvEthSetSpecialMcastTable(priv->port, queue); mvEthSetOtherMcastTable(priv->port, queue); } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; mvEthRxFilterModeSet(priv->hal_priv, 0); mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue); netdev_for_each_mc_addr(ha, dev) { mvEthMcastAddrSet(priv->hal_priv, ha->addr, queue); } }
static void usbnet_cdc_update_filter(struct usbnet *dev) { struct cdc_state *info = (void *) &dev->data; struct usb_interface *intf = info->control; struct net_device *net = dev->net; u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED | USB_CDC_PACKET_TYPE_BROADCAST; /* filtering on the device is an optional feature and not worth * the hassle so we just roughly care about snooping and if any * multicast is requested, we take every multicast */ if (net->flags & IFF_PROMISC) cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS; if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST; usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), USB_CDC_SET_ETHERNET_PACKET_FILTER, USB_TYPE_CLASS | USB_RECIP_INTERFACE, cdc_filter, intf->cur_altsetting->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT ); }
void mv_eth_set_multicast_list(struct net_device *dev) { struct eth_port *priv = MV_ETH_PRIV(dev); int rxq = CONFIG_MV_ETH_RXQ_DEF; /* printk("%s - mv_eth_set_multicast_list: flags=0x%x, mc_count=%d\n", dev->name, dev->flags, dev->mc_count); */ if (!mv_eth_pnc_ctrl_en) { printk(KERN_ERR "%s: PNC control is disabled\n", __func__); return; } if (dev->flags & IFF_PROMISC) { /* Accept all */ pnc_mac_me(priv->port, NULL, rxq); pnc_mcast_all(priv->port, 1); } else { /* Accept Unicast to me */ pnc_mac_me(priv->port, dev->dev_addr, rxq); if (dev->flags & IFF_ALLMULTI) { /* Accept all multicast */ pnc_mcast_all(priv->port, 1); } else { /* Accept only initialized Multicast */ pnc_mcast_all(priv->port, 0); pnc_mcast_me(priv->port, NULL); /* Number of entires for all ports is restricted by CONFIG_MV_ETH_PNC_MCAST_NUM */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, dev) { if (pnc_mcast_me(priv->port, ha->addr)) { printk(KERN_ERR "%s: Mcast init failed\n", dev->name); break; } } } #else { struct dev_mc_list *curr_addr = dev->mc_list; int i; for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) { if (!curr_addr) break; if (pnc_mcast_me(priv->port, curr_addr->dmi_addr)) { printk(KERN_ERR "%s: Mcast init failed - %d of %d\n", dev->name, i, dev->mc_count); break; } } } #endif /* KERNEL_VERSION >= 2.6.34 */ } } }
static void elp_set_mc_list(struct net_device *dev) { elp_device *adapter = netdev_priv(dev); struct netdev_hw_addr *ha; int i; unsigned long flags; if (elp_debug >= 3) pr_debug("%s: request to set multicast list\n", dev->name); spin_lock_irqsave(&adapter->lock, flags); if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { /* send a "load multicast list" command to the board, max 10 addrs/cmd */ /* if num_addrs==0 the list will be cleared */ adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; adapter->tx_pcb.length = 6 * netdev_mc_count(dev); i = 0; netdev_for_each_mc_addr(ha, dev) memcpy(adapter->tx_pcb.data.multicast[i++], ha->addr, 6); adapter->got[CMD_LOAD_MULTICAST_LIST] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) pr_err("%s: couldn't send set_multicast command\n", dev->name); else { unsigned long timeout = jiffies + TIMEOUT; while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); } } if (!netdev_mc_empty(dev)) adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI; else /* num_addrs == 0 */ adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; } else adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC; /* * configure adapter to receive messages (as specified above) * and wait for response */ if (elp_debug >= 3) pr_debug("%s: sending 82586 configure command\n", dev->name); adapter->tx_pcb.command = CMD_CONFIGURE_82586; adapter->tx_pcb.length = 2; adapter->got[CMD_CONFIGURE_82586] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) { spin_unlock_irqrestore(&adapter->lock, flags); pr_err("%s: couldn't send 82586 configure command\n", dev->name); } else { unsigned long timeout = jiffies + TIMEOUT; spin_unlock_irqrestore(&adapter->lock, flags); while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) TIMEOUT_MSG(__LINE__); } }
static void temac_set_multicast_list(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); u32 multi_addr_msw, multi_addr_lsw; int i = 0; unsigned long flags; bool promisc_mode_disabled = false; if (ndev->flags & (IFF_PROMISC | IFF_ALLMULTI) || (netdev_mc_count(ndev) > MULTICAST_CAM_TABLE_NUM)) { temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); return; } spin_lock_irqsave(lp->indirect_lock, flags); if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, ndev) { if (WARN_ON(i >= MULTICAST_CAM_TABLE_NUM)) break; multi_addr_msw = ((ha->addr[3] << 24) | (ha->addr[2] << 16) | (ha->addr[1] << 8) | (ha->addr[0])); temac_indirect_out32_locked(lp, XTE_MAW0_OFFSET, multi_addr_msw); multi_addr_lsw = ((ha->addr[5] << 8) | (ha->addr[4]) | (i << 16)); temac_indirect_out32_locked(lp, XTE_MAW1_OFFSET, multi_addr_lsw); i++; } } /* Clear all or remaining/unused address table entries */ while (i < MULTICAST_CAM_TABLE_NUM) { temac_indirect_out32_locked(lp, XTE_MAW0_OFFSET, 0); temac_indirect_out32_locked(lp, XTE_MAW1_OFFSET, i << 16); i++; } /* Enable address filter block if currently disabled */ if (temac_indirect_in32_locked(lp, XTE_AFM_OFFSET) & XTE_AFM_EPPRM_MASK) { temac_indirect_out32_locked(lp, XTE_AFM_OFFSET, 0); promisc_mode_disabled = true; } spin_unlock_irqrestore(lp->indirect_lock, flags); if (promisc_mode_disabled) dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); }
static void int51x1_set_multicast(struct net_device *netdev) { struct usb_ctrlrequest *req; int status; struct urb *urb; struct usbnet *dev = netdev_priv(netdev); u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST; if (netdev->flags & IFF_PROMISC) { /* */ filter |= PACKET_TYPE_PROMISCUOUS; netdev_info(dev->net, "promiscuous mode enabled\n"); } else if (!netdev_mc_empty(netdev) || (netdev->flags & IFF_ALLMULTI)) { filter |= PACKET_TYPE_ALL_MULTICAST; netdev_dbg(dev->net, "receive all multicast enabled\n"); } else { /* */ netdev_dbg(dev->net, "receive own packets only\n"); } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { netdev_warn(dev->net, "Error allocating URB\n"); return; } req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) { netdev_warn(dev->net, "Error allocating control msg\n"); goto out; } req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; req->bRequest = SET_ETHERNET_PACKET_FILTER; req->wValue = cpu_to_le16(filter); req->wIndex = 0; req->wLength = 0; usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (void *)req, NULL, 0, int51x1_async_cmd_callback, (void *)req); status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { netdev_warn(dev->net, "Error submitting control msg, sts=%d\n", status); goto out1; } return; out1: kfree(req); out: usb_free_urb(urb); }
/** * cvm_oct_common_set_multicast_list - set the multicast list * @dev: Device to work on */ static void cvm_oct_common_set_multicast_list(struct net_device *dev) { union cvmx_gmxx_prtx_cfg gmx_cfg; struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); int index = INDEX(priv->port); if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { union cvmx_gmxx_rxx_adr_ctl control; control.u64 = 0; control.s.bcst = 1; /* Allow broadcast MAC addresses */ if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) /* Force accept multicast packets */ control.s.mcst = 2; else /* Force reject multicast packets */ control.s.mcst = 1; if (dev->flags & IFF_PROMISC) /* * Reject matches if promisc. Since CAM is * shut off, should accept everything. */ control.s.cam_mode = 0; else /* Filter packets based on the CAM */ control.s.cam_mode = 1; gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64 & ~1ull); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), control.u64); if (dev->flags & IFF_PROMISC) cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN (index, interface), 0); else cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN (index, interface), 1); cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); } }
/* * Set or clear promiscuous/multicast mode filter for this adaptor. * * We don't attempt any packet filtering. The card may have a SEEQ 8004 * in which does not have the other ethernet address registers present... */ static void ether3_setmulticastlist(struct net_device *dev) { priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC; if (dev->flags & IFF_PROMISC) { /* promiscuous mode */ priv(dev)->regs.config1 |= CFG1_RECVPROMISC; } else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; } else priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); }
/* Number of entires for all ports is restricted by CONFIG_MV_ETH_PNC_MCAST_NUM */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, dev) { if (pnc_mcast_me(priv->port, ha->addr)) { printk(KERN_ERR "%s: Mcast init failed\n", dev->name); break; } } } #else { struct dev_mc_list *curr_addr = dev->mc_list; int i; for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) { if (!curr_addr) break; if (pnc_mcast_me(priv->port, curr_addr->dmi_addr)) { printk(KERN_ERR "%s: Mcast init failed - %d of %d\n", dev->name, i, dev->mc_count); break; } } } #endif /* KERNEL_VERSION >= 2.6.34 */ } } } #else /* !CONFIG_MV_ETH_PNC - legacy parser */ void mv_eth_set_multicast_list(struct net_device *dev) { struct eth_port *priv = MV_ETH_PRIV(dev); int queue = CONFIG_MV_ETH_RXQ_DEF; if (dev->flags & IFF_PROMISC) { /* Accept all: Multicast + Unicast */ mvNetaRxUnicastPromiscSet(priv->port, MV_TRUE); mvNetaSetUcastTable(priv->port, queue); mvNetaSetSpecialMcastTable(priv->port, queue); mvNetaSetOtherMcastTable(priv->port, queue); } else { /* Accept single Unicast */ mvNetaRxUnicastPromiscSet(priv->port, MV_FALSE); mvNetaSetUcastTable(priv->port, -1); if (mvNetaMacAddrSet(priv->port, dev->dev_addr, queue) != MV_OK) printk(KERN_ERR "%s: netaSetMacAddr failed\n", dev->name); if (dev->flags & IFF_ALLMULTI) { /* Accept all Multicast */ mvNetaSetSpecialMcastTable(priv->port, queue); mvNetaSetOtherMcastTable(priv->port, queue); } else { /* Accept only initialized Multicast */ mvNetaSetSpecialMcastTable(priv->port, -1); mvNetaSetOtherMcastTable(priv->port, -1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, dev) { mvNetaMcastAddrSet(priv->port, ha->addr, queue); } } #else { struct dev_mc_list *curr_addr = dev->mc_list; int i; for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) { if (!curr_addr) break; mvNetaMcastAddrSet(priv->port, curr_addr->dmi_addr, queue); } } #endif /* KERNEL_VERSION >= 2.6.34 */ } }
static void set_multicast_list(struct net_device *dev) { int ioaddr = dev->base_addr; if (dev->flags & IFF_PROMISC) { outb(RX_PROM, RX_CMD); inb(RX_STATUS); } else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) { /* Multicast or all multicast is the same */ outb(RX_MULT, RX_CMD); inb(RX_STATUS); /* Clear status. */ } else { outb(RX_NORM, RX_CMD); inb(RX_STATUS); } }
static void dwmac100_set_filter(struct mac_device_info *hw, struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; u32 value = readl(ioaddr + MAC_CONTROL); if (dev->flags & IFF_PROMISC) { value |= MAC_CONTROL_PR; value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) || (dev->flags & IFF_ALLMULTI)) { value |= MAC_CONTROL_PM; value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); writel(0xffffffff, ioaddr + MAC_HASH_HIGH); writel(0xffffffff, ioaddr + MAC_HASH_LOW); } else if (netdev_mc_empty(dev)) { /* no multicast */ value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else { u32 mc_filter[2]; struct netdev_hw_addr *ha; /* Perfect filter mode for physical address and Hash * filter for multicast */ value |= MAC_CONTROL_HP; value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(ha, dev) { /* The upper 6 bits of the calculated CRC are used to * index the contens of the hash table */ int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; /* The most significant bit determines the register to * use (H/L) while the other 5 bits determine the bit * within the register. */ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); } writel(mc_filter[0], ioaddr + MAC_HASH_LOW); writel(mc_filter[1], ioaddr + MAC_HASH_HIGH); }
static void sgiseeq_set_multicast(struct net_device *dev) { struct sgiseeq_private *sp = netdev_priv(dev); unsigned char oldmode = sp->mode; if(dev->flags & IFF_PROMISC) sp->mode = SEEQ_RCMD_RANY; else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) sp->mode = SEEQ_RCMD_RBMCAST; else sp->mode = SEEQ_RCMD_RBCAST; /* XXX I know this sucks, but is there a better way to reprogram * XXX the receiver? At least, this shouldn't happen too often. */ if (oldmode != sp->mode) sgiseeq_reset(dev); }
/** * axienet_set_multicast_list - Prepare the multicast table * @ndev: Pointer to the net_device structure * * This function is called to initialize the multicast table during * initialization. The Axi Ethernet basic multicast support has a four-entry * multicast table which is initialized here. Additionally this function * goes into the net_device_ops structure entry ndo_set_multicast_list. This * means whenever the multicast table entries need to be updated this * function gets called. */ static void axienet_set_multicast_list(struct net_device *ndev) { int i; u32 reg, af0reg, af1reg; struct axienet_local *lp = netdev_priv(ndev); if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) || netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) { /* We must make the kernel realize we had to move into * promiscuous mode. If it was a promiscuous mode request * the flag is already set. If not we set it. */ ndev->flags |= IFF_PROMISC; reg = axienet_ior(lp, XAE_FMI_OFFSET); reg |= XAE_FMI_PM_MASK; axienet_iow(lp, XAE_FMI_OFFSET, reg); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; i = 0; netdev_for_each_mc_addr(ha, ndev) { if (i >= XAE_MULTICAST_CAM_TABLE_NUM) break; af0reg = (ha->addr[0]); af0reg |= (ha->addr[1] << 8); af0reg |= (ha->addr[2] << 16); af0reg |= (ha->addr[3] << 24); af1reg = (ha->addr[4]); af1reg |= (ha->addr[5] << 8); reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; reg |= i; axienet_iow(lp, XAE_FMI_OFFSET, reg); axienet_iow(lp, XAE_AF0_OFFSET, af0reg); axienet_iow(lp, XAE_AF1_OFFSET, af1reg); i++; } } else {
static void cpsw_ndo_set_rx_mode(struct net_device *ndev) { struct cpsw_priv *priv = netdev_priv(ndev); if (ndev->flags & IFF_PROMISC) { /* Enable promiscuous mode */ dev_err(priv->dev, "Ignoring Promiscuous mode\n"); return; } /* Clear all mcast from ALE */ cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; /* program multicast address list into ALE register */ netdev_for_each_mc_addr(ha, ndev) { cpsw_add_mcast(priv, (u8 *)ha->addr); } }
static void set_multicast_list(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); if(dev->flags&IFF_PROMISC) { lp->rx_mode = RX_ALL_ACCEPT; } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { /* The multicast-accept list is initialized to accept-all, and we rely on higher-level filtering for now. */ lp->rx_mode = RX_MULTCAST_ACCEPT; } else lp->rx_mode = 0; writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode); /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */ writereg(dev, PP_RxCFG, lp->curr_rx_cfg | (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0)); }
static void dwmac1000_set_filter(struct mac_device_info *hw, struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; unsigned int value = 0; unsigned int perfect_addr_number = hw->unicast_filter_entries; u32 mc_filter[8]; int mcbitslog2 = hw->mcast_bits_log2; pr_debug("%s: # mcasts %d, # unicast %d\n", __func__, netdev_mc_count(dev), netdev_uc_count(dev)); memset(mc_filter, 0, sizeof(mc_filter)); if (dev->flags & IFF_PROMISC) { value = GMAC_FRAME_FILTER_PR; } else if (dev->flags & IFF_ALLMULTI) { value = GMAC_FRAME_FILTER_PM; /* pass all multi */ } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; /* Hash filter for multicast */ value = GMAC_FRAME_FILTER_HMC; netdev_for_each_mc_addr(ha, dev) { /* The upper n bits of the calculated CRC are used to * index the contents of the hash table. The number of * bits used depends on the hardware configuration * selected at core configuration time. */ int bit_nr = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN)) >> (32 - mcbitslog2); /* The most significant bit determines the register to * use (H/L) while the other 5 bits determine the bit * within the register. */ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); } }
static void dm9601_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); u8 *hashes = (u8 *) & dev->data; u8 rx_ctl = 0x31; memset(hashes, 0x00, DM_MCAST_SIZE); hashes[DM_MCAST_SIZE - 1] |= 0x80; if (net->flags & IFF_PROMISC) { rx_ctl |= 0x02; } else if (net->flags & IFF_ALLMULTI || netdev_mc_count(net) > DM_MAX_MCAST) { rx_ctl |= 0x04; } else if (!netdev_mc_empty(net)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, net) { u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } }
static void temac_set_multicast_list(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); u32 multi_addr_msw, multi_addr_lsw, val; int i; mutex_lock(&lp->indirect_mutex); if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) || netdev_mc_count(ndev) > MULTICAST_CAM_TABLE_NUM) { /* * We must make the kernel realise we had to move * into promisc mode or we start all out war on * the cable. If it was a promisc request the * flag is already set. If not we assert it. */ ndev->flags |= IFF_PROMISC; temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; i = 0; netdev_for_each_mc_addr(ha, ndev) { if (i >= MULTICAST_CAM_TABLE_NUM) break; multi_addr_msw = ((ha->addr[3] << 24) | (ha->addr[2] << 16) | (ha->addr[1] << 8) | (ha->addr[0])); temac_indirect_out32(lp, XTE_MAW0_OFFSET, multi_addr_msw); multi_addr_lsw = ((ha->addr[5] << 8) | (ha->addr[4]) | (i << 16)); temac_indirect_out32(lp, XTE_MAW1_OFFSET, multi_addr_lsw); i++; } } else {
static void dwmac4_set_filter(struct mac_device_info *hw, struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; unsigned int value = 0; if (dev->flags & IFF_PROMISC) { value = GMAC_PACKET_FILTER_PR | GMAC_PACKET_FILTER_PCF; } else if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > HASH_TABLE_SIZE)) { /* Pass all multi */ value = GMAC_PACKET_FILTER_PM; /* Set the 64 bits of the HASH tab. To be updated if taller * hash table is used */ writel(0xffffffff, ioaddr + GMAC_HASH_TAB_0_31); writel(0xffffffff, ioaddr + GMAC_HASH_TAB_32_63); } else if (!netdev_mc_empty(dev)) { u32 mc_filter[2]; struct netdev_hw_addr *ha; /* Hash filter for multicast */ value = GMAC_PACKET_FILTER_HMC; memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(ha, dev) { /* The upper 6 bits of the calculated CRC are used to * index the content of the Hash Table Reg 0 and 1. */ int bit_nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26); /* The most significant bit determines the register * to use while the other 5 bits determines the bit * within the selected register */ mc_filter[bit_nr >> 5] |= (1 << (bit_nr & 0x1F)); }
static void aqc111_set_rx_mode(struct net_device *net) { struct usbnet *dev = netdev_priv(net); struct aqc111_data *aqc111_data = dev->driver_priv; int mc_count = 0; mc_count = netdev_mc_count(net); aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL | SFR_RX_CTL_AM); if (net->flags & IFF_PROMISC) { aqc111_data->rxctl |= SFR_RX_CTL_PRO; } else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) { aqc111_data->rxctl |= SFR_RX_CTL_AMALL; } else if (!netdev_mc_empty(net)) { u8 m_filter[AQ_MCAST_FILTER_SIZE] = { 0 }; struct netdev_hw_addr *ha = NULL; u32 crc_bits = 0; netdev_for_each_mc_addr(ha, net) { crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; m_filter[crc_bits >> 3] |= BIT(crc_bits & 7); }
static void dm9601_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); /* We use the 20 byte dev->data for our 8 byte filter buffer * to avoid allocating memory that is tricky to free later */ u8 *hashes = (u8 *) & dev->data; u8 rx_ctl = 0x31; memset(hashes, 0x00, DM_MCAST_SIZE); hashes[DM_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ if (net->flags & IFF_PROMISC) { rx_ctl |= 0x02; } else if (net->flags & IFF_ALLMULTI || netdev_mc_count(net) > DM_MAX_MCAST) { rx_ctl |= 0x08; } else if (!netdev_mc_empty(net)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, net) { u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } }