From 0a9627f2649a02bea165cfd529d7bcb625c2fcad Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 16 Mar 2010 08:03:29 +0000 Subject: rps: Receive Packet Steering This patch implements software receive side packet steering (RPS). RPS distributes the load of received packet processing across multiple CPUs. Problem statement: Protocol processing done in the NAPI context for received packets is serialized per device queue and becomes a bottleneck under high packet load. This substantially limits pps that can be achieved on a single queue NIC and provides no scaling with multiple cores. This solution queues packets early on in the receive path on the backlog queues of other CPUs. This allows protocol processing (e.g. IP and TCP) to be performed on packets in parallel. For each device (or each receive queue in a multi-queue device) a mask of CPUs is set to indicate the CPUs that can process packets. A CPU is selected on a per packet basis by hashing contents of the packet header (e.g. the TCP or UDP 4-tuple) and using the result to index into the CPU mask. The IPI mechanism is used to raise networking receive softirqs between CPUs. This effectively emulates in software what a multi-queue NIC can provide, but is generic requiring no device support. Many devices now provide a hash over the 4-tuple on a per packet basis (e.g. the Toeplitz hash). This patch allow drivers to set the HW reported hash in an skb field, and that value in turn is used to index into the RPS maps. Using the HW generated hash can avoid cache misses on the packet when steering it to a remote CPU. The CPU mask is set on a per device and per queue basis in the sysfs variable /sys/class/net//queues/rx-/rps_cpus. This is a set of canonical bit maps for receive queues in the device (numbered by ). If a device does not support multi-queue, a single variable is used for the device (rx-0). Generally, we have found this technique increases pps capabilities of a single queue device with good CPU utilization. Optimal settings for the CPU mask seem to depend on architectures and cache hierarcy. Below are some results running 500 instances of netperf TCP_RR test with 1 byte req. and resp. Results show cumulative transaction rate and system CPU utilization. e1000e on 8 core Intel Without RPS: 108K tps at 33% CPU With RPS: 311K tps at 64% CPU forcedeth on 16 core AMD Without RPS: 156K tps at 15% CPU With RPS: 404K tps at 49% CPU bnx2x on 16 core AMD Without RPS 567K tps at 61% CPU (4 HW RX queues) Without RPS 738K tps at 96% CPU (8 HW RX queues) With RPS: 854K tps at 76% CPU (4 HW RX queues) Caveats: - The benefits of this patch are dependent on architecture and cache hierarchy. Tuning the masks to get best performance is probably necessary. - This patch adds overhead in the path for processing a single packet. In a lightly loaded server this overhead may eliminate the advantages of increased parallelism, and possibly cause some relative performance degradation. We have found that masks that are cache aware (share same caches with the interrupting CPU) mitigate much of this. - The RPS masks can be changed dynamically, however whenever the mask is changed this introduces the possibility of generating out of order packets. It's probably best not change the masks too frequently. Signed-off-by: Tom Herbert include/linux/netdevice.h | 32 ++++- include/linux/skbuff.h | 3 + net/core/dev.c | 335 +++++++++++++++++++++++++++++++++++++-------- net/core/net-sysfs.c | 225 ++++++++++++++++++++++++++++++- net/core/skbuff.c | 2 + 5 files changed, 538 insertions(+), 59 deletions(-) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c79a88be7c3..de1a52bcb9e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -223,6 +223,7 @@ struct netif_rx_stats { unsigned dropped; unsigned time_squeeze; unsigned cpu_collision; + unsigned received_rps; }; DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); @@ -530,6 +531,24 @@ struct netdev_queue { unsigned long tx_dropped; } ____cacheline_aligned_in_smp; +/* + * This structure holds an RPS map which can be of variable length. The + * map is an array of CPUs. + */ +struct rps_map { + unsigned int len; + struct rcu_head rcu; + u16 cpus[0]; +}; +#define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16))) + +/* This structure contains an instance of an RX queue. */ +struct netdev_rx_queue { + struct rps_map *rps_map; + struct kobject kobj; + struct netdev_rx_queue *first; + atomic_t count; +} ____cacheline_aligned_in_smp; /* * This structure defines the management hooks for network devices. @@ -878,6 +897,13 @@ struct net_device { unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ + struct kset *queues_kset; + + struct netdev_rx_queue *_rx; + + /* Number of RX queues allocated at alloc_netdev_mq() time */ + unsigned int num_rx_queues; + struct netdev_queue rx_queue; struct netdev_queue *_tx ____cacheline_aligned_in_smp; @@ -1311,14 +1337,16 @@ static inline int unregister_gifconf(unsigned int family) */ struct softnet_data { struct Qdisc *output_queue; - struct sk_buff_head input_pkt_queue; struct list_head poll_list; struct sk_buff *completion_queue; + /* Elements below can be accessed between CPUs for RPS */ + struct call_single_data csd ____cacheline_aligned_in_smp; + struct sk_buff_head input_pkt_queue; struct napi_struct backlog; }; -DECLARE_PER_CPU(struct softnet_data,softnet_data); +DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); #define HAVE_NETIF_QUEUE -- cgit v1.2.3 From 1e94d72feab025b8f7c55d07020602f82f3a97dd Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Thu, 18 Mar 2010 17:45:44 -0700 Subject: rps: Fixed build with CONFIG_SMP not enabled. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index de1a52bcb9e..726ecd1af53 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1341,7 +1341,9 @@ struct softnet_data { struct sk_buff *completion_queue; /* Elements below can be accessed between CPUs for RPS */ +#ifdef CONFIG_SMP struct call_single_data csd ____cacheline_aligned_in_smp; +#endif struct sk_buff_head input_pkt_queue; struct napi_struct backlog; }; diff --git a/net/core/dev.c b/net/core/dev.c index 17b16867150..1a7e1d1d5ad 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2174,6 +2174,7 @@ int weight_p __read_mostly = 64; /* old backlog weight */ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; +#ifdef CONFIG_SMP /* * get_rps_cpu is called from netif_receive_skb and returns the target * CPU from the RPS map of the receiving queue for a given skb. @@ -2293,6 +2294,7 @@ static void trigger_softirq(void *data) __napi_schedule(&queue->backlog); __get_cpu_var(netdev_rx_stat).received_rps++; } +#endif /* CONFIG_SMP */ /* * enqueue_to_backlog is called to queue an skb to a per CPU backlog @@ -2320,6 +2322,7 @@ enqueue: /* Schedule NAPI for backlog device */ if (napi_schedule_prep(&queue->backlog)) { +#ifdef CONFIG_SMP if (cpu != smp_processor_id()) { struct rps_remote_softirq_cpus *rcpus = &__get_cpu_var(rps_remote_softirq_cpus); @@ -2328,6 +2331,9 @@ enqueue: __raise_softirq_irqoff(NET_RX_SOFTIRQ); } else __napi_schedule(&queue->backlog); +#else + __napi_schedule(&queue->backlog); +#endif } goto enqueue; } @@ -2367,9 +2373,13 @@ int netif_rx(struct sk_buff *skb) if (!skb->tstamp.tv64) net_timestamp(skb); +#ifdef CONFIG_SMP cpu = get_rps_cpu(skb->dev, skb); if (cpu < 0) cpu = smp_processor_id(); +#else + cpu = smp_processor_id(); +#endif return enqueue_to_backlog(skb, cpu); } @@ -2735,6 +2745,7 @@ out: */ int netif_receive_skb(struct sk_buff *skb) { +#ifdef CONFIG_SMP int cpu; cpu = get_rps_cpu(skb->dev, skb); @@ -2743,6 +2754,9 @@ int netif_receive_skb(struct sk_buff *skb) return __netif_receive_skb(skb); else return enqueue_to_backlog(skb, cpu); +#else + return __netif_receive_skb(skb); +#endif } EXPORT_SYMBOL(netif_receive_skb); @@ -3168,6 +3182,7 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); +#ifdef CONFIG_SMP /* * net_rps_action sends any pending IPI's for rps. This is only called from * softirq and interrupts must be enabled. @@ -3184,6 +3199,7 @@ static void net_rps_action(cpumask_t *mask) } cpus_clear(*mask); } +#endif static void net_rx_action(struct softirq_action *h) { @@ -3191,8 +3207,10 @@ static void net_rx_action(struct softirq_action *h) unsigned long time_limit = jiffies + 2; int budget = netdev_budget; void *have; +#ifdef CONFIG_SMP int select; struct rps_remote_softirq_cpus *rcpus; +#endif local_irq_disable(); @@ -3255,6 +3273,7 @@ static void net_rx_action(struct softirq_action *h) netpoll_poll_unlock(have); } out: +#ifdef CONFIG_SMP rcpus = &__get_cpu_var(rps_remote_softirq_cpus); select = rcpus->select; rcpus->select ^= 1; @@ -3262,6 +3281,9 @@ out: local_irq_enable(); net_rps_action(&rcpus->mask[select]); +#else + local_irq_enable(); +#endif #ifdef CONFIG_NET_DMA /* @@ -6204,9 +6226,11 @@ static int __init net_dev_init(void) queue->completion_queue = NULL; INIT_LIST_HEAD(&queue->poll_list); +#ifdef CONFIG_SMP queue->csd.func = trigger_softirq; queue->csd.info = queue; queue->csd.flags = 0; +#endif queue->backlog.poll = process_backlog; queue->backlog.weight = weight_p; -- cgit v1.2.3 From 3ca5b4042ecae5e73c59de62e4ac0db31c10e0f8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 10 Mar 2010 10:29:35 +0000 Subject: bonding: check return value of nofitier when changing type This patch adds the possibility to refuse the bonding type change for other subsystems (such as for example bridge, vlan, etc.) Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 11 +++++++++-- include/linux/netdevice.h | 2 +- net/core/dev.c | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7eeb18751d6..cbe9e353d46 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1480,8 +1480,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_dev->name, bond_dev->type, slave_dev->type); - netdev_bonding_change(bond_dev, - NETDEV_PRE_TYPE_CHANGE); + res = netdev_bonding_change(bond_dev, + NETDEV_PRE_TYPE_CHANGE); + res = notifier_to_errno(res); + if (res) { + pr_err("%s: refused to change device type\n", + bond_dev->name); + res = -EBUSY; + goto err_undo_flags; + } if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 726ecd1af53..813bed723f5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2005,7 +2005,7 @@ extern void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct extern int dev_set_promiscuity(struct net_device *dev, int inc); extern int dev_set_allmulti(struct net_device *dev, int inc); extern void netdev_state_change(struct net_device *dev); -extern void netdev_bonding_change(struct net_device *dev, +extern int netdev_bonding_change(struct net_device *dev, unsigned long event); extern void netdev_features_change(struct net_device *dev); /* Load a device via the kmod */ diff --git a/net/core/dev.c b/net/core/dev.c index 1a7e1d1d5ad..d1f027c41e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1084,9 +1084,9 @@ void netdev_state_change(struct net_device *dev) } EXPORT_SYMBOL(netdev_state_change); -void netdev_bonding_change(struct net_device *dev, unsigned long event) +int netdev_bonding_change(struct net_device *dev, unsigned long event) { - call_netdevice_notifiers(event, dev); + return call_netdevice_notifiers(event, dev); } EXPORT_SYMBOL(netdev_bonding_change); -- cgit v1.2.3 From 32a806c194ea112cfab00f558482dd97bee5e44e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 19 Mar 2010 04:00:23 +0000 Subject: bonding: flush unicast and multicast lists when changing type After the type change, addresses in unicast and multicast lists wouldn't make sense, not to mention possible different lenghts. So flush both lists here. Note "dev_addr_discard" will be very soon replaced by "dev_mc_flush" (once mc_list conversion will be done). Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++++ include/linux/netdevice.h | 2 ++ net/core/dev.c | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index cbe9e353d46..c2aceaab014 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1490,6 +1490,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } + /* Flush unicast and multicast addresses */ + dev_unicast_flush(bond_dev); + dev_addr_discard(bond_dev); + if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); else diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9fc6ee8e750..c96c41e08e3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1994,10 +1994,12 @@ extern int dev_unicast_delete(struct net_device *dev, void *addr); extern int dev_unicast_add(struct net_device *dev, void *addr); extern int dev_unicast_sync(struct net_device *to, struct net_device *from); extern void dev_unicast_unsync(struct net_device *to, struct net_device *from); +extern void dev_unicast_flush(struct net_device *dev); extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); extern int dev_mc_sync(struct net_device *to, struct net_device *from); extern void dev_mc_unsync(struct net_device *to, struct net_device *from); +extern void dev_addr_discard(struct net_device *dev); extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all); extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly); extern int __dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count); diff --git a/net/core/dev.c b/net/core/dev.c index c0e260870c0..fe2a754238a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4457,12 +4457,13 @@ void dev_unicast_unsync(struct net_device *to, struct net_device *from) } EXPORT_SYMBOL(dev_unicast_unsync); -static void dev_unicast_flush(struct net_device *dev) +void dev_unicast_flush(struct net_device *dev) { netif_addr_lock_bh(dev); __hw_addr_flush(&dev->uc); netif_addr_unlock_bh(dev); } +EXPORT_SYMBOL(dev_unicast_flush); static void dev_unicast_init(struct net_device *dev) { @@ -4484,7 +4485,7 @@ static void __dev_addr_discard(struct dev_addr_list **list) } } -static void dev_addr_discard(struct net_device *dev) +void dev_addr_discard(struct net_device *dev) { netif_addr_lock_bh(dev); @@ -4493,6 +4494,7 @@ static void dev_addr_discard(struct net_device *dev) netif_addr_unlock_bh(dev); } +EXPORT_SYMBOL(dev_addr_discard); /** * dev_get_flags - get flags reported to userspace -- cgit v1.2.3 From df3345457a7a174dfb5872a070af80d456985038 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 24 Mar 2010 19:13:54 +0000 Subject: rps: add CONFIG_RPS RPS currently depends on SMP and SYSFS Adding a CONFIG_RPS makes sense in case this requirement changes in the future. This patch saves about 1500 bytes of kernel text in case SMP is on but SYSFS is off. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++++ net/Kconfig | 5 +++++ net/core/dev.c | 29 +++++++++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c96c41e08e3..53c272f2a73 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -531,6 +531,7 @@ struct netdev_queue { unsigned long tx_dropped; } ____cacheline_aligned_in_smp; +#ifdef CONFIG_RPS /* * This structure holds an RPS map which can be of variable length. The * map is an array of CPUs. @@ -549,6 +550,7 @@ struct netdev_rx_queue { struct netdev_rx_queue *first; atomic_t count; } ____cacheline_aligned_in_smp; +#endif /* * This structure defines the management hooks for network devices. @@ -897,12 +899,14 @@ struct net_device { unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ +#ifdef CONFIG_RPS struct kset *queues_kset; struct netdev_rx_queue *_rx; /* Number of RX queues allocated at alloc_netdev_mq() time */ unsigned int num_rx_queues; +#endif struct netdev_queue rx_queue; diff --git a/net/Kconfig b/net/Kconfig index 041c35edb76..68514644ce9 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -203,6 +203,11 @@ source "net/ieee802154/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig" +config RPS + boolean + depends on SMP && SYSFS + default y + menu "Network testing" config NET_PKTGEN diff --git a/net/core/dev.c b/net/core/dev.c index 5e3dc28cbf5..bcb3ed26af1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2177,7 +2177,7 @@ int weight_p __read_mostly = 64; /* old backlog weight */ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS /* * get_rps_cpu is called from netif_receive_skb and returns the target * CPU from the RPS map of the receiving queue for a given skb. @@ -2325,7 +2325,7 @@ enqueue: /* Schedule NAPI for backlog device */ if (napi_schedule_prep(&queue->backlog)) { -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS if (cpu != smp_processor_id()) { struct rps_remote_softirq_cpus *rcpus = &__get_cpu_var(rps_remote_softirq_cpus); @@ -2376,7 +2376,7 @@ int netif_rx(struct sk_buff *skb) if (!skb->tstamp.tv64) net_timestamp(skb); -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS cpu = get_rps_cpu(skb->dev, skb); if (cpu < 0) cpu = smp_processor_id(); @@ -2750,7 +2750,7 @@ out: */ int netif_receive_skb(struct sk_buff *skb) { -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS int cpu; cpu = get_rps_cpu(skb->dev, skb); @@ -3189,7 +3189,7 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS /* * net_rps_action sends any pending IPI's for rps. This is only called from * softirq and interrupts must be enabled. @@ -3214,7 +3214,7 @@ static void net_rx_action(struct softirq_action *h) unsigned long time_limit = jiffies + 2; int budget = netdev_budget; void *have; -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS int select; struct rps_remote_softirq_cpus *rcpus; #endif @@ -3280,7 +3280,7 @@ static void net_rx_action(struct softirq_action *h) netpoll_poll_unlock(have); } out: -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS rcpus = &__get_cpu_var(rps_remote_softirq_cpus); select = rcpus->select; rcpus->select ^= 1; @@ -5277,6 +5277,7 @@ int register_netdevice(struct net_device *dev) dev->iflink = -1; +#ifdef CONFIG_RPS if (!dev->num_rx_queues) { /* * Allocate a single RX queue if driver never called @@ -5293,7 +5294,7 @@ int register_netdevice(struct net_device *dev) atomic_set(&dev->_rx->count, 1); dev->num_rx_queues = 1; } - +#endif /* Init, if this function is available */ if (dev->netdev_ops->ndo_init) { ret = dev->netdev_ops->ndo_init(dev); @@ -5653,11 +5654,13 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, void (*setup)(struct net_device *), unsigned int queue_count) { struct netdev_queue *tx; - struct netdev_rx_queue *rx; struct net_device *dev; size_t alloc_size; struct net_device *p; +#ifdef CONFIG_RPS + struct netdev_rx_queue *rx; int i; +#endif BUG_ON(strlen(name) >= sizeof(dev->name)); @@ -5683,6 +5686,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, goto free_p; } +#ifdef CONFIG_RPS rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL); if (!rx) { printk(KERN_ERR "alloc_netdev: Unable to allocate " @@ -5698,6 +5702,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, */ for (i = 0; i < queue_count; i++) rx[i].first = rx; +#endif dev = PTR_ALIGN(p, NETDEV_ALIGN); dev->padded = (char *)dev - (char *)p; @@ -5713,8 +5718,10 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, dev->num_tx_queues = queue_count; dev->real_num_tx_queues = queue_count; +#ifdef CONFIG_RPS dev->_rx = rx; dev->num_rx_queues = queue_count; +#endif dev->gso_max_size = GSO_MAX_SIZE; @@ -5731,8 +5738,10 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, return dev; free_rx: +#ifdef CONFIG_RPS kfree(rx); free_tx: +#endif kfree(tx); free_p: kfree(p); @@ -6236,7 +6245,7 @@ static int __init net_dev_init(void) queue->completion_queue = NULL; INIT_LIST_HEAD(&queue->poll_list); -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS queue->csd.func = trigger_softirq; queue->csd.info = queue; queue->csd.flags = 0; -- cgit v1.2.3 From b00fabb4020d17bda4bea59507e09fadf573088d Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 29 Mar 2010 14:47:27 +0000 Subject: netdev: ethtool RXHASH flag This adds ethtool and device feature flag to allow control of receive hashing offload. Signed-off-by: Stephen Hemminger Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 + include/linux/netdevice.h | 1 + net/core/ethtool.c | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index b33f316bb92..b391969a0dd 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -310,6 +310,7 @@ struct ethtool_perm_addr { enum ethtool_flags { ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ + ETH_FLAG_RXHASH = (1 << 28), }; /* The following structures are for supporting RX network flow diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 53c272f2a73..b5670ab5107 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -785,6 +785,7 @@ struct net_device { #define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ #define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/ #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ +#define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 diff --git a/net/core/ethtool.c b/net/core/ethtool.c index f4cb6b6299d..73c81edde8d 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -121,7 +121,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data) * NETIF_F_xxx values in include/linux/netdevice.h */ static const u32 flags_dup_features = - (ETH_FLAG_LRO | ETH_FLAG_NTUPLE); + (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH); u32 ethtool_op_get_flags(struct net_device *dev) { @@ -152,6 +152,11 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data) features &= ~NETIF_F_NTUPLE; } + if (data & ETH_FLAG_RXHASH) + features |= NETIF_F_RXHASH; + else + features &= ~NETIF_F_RXHASH; + dev->features = features; return 0; } -- cgit v1.2.3 From a748ee2426817a95b1f03012d8f339c45c722ae1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Apr 2010 21:22:09 +0000 Subject: net: move address list functions to a separate file +little renaming of unicast functions to be smooth with multicast ones Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- drivers/net/macvlan.c | 10 +- drivers/scsi/fcoe/fcoe.c | 14 +- include/linux/netdevice.h | 15 +- net/8021q/vlan.c | 4 +- net/8021q/vlan_dev.c | 14 +- net/core/Makefile | 3 +- net/core/dev.c | 430 +----------------------------------- net/core/dev_addr_lists.c | 478 ++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 14 +- net/packet/af_packet.c | 4 +- 11 files changed, 524 insertions(+), 464 deletions(-) create mode 100644 net/core/dev_addr_lists.c (limited to 'include/linux/netdevice.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f8ab60b914c..d6ae63b2cf0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1491,7 +1491,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } /* Flush unicast and multicast addresses */ - dev_unicast_flush(bond_dev); + dev_uc_flush(bond_dev); dev_addr_discard(bond_dev); if (slave_dev->type != ARPHRD_ETHER) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 445e73c343b..9a939d828b4 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -282,7 +282,7 @@ static int macvlan_open(struct net_device *dev) if (macvlan_addr_busy(vlan->port, dev->dev_addr)) goto out; - err = dev_unicast_add(lowerdev, dev->dev_addr); + err = dev_uc_add(lowerdev, dev->dev_addr); if (err < 0) goto out; if (dev->flags & IFF_ALLMULTI) { @@ -294,7 +294,7 @@ static int macvlan_open(struct net_device *dev) return 0; del_unicast: - dev_unicast_delete(lowerdev, dev->dev_addr); + dev_uc_del(lowerdev, dev->dev_addr); out: return err; } @@ -308,7 +308,7 @@ static int macvlan_stop(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(lowerdev, -1); - dev_unicast_delete(lowerdev, dev->dev_addr); + dev_uc_del(lowerdev, dev->dev_addr); macvlan_hash_del(vlan); return 0; @@ -332,11 +332,11 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p) if (macvlan_addr_busy(vlan->port, addr->sa_data)) return -EBUSY; - err = dev_unicast_add(lowerdev, addr->sa_data); + err = dev_uc_add(lowerdev, addr->sa_data); if (err) return err; - dev_unicast_delete(lowerdev, dev->dev_addr); + dev_uc_del(lowerdev, dev->dev_addr); macvlan_hash_change_addr(vlan, addr->sa_data); } diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 2f47ae7cce9..de33e38a405 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -308,9 +308,9 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, * for multiple unicast MACs. */ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); - dev_unicast_add(netdev, flogi_maddr); + dev_uc_add(netdev, flogi_maddr); if (fip->spma) - dev_unicast_add(netdev, fip->ctl_src_addr); + dev_uc_add(netdev, fip->ctl_src_addr); dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); /* @@ -394,9 +394,9 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) /* Delete secondary MAC addresses */ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); - dev_unicast_delete(netdev, flogi_maddr); + dev_uc_del(netdev, flogi_maddr); if (fip->spma) - dev_unicast_delete(netdev, fip->ctl_src_addr); + dev_uc_del(netdev, fip->ctl_src_addr); dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); /* Tell the LLD we are done w/ FCoE */ @@ -490,9 +490,9 @@ static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) rtnl_lock(); if (!is_zero_ether_addr(port->data_src_addr)) - dev_unicast_delete(fcoe->netdev, port->data_src_addr); + dev_uc_del(fcoe->netdev, port->data_src_addr); if (!is_zero_ether_addr(addr)) - dev_unicast_add(fcoe->netdev, addr); + dev_uc_add(fcoe->netdev, addr); memcpy(port->data_src_addr, addr, ETH_ALEN); rtnl_unlock(); } @@ -819,7 +819,7 @@ static void fcoe_if_destroy(struct fc_lport *lport) rtnl_lock(); if (!is_zero_ether_addr(port->data_src_addr)) - dev_unicast_delete(netdev, port->data_src_addr); + dev_uc_del(netdev, port->data_src_addr); rtnl_unlock(); /* receives may not be stopped until after this */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b5670ab5107..60f0c83192f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1991,15 +1991,20 @@ extern int dev_addr_add_multiple(struct net_device *to_dev, extern int dev_addr_del_multiple(struct net_device *to_dev, struct net_device *from_dev, unsigned char addr_type); +extern void dev_addr_flush(struct net_device *dev); +extern int dev_addr_init(struct net_device *dev); + +/* Functions used for unicast addresses handling */ +extern int dev_uc_add(struct net_device *dev, unsigned char *addr); +extern int dev_uc_del(struct net_device *dev, unsigned char *addr); +extern int dev_uc_sync(struct net_device *to, struct net_device *from); +extern void dev_uc_unsync(struct net_device *to, struct net_device *from); +extern void dev_uc_flush(struct net_device *dev); +extern void dev_uc_init(struct net_device *dev); /* Functions used for secondary unicast and multicast support */ extern void dev_set_rx_mode(struct net_device *dev); extern void __dev_set_rx_mode(struct net_device *dev); -extern int dev_unicast_delete(struct net_device *dev, void *addr); -extern int dev_unicast_add(struct net_device *dev, void *addr); -extern int dev_unicast_sync(struct net_device *to, struct net_device *from); -extern void dev_unicast_unsync(struct net_device *to, struct net_device *from); -extern void dev_unicast_flush(struct net_device *dev); extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); extern int dev_mc_sync(struct net_device *to, struct net_device *from); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index c39a5f41169..bd33f02013e 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -356,13 +356,13 @@ static void vlan_sync_address(struct net_device *dev, * the new address */ if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) - dev_unicast_delete(dev, vlandev->dev_addr); + dev_uc_del(dev, vlandev->dev_addr); /* vlan address was equal to the old address and is different from * the new address */ if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) - dev_unicast_add(dev, vlandev->dev_addr); + dev_uc_add(dev, vlandev->dev_addr); memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); } diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9e83272fc5b..7f4d247237e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -461,7 +461,7 @@ static int vlan_dev_open(struct net_device *dev) return -ENETDOWN; if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { - err = dev_unicast_add(real_dev, dev->dev_addr); + err = dev_uc_add(real_dev, dev->dev_addr); if (err < 0) goto out; } @@ -490,7 +490,7 @@ clear_allmulti: dev_set_allmulti(real_dev, -1); del_unicast: if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr); + dev_uc_del(real_dev, dev->dev_addr); out: netif_carrier_off(dev); return err; @@ -505,14 +505,14 @@ static int vlan_dev_stop(struct net_device *dev) vlan_gvrp_request_leave(dev); dev_mc_unsync(real_dev, dev); - dev_unicast_unsync(real_dev, dev); + dev_uc_unsync(real_dev, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(real_dev, -1); if (dev->flags & IFF_PROMISC) dev_set_promiscuity(real_dev, -1); if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr); + dev_uc_del(real_dev, dev->dev_addr); netif_carrier_off(dev); return 0; @@ -531,13 +531,13 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p) goto out; if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { - err = dev_unicast_add(real_dev, addr->sa_data); + err = dev_uc_add(real_dev, addr->sa_data); if (err < 0) return err; } if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr); + dev_uc_del(real_dev, dev->dev_addr); out: memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -654,7 +654,7 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); - dev_unicast_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); + dev_uc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); } /* diff --git a/net/core/Makefile b/net/core/Makefile index 08791ac3e05..0a899f1aadb 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -8,7 +8,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ - neighbour.o rtnetlink.o utils.o link_watch.o filter.o + neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ + dev_addr_lists.o obj-$(CONFIG_XFRM) += flow.o obj-y += net-sysfs.o diff --git a/net/core/dev.c b/net/core/dev.c index c6b52068d5e..949c62dba71 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3968,314 +3968,6 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } -/* hw addresses list handling functions */ - -static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, - int addr_len, unsigned char addr_type) -{ - struct netdev_hw_addr *ha; - int alloc_size; - - if (addr_len > MAX_ADDR_LEN) - return -EINVAL; - - list_for_each_entry(ha, &list->list, list) { - if (!memcmp(ha->addr, addr, addr_len) && - ha->type == addr_type) { - ha->refcount++; - return 0; - } - } - - - alloc_size = sizeof(*ha); - if (alloc_size < L1_CACHE_BYTES) - alloc_size = L1_CACHE_BYTES; - ha = kmalloc(alloc_size, GFP_ATOMIC); - if (!ha) - return -ENOMEM; - memcpy(ha->addr, addr, addr_len); - ha->type = addr_type; - ha->refcount = 1; - ha->synced = false; - list_add_tail_rcu(&ha->list, &list->list); - list->count++; - return 0; -} - -static void ha_rcu_free(struct rcu_head *head) -{ - struct netdev_hw_addr *ha; - - ha = container_of(head, struct netdev_hw_addr, rcu_head); - kfree(ha); -} - -static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, - int addr_len, unsigned char addr_type) -{ - struct netdev_hw_addr *ha; - - list_for_each_entry(ha, &list->list, list) { - if (!memcmp(ha->addr, addr, addr_len) && - (ha->type == addr_type || !addr_type)) { - if (--ha->refcount) - return 0; - list_del_rcu(&ha->list); - call_rcu(&ha->rcu_head, ha_rcu_free); - list->count--; - return 0; - } - } - return -ENOENT; -} - -static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, - unsigned char addr_type) -{ - int err; - struct netdev_hw_addr *ha, *ha2; - unsigned char type; - - list_for_each_entry(ha, &from_list->list, list) { - type = addr_type ? addr_type : ha->type; - err = __hw_addr_add(to_list, ha->addr, addr_len, type); - if (err) - goto unroll; - } - return 0; - -unroll: - list_for_each_entry(ha2, &from_list->list, list) { - if (ha2 == ha) - break; - type = addr_type ? addr_type : ha2->type; - __hw_addr_del(to_list, ha2->addr, addr_len, type); - } - return err; -} - -static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, - unsigned char addr_type) -{ - struct netdev_hw_addr *ha; - unsigned char type; - - list_for_each_entry(ha, &from_list->list, list) { - type = addr_type ? addr_type : ha->type; - __hw_addr_del(to_list, ha->addr, addr_len, addr_type); - } -} - -static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len) -{ - int err = 0; - struct netdev_hw_addr *ha, *tmp; - - list_for_each_entry_safe(ha, tmp, &from_list->list, list) { - if (!ha->synced) { - err = __hw_addr_add(to_list, ha->addr, - addr_len, ha->type); - if (err) - break; - ha->synced = true; - ha->refcount++; - } else if (ha->refcount == 1) { - __hw_addr_del(to_list, ha->addr, addr_len, ha->type); - __hw_addr_del(from_list, ha->addr, addr_len, ha->type); - } - } - return err; -} - -static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len) -{ - struct netdev_hw_addr *ha, *tmp; - - list_for_each_entry_safe(ha, tmp, &from_list->list, list) { - if (ha->synced) { - __hw_addr_del(to_list, ha->addr, - addr_len, ha->type); - ha->synced = false; - __hw_addr_del(from_list, ha->addr, - addr_len, ha->type); - } - } -} - -static void __hw_addr_flush(struct netdev_hw_addr_list *list) -{ - struct netdev_hw_addr *ha, *tmp; - - list_for_each_entry_safe(ha, tmp, &list->list, list) { - list_del_rcu(&ha->list); - call_rcu(&ha->rcu_head, ha_rcu_free); - } - list->count = 0; -} - -static void __hw_addr_init(struct netdev_hw_addr_list *list) -{ - INIT_LIST_HEAD(&list->list); - list->count = 0; -} - -/* Device addresses handling functions */ - -static void dev_addr_flush(struct net_device *dev) -{ - /* rtnl_mutex must be held here */ - - __hw_addr_flush(&dev->dev_addrs); - dev->dev_addr = NULL; -} - -static int dev_addr_init(struct net_device *dev) -{ - unsigned char addr[MAX_ADDR_LEN]; - struct netdev_hw_addr *ha; - int err; - - /* rtnl_mutex must be held here */ - - __hw_addr_init(&dev->dev_addrs); - memset(addr, 0, sizeof(addr)); - err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), - NETDEV_HW_ADDR_T_LAN); - if (!err) { - /* - * Get the first (previously created) address from the list - * and set dev_addr pointer to this location. - */ - ha = list_first_entry(&dev->dev_addrs.list, - struct netdev_hw_addr, list); - dev->dev_addr = ha->addr; - } - return err; -} - -/** - * dev_addr_add - Add a device address - * @dev: device - * @addr: address to add - * @addr_type: address type - * - * Add a device address to the device or increase the reference count if - * it already exists. - * - * The caller must hold the rtnl_mutex. - */ -int dev_addr_add(struct net_device *dev, unsigned char *addr, - unsigned char addr_type) -{ - int err; - - ASSERT_RTNL(); - - err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type); - if (!err) - call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); - return err; -} -EXPORT_SYMBOL(dev_addr_add); - -/** - * dev_addr_del - Release a device address. - * @dev: device - * @addr: address to delete - * @addr_type: address type - * - * Release reference to a device address and remove it from the device - * if the reference count drops to zero. - * - * The caller must hold the rtnl_mutex. - */ -int dev_addr_del(struct net_device *dev, unsigned char *addr, - unsigned char addr_type) -{ - int err; - struct netdev_hw_addr *ha; - - ASSERT_RTNL(); - - /* - * We can not remove the first address from the list because - * dev->dev_addr points to that. - */ - ha = list_first_entry(&dev->dev_addrs.list, - struct netdev_hw_addr, list); - if (ha->addr == dev->dev_addr && ha->refcount == 1) - return -ENOENT; - - err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, - addr_type); - if (!err) - call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); - return err; -} -EXPORT_SYMBOL(dev_addr_del); - -/** - * dev_addr_add_multiple - Add device addresses from another device - * @to_dev: device to which addresses will be added - * @from_dev: device from which addresses will be added - * @addr_type: address type - 0 means type will be used from from_dev - * - * Add device addresses of the one device to another. - ** - * The caller must hold the rtnl_mutex. - */ -int dev_addr_add_multiple(struct net_device *to_dev, - struct net_device *from_dev, - unsigned char addr_type) -{ - int err; - - ASSERT_RTNL(); - - if (from_dev->addr_len != to_dev->addr_len) - return -EINVAL; - err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, - to_dev->addr_len, addr_type); - if (!err) - call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); - return err; -} -EXPORT_SYMBOL(dev_addr_add_multiple); - -/** - * dev_addr_del_multiple - Delete device addresses by another device - * @to_dev: device where the addresses will be deleted - * @from_dev: device by which addresses the addresses will be deleted - * @addr_type: address type - 0 means type will used from from_dev - * - * Deletes addresses in to device by the list of addresses in from device. - * - * The caller must hold the rtnl_mutex. - */ -int dev_addr_del_multiple(struct net_device *to_dev, - struct net_device *from_dev, - unsigned char addr_type) -{ - ASSERT_RTNL(); - - if (from_dev->addr_len != to_dev->addr_len) - return -EINVAL; - __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, - to_dev->addr_len, addr_type); - call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); - return 0; -} -EXPORT_SYMBOL(dev_addr_del_multiple); - /* multicast addresses handling functions */ int __dev_addr_delete(struct dev_addr_list **list, int *count, @@ -4336,57 +4028,6 @@ int __dev_addr_add(struct dev_addr_list **list, int *count, return 0; } -/** - * dev_unicast_delete - Release secondary unicast address. - * @dev: device - * @addr: address to delete - * - * Release reference to a secondary unicast address and remove it - * from the device if the reference count drops to zero. - * - * The caller must hold the rtnl_mutex. - */ -int dev_unicast_delete(struct net_device *dev, void *addr) -{ - int err; - - ASSERT_RTNL(); - - netif_addr_lock_bh(dev); - err = __hw_addr_del(&dev->uc, addr, dev->addr_len, - NETDEV_HW_ADDR_T_UNICAST); - if (!err) - __dev_set_rx_mode(dev); - netif_addr_unlock_bh(dev); - return err; -} -EXPORT_SYMBOL(dev_unicast_delete); - -/** - * dev_unicast_add - add a secondary unicast address - * @dev: device - * @addr: address to add - * - * Add a secondary unicast address to the device or increase - * the reference count if it already exists. - * - * The caller must hold the rtnl_mutex. - */ -int dev_unicast_add(struct net_device *dev, void *addr) -{ - int err; - - ASSERT_RTNL(); - - netif_addr_lock_bh(dev); - err = __hw_addr_add(&dev->uc, addr, dev->addr_len, - NETDEV_HW_ADDR_T_UNICAST); - if (!err) - __dev_set_rx_mode(dev); - netif_addr_unlock_bh(dev); - return err; -} -EXPORT_SYMBOL(dev_unicast_add); int __dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count) @@ -4436,71 +4077,6 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, } EXPORT_SYMBOL_GPL(__dev_addr_unsync); -/** - * dev_unicast_sync - Synchronize device's unicast list to another device - * @to: destination device - * @from: source device - * - * Add newly added addresses to the destination device and release - * addresses that have no users left. The source device must be - * locked by netif_tx_lock_bh. - * - * This function is intended to be called from the dev->set_rx_mode - * function of layered software devices. - */ -int dev_unicast_sync(struct net_device *to, struct net_device *from) -{ - int err = 0; - - if (to->addr_len != from->addr_len) - return -EINVAL; - - netif_addr_lock_bh(to); - err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); - if (!err) - __dev_set_rx_mode(to); - netif_addr_unlock_bh(to); - return err; -} -EXPORT_SYMBOL(dev_unicast_sync); - -/** - * dev_unicast_unsync - Remove synchronized addresses from the destination device - * @to: destination device - * @from: source device - * - * Remove all addresses that were added to the destination device by - * dev_unicast_sync(). This function is intended to be called from the - * dev->stop function of layered software devices. - */ -void dev_unicast_unsync(struct net_device *to, struct net_device *from) -{ - if (to->addr_len != from->addr_len) - return; - - netif_addr_lock_bh(from); - netif_addr_lock(to); - __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); - __dev_set_rx_mode(to); - netif_addr_unlock(to); - netif_addr_unlock_bh(from); -} -EXPORT_SYMBOL(dev_unicast_unsync); - -void dev_unicast_flush(struct net_device *dev) -{ - netif_addr_lock_bh(dev); - __hw_addr_flush(&dev->uc); - netif_addr_unlock_bh(dev); -} -EXPORT_SYMBOL(dev_unicast_flush); - -static void dev_unicast_init(struct net_device *dev) -{ - __hw_addr_init(&dev->uc); -} - - static void __dev_addr_discard(struct dev_addr_list **list) { struct dev_addr_list *tmp; @@ -5153,7 +4729,7 @@ static void rollback_registered_many(struct list_head *head) /* * Flush the unicast and multicast chains */ - dev_unicast_flush(dev); + dev_uc_flush(dev); dev_addr_discard(dev); if (dev->netdev_ops->ndo_uninit) @@ -5734,7 +5310,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, if (dev_addr_init(dev)) goto free_rx; - dev_unicast_init(dev); + dev_uc_init(dev); dev_net_set(dev, &init_net); @@ -5968,7 +5544,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* * Flush the unicast and multicast chains */ - dev_unicast_flush(dev); + dev_uc_flush(dev); dev_addr_discard(dev); netdev_unregister_kobject(dev); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c new file mode 100644 index 00000000000..7e52b6d18ad --- /dev/null +++ b/net/core/dev_addr_lists.c @@ -0,0 +1,478 @@ +/* + * net/core/dev_addr_lists.c - Functions for handling net device lists + * Copyright (c) 2010 Jiri Pirko + * + * This file contains functions for working with unicast, multicast and device + * addresses lists. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +/* + * General list handling functions + */ + +static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, + int addr_len, unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + int alloc_size; + + if (addr_len > MAX_ADDR_LEN) + return -EINVAL; + + list_for_each_entry(ha, &list->list, list) { + if (!memcmp(ha->addr, addr, addr_len) && + ha->type == addr_type) { + ha->refcount++; + return 0; + } + } + + + alloc_size = sizeof(*ha); + if (alloc_size < L1_CACHE_BYTES) + alloc_size = L1_CACHE_BYTES; + ha = kmalloc(alloc_size, GFP_ATOMIC); + if (!ha) + return -ENOMEM; + memcpy(ha->addr, addr, addr_len); + ha->type = addr_type; + ha->refcount = 1; + ha->synced = false; + list_add_tail_rcu(&ha->list, &list->list); + list->count++; + return 0; +} + +static void ha_rcu_free(struct rcu_head *head) +{ + struct netdev_hw_addr *ha; + + ha = container_of(head, struct netdev_hw_addr, rcu_head); + kfree(ha); +} + +static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, + int addr_len, unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + + list_for_each_entry(ha, &list->list, list) { + if (!memcmp(ha->addr, addr, addr_len) && + (ha->type == addr_type || !addr_type)) { + if (--ha->refcount) + return 0; + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + list->count--; + return 0; + } + } + return -ENOENT; +} + +static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, + unsigned char addr_type) +{ + int err; + struct netdev_hw_addr *ha, *ha2; + unsigned char type; + + list_for_each_entry(ha, &from_list->list, list) { + type = addr_type ? addr_type : ha->type; + err = __hw_addr_add(to_list, ha->addr, addr_len, type); + if (err) + goto unroll; + } + return 0; + +unroll: + list_for_each_entry(ha2, &from_list->list, list) { + if (ha2 == ha) + break; + type = addr_type ? addr_type : ha2->type; + __hw_addr_del(to_list, ha2->addr, addr_len, type); + } + return err; +} + +static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, + unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + unsigned char type; + + list_for_each_entry(ha, &from_list->list, list) { + type = addr_type ? addr_type : ha->type; + __hw_addr_del(to_list, ha->addr, addr_len, addr_type); + } +} + +static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len) +{ + int err = 0; + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, &from_list->list, list) { + if (!ha->synced) { + err = __hw_addr_add(to_list, ha->addr, + addr_len, ha->type); + if (err) + break; + ha->synced = true; + ha->refcount++; + } else if (ha->refcount == 1) { + __hw_addr_del(to_list, ha->addr, addr_len, ha->type); + __hw_addr_del(from_list, ha->addr, addr_len, ha->type); + } + } + return err; +} + +static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, &from_list->list, list) { + if (ha->synced) { + __hw_addr_del(to_list, ha->addr, + addr_len, ha->type); + ha->synced = false; + __hw_addr_del(from_list, ha->addr, + addr_len, ha->type); + } + } +} + +static void __hw_addr_flush(struct netdev_hw_addr_list *list) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, &list->list, list) { + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + } + list->count = 0; +} + +static void __hw_addr_init(struct netdev_hw_addr_list *list) +{ + INIT_LIST_HEAD(&list->list); + list->count = 0; +} + +/* + * Device addresses handling functions + */ + +/** + * dev_addr_flush - Flush device address list + * @dev: device + * + * Flush device address list and reset ->dev_addr. + * + * The caller must hold the rtnl_mutex. + */ +void dev_addr_flush(struct net_device *dev) +{ + /* rtnl_mutex must be held here */ + + __hw_addr_flush(&dev->dev_addrs); + dev->dev_addr = NULL; +} +EXPORT_SYMBOL(dev_addr_flush); + +/** + * dev_addr_init - Init device address list + * @dev: device + * + * Init device address list and create the first element, + * used by ->dev_addr. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_init(struct net_device *dev) +{ + unsigned char addr[MAX_ADDR_LEN]; + struct netdev_hw_addr *ha; + int err; + + /* rtnl_mutex must be held here */ + + __hw_addr_init(&dev->dev_addrs); + memset(addr, 0, sizeof(addr)); + err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), + NETDEV_HW_ADDR_T_LAN); + if (!err) { + /* + * Get the first (previously created) address from the list + * and set dev_addr pointer to this location. + */ + ha = list_first_entry(&dev->dev_addrs.list, + struct netdev_hw_addr, list); + dev->dev_addr = ha->addr; + } + return err; +} +EXPORT_SYMBOL(dev_addr_init); + +/** + * dev_addr_add - Add a device address + * @dev: device + * @addr: address to add + * @addr_type: address type + * + * Add a device address to the device or increase the reference count if + * it already exists. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add); + +/** + * dev_addr_del - Release a device address. + * @dev: device + * @addr: address to delete + * @addr_type: address type + * + * Release reference to a device address and remove it from the device + * if the reference count drops to zero. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + struct netdev_hw_addr *ha; + + ASSERT_RTNL(); + + /* + * We can not remove the first address from the list because + * dev->dev_addr points to that. + */ + ha = list_first_entry(&dev->dev_addrs.list, + struct netdev_hw_addr, list); + if (ha->addr == dev->dev_addr && ha->refcount == 1) + return -ENOENT; + + err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, + addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_del); + +/** + * dev_addr_add_multiple - Add device addresses from another device + * @to_dev: device to which addresses will be added + * @from_dev: device from which addresses will be added + * @addr_type: address type - 0 means type will be used from from_dev + * + * Add device addresses of the one device to another. + ** + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, + to_dev->addr_len, addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add_multiple); + +/** + * dev_addr_del_multiple - Delete device addresses by another device + * @to_dev: device where the addresses will be deleted + * @from_dev: device by which addresses the addresses will be deleted + * @addr_type: address type - 0 means type will used from from_dev + * + * Deletes addresses in to device by the list of addresses in from device. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, + to_dev->addr_len, addr_type); + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return 0; +} +EXPORT_SYMBOL(dev_addr_del_multiple); + +/* + * Unicast list handling functions + */ + +/** + * dev_uc_add - Add a secondary unicast address + * @dev: device + * @addr: address to add + * + * Add a secondary unicast address to the device or increase + * the reference count if it already exists. + */ +int dev_uc_add(struct net_device *dev, unsigned char *addr) +{ + int err; + + netif_addr_lock_bh(dev); + err = __hw_addr_add(&dev->uc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_UNICAST); + if (!err) + __dev_set_rx_mode(dev); + netif_addr_unlock_bh(dev); + return err; +} +EXPORT_SYMBOL(dev_uc_add); + +/** + * dev_uc_del - Release secondary unicast address. + * @dev: device + * @addr: address to delete + * + * Release reference to a secondary unicast address and remove it + * from the device if the reference count drops to zero. + */ +int dev_uc_del(struct net_device *dev, unsigned char *addr) +{ + int err; + + netif_addr_lock_bh(dev); + err = __hw_addr_del(&dev->uc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_UNICAST); + if (!err) + __dev_set_rx_mode(dev); + netif_addr_unlock_bh(dev); + return err; +} +EXPORT_SYMBOL(dev_uc_del); + +/** + * dev_uc_sync - Synchronize device's unicast list to another device + * @to: destination device + * @from: source device + * + * Add newly added addresses to the destination device and release + * addresses that have no users left. The source device must be + * locked by netif_tx_lock_bh. + * + * This function is intended to be called from the dev->set_rx_mode + * function of layered software devices. + */ +int dev_uc_sync(struct net_device *to, struct net_device *from) +{ + int err = 0; + + if (to->addr_len != from->addr_len) + return -EINVAL; + + netif_addr_lock_bh(to); + err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); + if (!err) + __dev_set_rx_mode(to); + netif_addr_unlock_bh(to); + return err; +} +EXPORT_SYMBOL(dev_uc_sync); + +/** + * dev_uc_unsync - Remove synchronized addresses from the destination device + * @to: destination device + * @from: source device + * + * Remove all addresses that were added to the destination device by + * dev_uc_sync(). This function is intended to be called from the + * dev->stop function of layered software devices. + */ +void dev_uc_unsync(struct net_device *to, struct net_device *from) +{ + if (to->addr_len != from->addr_len) + return; + + netif_addr_lock_bh(from); + netif_addr_lock(to); + __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); + __dev_set_rx_mode(to); + netif_addr_unlock(to); + netif_addr_unlock_bh(from); +} +EXPORT_SYMBOL(dev_uc_unsync); + +/** + * dev_uc_flush - Flush unicast addresses + * @dev: device + * + * Flush unicast addresses. + */ +void dev_uc_flush(struct net_device *dev) +{ + netif_addr_lock_bh(dev); + __hw_addr_flush(&dev->uc); + netif_addr_unlock_bh(dev); +} +EXPORT_SYMBOL(dev_uc_flush); + +/** + * dev_uc_flush - Init unicast address list + * @dev: device + * + * Init unicast address list. + */ +void dev_uc_init(struct net_device *dev) +{ + __hw_addr_init(&dev->uc); +} +EXPORT_SYMBOL(dev_uc_init); + +/* + * Multicast list handling functions + */ + +/* To be filled here */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 2175e6d5cc8..8fdca56bb08 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -67,7 +67,7 @@ static int dsa_slave_open(struct net_device *dev) return -ENETDOWN; if (compare_ether_addr(dev->dev_addr, master->dev_addr)) { - err = dev_unicast_add(master, dev->dev_addr); + err = dev_uc_add(master, dev->dev_addr); if (err < 0) goto out; } @@ -90,7 +90,7 @@ clear_allmulti: dev_set_allmulti(master, -1); del_unicast: if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr); + dev_uc_del(master, dev->dev_addr); out: return err; } @@ -101,14 +101,14 @@ static int dsa_slave_close(struct net_device *dev) struct net_device *master = p->parent->dst->master_netdev; dev_mc_unsync(master, dev); - dev_unicast_unsync(master, dev); + dev_uc_unsync(master, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(master, -1); if (dev->flags & IFF_PROMISC) dev_set_promiscuity(master, -1); if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr); + dev_uc_del(master, dev->dev_addr); return 0; } @@ -130,7 +130,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev) struct net_device *master = p->parent->dst->master_netdev; dev_mc_sync(master, dev); - dev_unicast_sync(master, dev); + dev_uc_sync(master, dev); } static int dsa_slave_set_mac_address(struct net_device *dev, void *a) @@ -147,13 +147,13 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a) goto out; if (compare_ether_addr(addr->sa_data, master->dev_addr)) { - err = dev_unicast_add(master, addr->sa_data); + err = dev_uc_add(master, addr->sa_data); if (err < 0) return err; } if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr); + dev_uc_del(master, dev->dev_addr); out: memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1612d417d10..48c1e0ae565 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1705,9 +1705,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, if (i->alen != dev->addr_len) return -EINVAL; if (what > 0) - return dev_unicast_add(dev, i->addr); + return dev_uc_add(dev, i->addr); else - return dev_unicast_delete(dev, i->addr); + return dev_uc_del(dev, i->addr); break; default: break; -- cgit v1.2.3 From 22bedad3ce112d5ca1eaf043d4990fa2ed698c87 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Apr 2010 21:22:57 +0000 Subject: net: convert multicast list to list_head Converts the list and the core manipulating with it to be the same as uc_list. +uses two functions for adding/removing mc address (normal and "global" variant) instead of a function parameter. +removes dev_mcast.c completely. +exposes netdev_hw_addr_list_* macros along with __hw_addr_* functions for manipulation with lists on a sandbox (used in bonding and 80211 drivers) Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 7 +- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 9 +- drivers/media/dvb/dvb-core/dvb_net.c | 10 +- drivers/net/3c505.c | 7 +- drivers/net/3c523.c | 7 +- drivers/net/3c527.c | 6 +- drivers/net/7990.c | 6 +- drivers/net/8139cp.c | 6 +- drivers/net/8139too.c | 6 +- drivers/net/82596.c | 6 +- drivers/net/a2065.c | 6 +- drivers/net/amd8111e.c | 6 +- drivers/net/arm/am79c961a.c | 6 +- drivers/net/arm/at91_ether.c | 6 +- drivers/net/arm/ixp4xx_eth.c | 8 +- drivers/net/arm/ks8695net.c | 10 +- drivers/net/at1700.c | 6 +- drivers/net/atl1c/atl1c_main.c | 6 +- drivers/net/atl1e/atl1e_main.c | 6 +- drivers/net/atlx/atl2.c | 6 +- drivers/net/atlx/atlx.c | 6 +- drivers/net/atp.c | 6 +- drivers/net/au1000_eth.c | 6 +- drivers/net/b44.c | 6 +- drivers/net/bcm63xx_enet.c | 6 +- drivers/net/benet/be_cmds.c | 6 +- drivers/net/bfin_mac.c | 6 +- drivers/net/bmac.c | 12 +- drivers/net/bnx2.c | 5 +- drivers/net/bnx2x_main.c | 18 +- drivers/net/bonding/bond_main.c | 157 +++++-------- drivers/net/bonding/bonding.h | 2 +- drivers/net/cassini.c | 12 +- drivers/net/chelsio/pm3393.c | 7 +- drivers/net/cpmac.c | 16 +- drivers/net/cris/eth_v10.c | 6 +- drivers/net/cxgb3/xgmac.c | 8 +- drivers/net/davinci_emac.c | 7 +- drivers/net/declance.c | 6 +- drivers/net/defxx.c | 6 +- drivers/net/depca.c | 6 +- drivers/net/dl2k.c | 6 +- drivers/net/dm9000.c | 6 +- drivers/net/e100.c | 6 +- drivers/net/e1000/e1000_main.c | 7 +- drivers/net/e1000e/netdev.c | 7 +- drivers/net/eepro.c | 6 +- drivers/net/eexpress.c | 6 +- drivers/net/ehea/ehea_main.c | 6 +- drivers/net/enic/enic_main.c | 6 +- drivers/net/epic100.c | 6 +- drivers/net/ethoc.c | 6 +- drivers/net/ewrk3.c | 6 +- drivers/net/fealnx.c | 6 +- drivers/net/fec.c | 10 +- drivers/net/fec_mpc52xx.c | 6 +- drivers/net/forcedeth.c | 10 +- drivers/net/fs_enet/mac-fcc.c | 6 +- drivers/net/fs_enet/mac-fec.c | 6 +- drivers/net/fs_enet/mac-scc.c | 6 +- drivers/net/gianfar.c | 9 +- drivers/net/greth.c | 6 +- drivers/net/hamachi.c | 8 +- drivers/net/hp100.c | 6 +- drivers/net/ibm_newemac/core.c | 11 +- drivers/net/ibmlana.c | 8 +- drivers/net/ibmveth.c | 6 +- drivers/net/igb/igb_main.c | 6 +- drivers/net/igbvf/netdev.c | 6 +- drivers/net/ioc3-eth.c | 6 +- drivers/net/ipg.c | 6 +- drivers/net/iseries_veth.c | 6 +- drivers/net/ixgb/ixgb_main.c | 6 +- drivers/net/ixgbe/ixgbe_common.c | 6 +- drivers/net/ixgbevf/vf.c | 6 +- drivers/net/jme.c | 6 +- drivers/net/korina.c | 6 +- drivers/net/ks8851.c | 6 +- drivers/net/ks8851_mll.c | 12 +- drivers/net/ksz884x.c | 11 +- drivers/net/lib82596.c | 6 +- drivers/net/lib8390.c | 6 +- drivers/net/ll_temac_main.c | 16 +- drivers/net/lp486e.c | 6 +- drivers/net/macb.c | 6 +- drivers/net/mace.c | 6 +- drivers/net/macmace.c | 6 +- drivers/net/mlx4/en_netdev.c | 6 +- drivers/net/mv643xx_eth.c | 6 +- drivers/net/myri10ge/myri10ge.c | 8 +- drivers/net/natsemi.c | 6 +- drivers/net/netxen/netxen_nic_hw.c | 12 +- drivers/net/ni52.c | 6 +- drivers/net/niu.c | 5 +- drivers/net/octeon/octeon_mgmt.c | 6 +- drivers/net/pci-skeleton.c | 6 +- drivers/net/pcmcia/axnet_cs.c | 6 +- drivers/net/pcmcia/fmvj18x_cs.c | 6 +- drivers/net/pcmcia/nmclan_cs.c | 6 +- drivers/net/pcmcia/smc91c92_cs.c | 8 +- drivers/net/pcmcia/xirc2ps_cs.c | 6 +- drivers/net/pcnet32.c | 6 +- drivers/net/ps3_gelic_net.c | 6 +- drivers/net/qlcnic/qlcnic_hw.c | 6 +- drivers/net/qlge/qlge_main.c | 6 +- drivers/net/r6040.c | 10 +- drivers/net/r8169.c | 6 +- drivers/net/s2io.c | 8 +- drivers/net/sb1250-mac.c | 6 +- drivers/net/sc92031.c | 6 +- drivers/net/sfc/efx.c | 6 +- drivers/net/sis190.c | 6 +- drivers/net/sis900.c | 10 +- drivers/net/skfp/skfddi.c | 12 +- drivers/net/skge.c | 12 +- drivers/net/sky2.c | 6 +- drivers/net/smc911x.c | 13 +- drivers/net/smc9194.c | 13 +- drivers/net/smc91x.c | 8 +- drivers/net/smsc911x.c | 6 +- drivers/net/smsc9420.c | 6 +- drivers/net/sonic.c | 6 +- drivers/net/spider_net.c | 6 +- drivers/net/starfire.c | 10 +- drivers/net/stmmac/dwmac100.c | 6 +- drivers/net/stmmac/dwmac1000_core.c | 6 +- drivers/net/sun3_82586.c | 6 +- drivers/net/sunbmac.c | 6 +- drivers/net/sundance.c | 6 +- drivers/net/sungem.c | 6 +- drivers/net/sunhme.c | 12 +- drivers/net/sunlance.c | 6 +- drivers/net/sunqe.c | 6 +- drivers/net/sunvnet.c | 8 +- drivers/net/tc35815.c | 6 +- drivers/net/tehuti.c | 6 +- drivers/net/tg3.c | 6 +- drivers/net/tlan.c | 8 +- drivers/net/tokenring/3c359.c | 12 +- drivers/net/tokenring/ibmtr.c | 12 +- drivers/net/tokenring/lanstreamer.c | 12 +- drivers/net/tokenring/olympic.c | 12 +- drivers/net/tokenring/tms380tr.c | 12 +- drivers/net/tsi108_eth.c | 6 +- drivers/net/tulip/de2104x.c | 12 +- drivers/net/tulip/de4x5.c | 10 +- drivers/net/tulip/dmfe.c | 12 +- drivers/net/tulip/tulip_core.c | 27 ++- drivers/net/tulip/uli526x.c | 6 +- drivers/net/tulip/winbond-840.c | 12 +- drivers/net/typhoon.c | 6 +- drivers/net/ucc_geth.c | 8 +- drivers/net/usb/asix.c | 16 +- drivers/net/usb/catc.c | 6 +- drivers/net/usb/dm9601.c | 6 +- drivers/net/usb/mcs7830.c | 6 +- drivers/net/usb/smsc75xx.c | 6 +- drivers/net/usb/smsc95xx.c | 6 +- drivers/net/via-rhine.c | 6 +- drivers/net/via-velocity.c | 6 +- drivers/net/virtio_net.c | 5 +- drivers/net/vmxnet3/vmxnet3_drv.c | 6 +- drivers/net/vxge/vxge-main.c | 6 +- drivers/net/wireless/adm8211.c | 12 +- drivers/net/wireless/ath/ar9170/main.c | 14 +- drivers/net/wireless/ath/ath5k/base.c | 17 +- drivers/net/wireless/libertas/main.c | 12 +- drivers/net/wireless/libertas_tf/main.c | 14 +- drivers/net/wireless/mwl8k.c | 24 +- drivers/net/wireless/orinoco/hw.c | 6 +- drivers/net/wireless/orinoco/hw.h | 1 - drivers/net/wireless/ray_cs.c | 12 +- drivers/net/wireless/rndis_wlan.c | 6 +- drivers/net/wireless/rtl818x/rtl8180_dev.c | 6 +- drivers/net/wireless/rtl818x/rtl8187_dev.c | 4 +- drivers/net/wireless/wl12xx/wl1271_main.c | 25 +- drivers/net/wireless/zd1201.c | 6 +- drivers/net/wireless/zd1211rw/zd_mac.c | 13 +- drivers/net/yellowfin.c | 12 +- drivers/s390/net/qeth_l2_main.c | 5 +- drivers/scsi/fcoe/fcoe.c | 4 +- drivers/staging/arlan/arlan-main.c | 9 +- drivers/staging/et131x/et131x_netdev.c | 6 +- drivers/staging/slicoss/slicoss.c | 6 +- drivers/staging/vt6655/device_main.c | 6 +- drivers/staging/vt6656/main_usb.c | 6 +- drivers/staging/wavelan/wavelan.c | 10 +- drivers/staging/wavelan/wavelan_cs.c | 12 +- drivers/staging/winbond/wbusb.c | 6 +- drivers/staging/wlags49_h2/wl_netdev.c | 12 +- include/linux/netdevice.h | 82 +++---- include/net/mac80211.h | 2 +- net/802/garp.c | 4 +- net/appletalk/ddp.c | 2 +- net/bluetooth/bnep/netdev.c | 8 +- net/core/Makefile | 5 +- net/core/dev.c | 145 +----------- net/core/dev_addr_lists.c | 305 +++++++++++++++++++++++-- net/core/dev_mcast.c | 232 ------------------- net/decnet/dn_dev.c | 12 +- net/ipv4/igmp.c | 4 +- net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 +- net/ipv6/mcast.c | 4 +- net/mac80211/driver-ops.h | 8 +- net/mac80211/ieee80211_i.h | 3 +- net/mac80211/iface.c | 6 +- net/mac80211/main.c | 2 +- net/packet/af_packet.c | 4 +- 208 files changed, 1137 insertions(+), 1327 deletions(-) delete mode 100644 net/core/dev_mcast.c (limited to 'include/linux/netdevice.h') diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 91fdde382e8..ce9ef6bc865 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -876,7 +876,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) if (!mc_all_on) { char *addrs; int i; - struct dev_mc_list *mcaddr; + struct netdev_hw_addr *ha; addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC); if (!addrs) { @@ -884,9 +884,8 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) goto unlock; } i = 0; - netdev_for_each_mc_addr(mcaddr, netdev) - memcpy(get_addr(addrs, i++), - mcaddr->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, netdev) + memcpy(get_addr(addrs, i++), ha->addr, ETH_ALEN); perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + pft_entries_preallocated * 0x8; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 19eba3c877c..c8a0f7dab5b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -783,7 +783,7 @@ void ipoib_mcast_restart_task(struct work_struct *work) struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, restart_task); struct net_device *dev = priv->dev; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct ipoib_mcast *mcast, *tmcast; LIST_HEAD(remove_list); unsigned long flags; @@ -808,14 +808,13 @@ void ipoib_mcast_restart_task(struct work_struct *work) clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags); /* Mark all of the entries that are found or don't exist */ - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { union ib_gid mgid; - if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr, - dev->broadcast)) + if (!ipoib_mcast_addr_is_valid(ha->addr, dev->broadcast)) continue; - memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid); + memcpy(mgid.raw, ha->addr + 4, sizeof mgid); mcast = __ipoib_mcast_find(dev, &mgid); if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index dba1c84058b..cccea412088 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -1109,14 +1109,14 @@ static int dvb_net_feed_stop(struct net_device *dev) } -static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) +static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr) { struct dvb_net_priv *priv = netdev_priv(dev); if (priv->multi_num == DVB_NET_MULTICAST_MAX) return -ENOMEM; - memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6); + memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN); priv->multi_num++; return 0; @@ -1140,7 +1140,7 @@ static void wq_set_multicast_list (struct work_struct *work) dprintk("%s: allmulti mode\n", dev->name); priv->rx_mode = RX_MODE_ALL_MULTI; } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; dprintk("%s: set_mc_list, %d entries\n", dev->name, netdev_mc_count(dev)); @@ -1148,8 +1148,8 @@ static void wq_set_multicast_list (struct work_struct *work) priv->rx_mode = RX_MODE_MULTI; priv->multi_num = 0; - netdev_for_each_mc_addr(mc, dev) - dvb_set_mc_filter(dev, mc); + netdev_for_each_mc_addr(ha, dev) + dvb_set_mc_filter(dev, ha->addr); } netif_addr_unlock_bh(dev); diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 04b5bba1902..81c8b31e629 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1216,7 +1216,7 @@ static int elp_close(struct net_device *dev) static void elp_set_mc_list(struct net_device *dev) { elp_device *adapter = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i; unsigned long flags; @@ -1231,8 +1231,9 @@ static void elp_set_mc_list(struct net_device *dev) adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; adapter->tx_pcb.length = 6 * netdev_mc_count(dev); i = 0; - netdev_for_each_mc_addr(dmi, dev) - memcpy(adapter->tx_pcb.data.multicast[i++], dmi->dmi_addr, 6); + 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); diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index beed4fa10c6..966cb12e1e0 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -625,7 +625,7 @@ static int init586(struct net_device *dev) volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int num_addrs = netdev_mc_count(dev); ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); @@ -788,8 +788,9 @@ static int init586(struct net_device *dev) mc_cmd->cmd_link = 0xffff; mc_cmd->mc_cnt = num_addrs * 6; i = 0; - netdev_for_each_mc_addr(dmi, dev) - memcpy((char *) mc_cmd->mc_list[i++], dmi->dmi_addr, 6); + netdev_for_each_mc_addr(ha, dev) + memcpy((char *) mc_cmd->mc_list[i++], + ha->addr, 6); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd = CUC_START; elmc_id_attn586(); diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 5c07b147ec9..38395dfa496 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1533,7 +1533,7 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) { unsigned char block[62]; unsigned char *bp; - struct dev_mc_list *dmc; + struct netdev_hw_addr *ha; if(retry==0) lp->mc_list_valid = 0; @@ -1543,8 +1543,8 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) block[0]=netdev_mc_count(dev); bp=block+2; - netdev_for_each_mc_addr(dmc, dev) { - memcpy(bp, dmc->dmi_addr, 6); + netdev_for_each_mc_addr(ha, dev) { + memcpy(bp, ha->addr, 6); bp+=6; } if(mc32_command_nowait(dev, 2, block, diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 4e9a5a20b6a..818837d8ffe 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -595,7 +595,7 @@ static void lance_load_multicast (struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; @@ -610,8 +610,8 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 3d4406b1665..e4e2aef1101 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -909,11 +909,11 @@ static void __cp_set_rx_mode (struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + 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); rx_mode |= AcceptMulticast; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index b4efc913978..f61784c3c4a 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -2502,11 +2502,11 @@ static void __set_rx_mode (struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + 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); rx_mode |= AcceptMulticast; diff --git a/drivers/net/82596.c b/drivers/net/82596.c index f94d17d78bb..3a28b1f451d 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1542,7 +1542,7 @@ static void set_multicast_list(struct net_device *dev) } if (!netdev_mc_empty(dev)) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char *cp; struct mc_cmd *cmd; @@ -1552,10 +1552,10 @@ static void set_multicast_list(struct net_device *dev) cmd->cmd.command = CmdMulticastList; cmd->mc_cnt = cnt * ETH_ALEN; cp = cmd->mc_addrs; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if (!cnt--) break; - memcpy(cp, dmi->dmi_addr, ETH_ALEN); + memcpy(cp, ha->addr, ETH_ALEN); if (i596_debug > 1) DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %pM\n", dev->name, cp)); diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index bd4d829eca1..7cce643793c 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -603,7 +603,7 @@ static void lance_load_multicast (struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; @@ -618,8 +618,8 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index b8a59d255b4..d002c764a26 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1377,7 +1377,7 @@ list to the device. */ static void amd8111e_set_multicast_list(struct net_device *dev) { - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; struct amd8111e_priv *lp = netdev_priv(dev); u32 mc_filter[2] ; int bit_num; @@ -1408,8 +1408,8 @@ static void amd8111e_set_multicast_list(struct net_device *dev) /* load all the multicast addresses in the logic filter */ lp->options |= OPTION_MULTICAST_ENABLE; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mc_ptr, dev) { - bit_num = (ether_crc_le(ETH_ALEN, mc_ptr->dmi_addr) >> 26) & 0x3f; + netdev_for_each_mc_addr(ha, dev) { + bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f; mc_filter[bit_num >> 5] |= 1 << (bit_num & 31); } amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF); diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index f1f58c5e27b..a4b5b08276f 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -383,12 +383,12 @@ static void am79c961_setmulticastlist (struct net_device *dev) } else if (dev->flags & IFF_ALLMULTI) { memset(multi_hash, 0xff, sizeof(multi_hash)); } else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; memset(multi_hash, 0x00, sizeof(multi_hash)); - netdev_for_each_mc_addr(dmi, dev) - am79c961_mc_hash(dmi->dmi_addr, multi_hash); + netdev_for_each_mc_addr(ha, dev) + am79c961_mc_hash(ha->addr, multi_hash); } spin_lock_irqsave(&priv->chip_lock, flags); diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 8b23d5a175b..f31e8b6cbf7 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -556,14 +556,14 @@ static int hash_get_index(__u8 *addr) */ static void at91ether_sethashtable(struct net_device *dev) { - struct dev_mc_list *curr; + struct netdev_hw_addr *ha; unsigned long mc_filter[2]; unsigned int bitnr; mc_filter[0] = mc_filter[1] = 0; - netdev_for_each_mc_addr(curr, dev) { - bitnr = hash_get_index(curr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + bitnr = hash_get_index(ha->addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 6e2ae1d06df..f9d168775d0 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -735,7 +735,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) static void eth_set_mcast_list(struct net_device *dev) { struct port *port = netdev_priv(dev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u8 diffs[ETH_ALEN], *addr; int i; @@ -748,11 +748,11 @@ static void eth_set_mcast_list(struct net_device *dev) memset(diffs, 0, ETH_ALEN); addr = NULL; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { if (!addr) - addr = mclist->dmi_addr; /* first MAC address */ + addr = ha->addr; /* first MAC address */ for (i = 0; i < ETH_ALEN; i++) - diffs[i] |= addr[i] ^ mclist->dmi_addr[i]; + diffs[i] |= addr[i] ^ ha->addr[i]; } for (i = 0; i < ETH_ALEN; i++) { diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index e7810b74f39..6ec245c6394 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -331,16 +331,16 @@ ks8695_init_partial_multicast(struct ks8695_priv *ksp, { u32 low, high; int i; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; i = 0; - netdev_for_each_mc_addr(dmi, ndev) { + netdev_for_each_mc_addr(ha, ndev) { /* Ran out of space in chip? */ BUG_ON(i == KS8695_NR_ADDRESSES); - low = (dmi->dmi_addr[2] << 24) | (dmi->dmi_addr[3] << 16) | - (dmi->dmi_addr[4] << 8) | (dmi->dmi_addr[5]); - high = (dmi->dmi_addr[0] << 8) | (dmi->dmi_addr[1]); + low = (ha->addr[2] << 24) | (ha->addr[3] << 16) | + (ha->addr[4] << 8) | (ha->addr[5]); + high = (ha->addr[0] << 8) | (ha->addr[1]); ks8695_writereg(ksp, KS8695_AAL_(i), low); ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high); diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index 309843ab886..e2a549a60e2 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -848,12 +848,12 @@ set_rx_mode(struct net_device *dev) memset(mc_filter, 0x00, sizeof(mc_filter)); outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { unsigned int bit = - ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; + ether_crc_le(ETH_ALEN, ha->addr) >> 26; mc_filter[bit >> 3] |= (1 << bit); } outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */ diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index a5508e1b261..3d7051135c3 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -354,7 +354,7 @@ static void atl1c_set_multi(struct net_device *netdev) { struct atl1c_adapter *adapter = netdev_priv(netdev); struct atl1c_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u32 mac_ctrl_data; u32 hash_value; @@ -377,8 +377,8 @@ static void atl1c_set_multi(struct net_device *netdev) AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(mc_ptr, netdev) { - hash_value = atl1c_hash_mc_addr(hw, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + hash_value = atl1c_hash_mc_addr(hw, ha->addr); atl1c_hash_set(hw, hash_value); } } diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 7231b577912..b6605d433e9 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -284,7 +284,7 @@ static void atl1e_set_multi(struct net_device *netdev) { struct atl1e_adapter *adapter = netdev_priv(netdev); struct atl1e_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u32 mac_ctrl_data = 0; u32 hash_value; @@ -307,8 +307,8 @@ static void atl1e_set_multi(struct net_device *netdev) AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(mc_ptr, netdev) { - hash_value = atl1e_hash_mc_addr(hw, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + hash_value = atl1e_hash_mc_addr(hw, ha->addr); atl1e_hash_set(hw, hash_value); } } diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index 199f2c9ce74..078d9d1b427 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -135,7 +135,7 @@ static void atl2_set_multi(struct net_device *netdev) { struct atl2_adapter *adapter = netdev_priv(netdev); struct atl2_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u32 rctl; u32 hash_value; @@ -157,8 +157,8 @@ static void atl2_set_multi(struct net_device *netdev) ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(mc_ptr, netdev) { - hash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + hash_value = atl2_hash_mc_addr(hw, ha->addr); atl2_hash_set(hw, hash_value); } } diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index 72f3306352e..f979ea2d6d3 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c @@ -123,7 +123,7 @@ static void atlx_set_multi(struct net_device *netdev) { struct atlx_adapter *adapter = netdev_priv(netdev); struct atlx_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u32 rctl; u32 hash_value; @@ -144,8 +144,8 @@ static void atlx_set_multi(struct net_device *netdev) iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); /* compute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(mc_ptr, netdev) { - hash_value = atlx_hash_mc_addr(hw, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + hash_value = atlx_hash_mc_addr(hw, ha->addr); atlx_hash_set(hw, hash_value); } } diff --git a/drivers/net/atp.c b/drivers/net/atp.c index 6ad16205dc1..0d730c8329d 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -883,11 +883,11 @@ static void set_rx_mode_8012(struct net_device *dev) memset(mc_filter, 0xff, sizeof(mc_filter)); new_mode = CMR2h_Normal; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; + netdev_for_each_mc_addr(ha, dev) { + int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); } new_mode = CMR2h_Normal; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 4da191b87b0..29631593cc2 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -957,12 +957,12 @@ static void au1000_multicast_list(struct net_device *dev) aup->mac->control &= ~MAC_PROMISCUOUS; printk(KERN_INFO "%s: Pass all multicast\n", dev->name); } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u32 mc_filter[2]; /* Multicast hash filter */ mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) - set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, + netdev_for_each_mc_addr(ha, dev) + set_bit(ether_crc(ETH_ALEN, ha->addr)>>26, (long *)mc_filter); aup->mac->multi_hash_high = mc_filter[1]; aup->mac->multi_hash_low = mc_filter[0]; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 332c6035628..b2c5fd7b63a 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1680,15 +1680,15 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev) static int __b44_load_mcast(struct b44 *bp, struct net_device *dev) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i, num_ents; num_ents = min_t(int, netdev_mc_count(dev), B44_MCAST_TABLE_SIZE); i = 0; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i == num_ents) break; - __b44_cam_write(bp, mclist->dmi_addr, i++ + 1); + __b44_cam_write(bp, ha->addr, i++ + 1); } return i+1; } diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index 37eb8021de1..51733404478 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -603,7 +603,7 @@ static int bcm_enet_set_mac_address(struct net_device *dev, void *p) static void bcm_enet_set_multicast_list(struct net_device *dev) { struct bcm_enet_priv *priv; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; u32 val; int i; @@ -631,14 +631,14 @@ static void bcm_enet_set_multicast_list(struct net_device *dev) } i = 0; - netdev_for_each_mc_addr(mc_list, dev) { + netdev_for_each_mc_addr(ha, dev) { u8 *dmi_addr; u32 tmp; if (i == 3) break; /* update perfect match registers */ - dmi_addr = mc_list->dmi_addr; + dmi_addr = ha->addr; tmp = (dmi_addr[2] << 24) | (dmi_addr[3] << 16) | (dmi_addr[4] << 8) | dmi_addr[5]; enet_writel(priv, tmp, ENET_PML_REG(i + 1)); diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 9f53d9e86e2..61a9afdb83f 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1159,13 +1159,13 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, req->interface_id = if_id; if (netdev) { int i; - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; req->num_mac = cpu_to_le16(netdev_mc_count(netdev)); i = 0; - netdev_for_each_mc_addr(mc, netdev) - memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, netdev) + memcpy(req->mac[i].byte, ha->addr, ETH_ALEN); } else { req->promiscuous = 1; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 587f93cf03f..c488cea8f45 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -812,14 +812,14 @@ static void bfin_mac_timeout(struct net_device *dev) static void bfin_mac_multicast_hash(struct net_device *dev) { u32 emac_hashhi, emac_hashlo; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; emac_hashhi = emac_hashlo = 0; - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* skip non-multicast addresses */ if (!(*addrs & 1)) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 119468e7632..1245e983576 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -971,7 +971,7 @@ bmac_remove_multi(struct net_device *dev, */ static void bmac_set_multicast(struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; struct bmac_data *bp = netdev_priv(dev); int num_addrs = netdev_mc_count(dev); unsigned short rx_cfg; @@ -1000,8 +1000,8 @@ static void bmac_set_multicast(struct net_device *dev) rx_cfg = bmac_rx_on(dev, 0, 0); XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg)); } else { - netdev_for_each_mc_addr(dmi, dev) - bmac_addhash(bp, dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + bmac_addhash(bp, ha->addr); bmac_update_hash_table_mask(dev, bp); rx_cfg = bmac_rx_on(dev, 1, 0); XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg)); @@ -1015,7 +1015,7 @@ static void bmac_set_multicast(struct net_device *dev) static void bmac_set_multicast(struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; int i; unsigned short rx_cfg; @@ -1039,8 +1039,8 @@ static void bmac_set_multicast(struct net_device *dev) for(i = 0; i < 4; i++) hash_table[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if(!(*addrs & 1)) continue; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 381887ba677..0b69ffb7951 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3544,7 +3544,6 @@ bnx2_set_rx_mode(struct net_device *dev) } else { /* Accept one or more multicast(s). */ - struct dev_mc_list *mclist; u32 mc_filter[NUM_MC_HASH_REGISTERS]; u32 regidx; u32 bit; @@ -3552,8 +3551,8 @@ bnx2_set_rx_mode(struct net_device *dev) memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS); - netdev_for_each_mc_addr(mclist, dev) { - crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc_le(ETH_ALEN, ha->addr); bit = crc & 0xff; regidx = (bit & 0xe0) >> 5; bit &= 0x1f; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f4ea99d06c7..fa9275c2ef5 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11496,21 +11496,21 @@ static void bnx2x_set_rx_mode(struct net_device *dev) else { /* some multicasts */ if (CHIP_IS_E1(bp)) { int i, old, offset; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); i = 0; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { config->config_table[i]. cam_entry.msb_mac_addr = - swab16(*(u16 *)&mclist->dmi_addr[0]); + swab16(*(u16 *)&ha->addr[0]); config->config_table[i]. cam_entry.middle_mac_addr = - swab16(*(u16 *)&mclist->dmi_addr[2]); + swab16(*(u16 *)&ha->addr[2]); config->config_table[i]. cam_entry.lsb_mac_addr = - swab16(*(u16 *)&mclist->dmi_addr[4]); + swab16(*(u16 *)&ha->addr[4]); config->config_table[i].cam_entry.flags = cpu_to_le16(port); config->config_table[i]. @@ -11564,18 +11564,18 @@ static void bnx2x_set_rx_mode(struct net_device *dev) 0); } else { /* E1H */ /* Accept one or more multicasts */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u32 mc_filter[MC_HASH_SIZE]; u32 crc, bit, regidx; int i; memset(mc_filter, 0, 4 * MC_HASH_SIZE); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n", - mclist->dmi_addr); + ha->addr); - crc = crc32c_le(0, mclist->dmi_addr, ETH_ALEN); + crc = crc32c_le(0, ha->addr, ETH_ALEN); bit = (crc >> 24) & 0xff; regidx = bit >> 5; bit &= 0x1f; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d6ae63b2cf0..22682f1c847 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -761,32 +761,6 @@ static int bond_check_dev_link(struct bonding *bond, /*----------------------------- Multicast list ------------------------------*/ -/* - * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise - */ -static inline int bond_is_dmi_same(const struct dev_mc_list *dmi1, - const struct dev_mc_list *dmi2) -{ - return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 && - dmi1->dmi_addrlen == dmi2->dmi_addrlen; -} - -/* - * returns dmi entry if found, NULL otherwise - */ -static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, - struct dev_mc_list *mc_list) -{ - struct dev_mc_list *idmi; - - for (idmi = mc_list; idmi; idmi = idmi->next) { - if (bond_is_dmi_same(dmi, idmi)) - return idmi; - } - - return NULL; -} - /* * Push the promiscuity flag down to appropriate slaves */ @@ -839,18 +813,18 @@ static int bond_set_allmulti(struct bonding *bond, int inc) * Add a Multicast address to slaves * according to mode */ -static void bond_mc_add(struct bonding *bond, void *addr, int alen) +static void bond_mc_add(struct bonding *bond, void *addr) { if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) - dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); + dev_mc_add(bond->curr_active_slave->dev, addr); } else { struct slave *slave; int i; bond_for_each_slave(bond, slave, i) - dev_mc_add(slave->dev, addr, alen, 0); + dev_mc_add(slave->dev, addr); } } @@ -858,18 +832,17 @@ static void bond_mc_add(struct bonding *bond, void *addr, int alen) * Remove a multicast address from slave * according to mode */ -static void bond_mc_delete(struct bonding *bond, void *addr, int alen) +static void bond_mc_del(struct bonding *bond, void *addr) { if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) - dev_mc_delete(bond->curr_active_slave->dev, addr, - alen, 0); + dev_mc_del(bond->curr_active_slave->dev, addr); } else { struct slave *slave; int i; bond_for_each_slave(bond, slave, i) { - dev_mc_delete(slave->dev, addr, alen, 0); + dev_mc_del(slave->dev, addr); } } } @@ -895,50 +868,6 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) rcu_read_unlock(); } -/* - * Totally destroys the mc_list in bond - */ -static void bond_mc_list_destroy(struct bonding *bond) -{ - struct dev_mc_list *dmi; - - dmi = bond->mc_list; - while (dmi) { - bond->mc_list = dmi->next; - kfree(dmi); - dmi = bond->mc_list; - } - - bond->mc_list = NULL; -} - -/* - * Copy all the Multicast addresses from src to the bonding device dst - */ -static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, - gfp_t gfp_flag) -{ - struct dev_mc_list *dmi, *new_dmi; - - for (dmi = mc_list; dmi; dmi = dmi->next) { - new_dmi = kmalloc(sizeof(struct dev_mc_list), gfp_flag); - - if (!new_dmi) { - /* FIXME: Potential memory leak !!! */ - return -ENOMEM; - } - - new_dmi->next = bond->mc_list; - bond->mc_list = new_dmi; - new_dmi->dmi_addrlen = dmi->dmi_addrlen; - memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); - new_dmi->dmi_users = dmi->dmi_users; - new_dmi->dmi_gusers = dmi->dmi_gusers; - } - - return 0; -} - /* * flush all members of flush->mc_list from device dev->mc_list */ @@ -946,16 +875,16 @@ static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; - for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) - dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); + netdev_for_each_mc_addr(ha, bond_dev) + dev_mc_del(slave_dev, ha->addr); if (bond->params.mode == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; - dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0); + dev_mc_del(slave_dev, lacpdu_multicast); } } @@ -969,7 +898,7 @@ static void bond_mc_list_flush(struct net_device *bond_dev, static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; if (!USES_PRIMARY(bond->params.mode)) /* nothing to do - mc list is already up-to-date on @@ -984,9 +913,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, if (bond->dev->flags & IFF_ALLMULTI) dev_set_allmulti(old_active->dev, -1); - for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) - dev_mc_delete(old_active->dev, dmi->dmi_addr, - dmi->dmi_addrlen, 0); + netdev_for_each_mc_addr(ha, bond->dev) + dev_mc_del(old_active->dev, ha->addr); } if (new_active) { @@ -997,9 +925,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, if (bond->dev->flags & IFF_ALLMULTI) dev_set_allmulti(new_active->dev, 1); - for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) - dev_mc_add(new_active->dev, dmi->dmi_addr, - dmi->dmi_addrlen, 0); + netdev_for_each_mc_addr(ha, bond->dev) + dev_mc_add(new_active->dev, ha->addr); bond_resend_igmp_join_requests(bond); } } @@ -1406,7 +1333,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) struct bonding *bond = netdev_priv(bond_dev); const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct slave *new_slave = NULL; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; struct sockaddr addr; int link_reporting; int old_features = bond_dev->features; @@ -1492,7 +1419,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* Flush unicast and multicast addresses */ dev_uc_flush(bond_dev); - dev_addr_discard(bond_dev); + dev_mc_flush(bond_dev); if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); @@ -1601,9 +1528,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) netif_addr_lock_bh(bond_dev); /* upload master's mc_list to new slave */ - for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) - dev_mc_add(slave_dev, dmi->dmi_addr, - dmi->dmi_addrlen, 0); + netdev_for_each_mc_addr(ha, bond_dev) + dev_mc_add(slave_dev, ha->addr); netif_addr_unlock_bh(bond_dev); } @@ -1611,7 +1537,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* add lacpdu mc addr to mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; - dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0); + dev_mc_add(slave_dev, lacpdu_multicast); } bond_add_vlans_on_slave(bond, slave_dev); @@ -3913,10 +3839,24 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd return res; } +static bool bond_addr_in_mc_list(unsigned char *addr, + struct netdev_hw_addr_list *list, + int addrlen) +{ + struct netdev_hw_addr *ha; + + netdev_hw_addr_list_for_each(ha, list) + if (!memcmp(ha->addr, addr, addrlen)) + return true; + + return false; +} + static void bond_set_multicast_list(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; + bool found; /* * Do promisc before checking multicast_mode @@ -3951,20 +3891,25 @@ static void bond_set_multicast_list(struct net_device *bond_dev) bond->flags = bond_dev->flags; /* looking for addresses to add to slaves' mc list */ - for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { - if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) - bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); + netdev_for_each_mc_addr(ha, bond_dev) { + found = bond_addr_in_mc_list(ha->addr, &bond->mc_list, + bond_dev->addr_len); + if (!found) + bond_mc_add(bond, ha->addr); } /* looking for addresses to delete from slaves' list */ - for (dmi = bond->mc_list; dmi; dmi = dmi->next) { - if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) - bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); + netdev_hw_addr_list_for_each(ha, &bond->mc_list) { + found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc, + bond_dev->addr_len); + if (!found) + bond_mc_del(bond, ha->addr); } /* save master's multicast list */ - bond_mc_list_destroy(bond); - bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); + __hw_addr_flush(&bond->mc_list); + __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc, + bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST); read_unlock(&bond->lock); } @@ -4534,9 +4479,7 @@ static void bond_uninit(struct net_device *bond_dev) if (bond->wq) destroy_workqueue(bond->wq); - netif_addr_lock_bh(bond_dev); - bond_mc_list_destroy(bond); - netif_addr_unlock_bh(bond_dev); + __hw_addr_flush(&bond->mc_list); } /*------------------------- Module initialization ---------------------------*/ @@ -4908,6 +4851,8 @@ static int bond_init(struct net_device *bond_dev) list_add_tail(&bond->bond_list, &bn->dev_list); bond_prepare_sysfs_group(bond); + + __hw_addr_init(&bond->mc_list); return 0; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 257a7a4dfce..2aa33672059 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -202,7 +202,7 @@ struct bonding { char proc_file_name[IFNAMSIZ]; #endif /* CONFIG_PROC_FS */ struct list_head bond_list; - struct dev_mc_list *mc_list; + struct netdev_hw_addr_list mc_list; int (*xmit_hash_policy)(struct sk_buff *, int); __be32 master_ip; u16 flags; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 9bd155e4111..bd857a20a75 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2957,20 +2957,20 @@ static void cas_process_mc_list(struct cas *cp) { u16 hash_table[16]; u32 crc; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i = 1; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(dmi, cp->dev) { + netdev_for_each_mc_addr(ha, cp->dev) { if (i <= CAS_MC_EXACT_MATCH_SIZE) { /* use the alternate mac address registers for the * first 15 multicast addresses */ - writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], + writel((ha->addr[4] << 8) | ha->addr[5], cp->regs + REG_MAC_ADDRN(i*3 + 0)); - writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], + writel((ha->addr[2] << 8) | ha->addr[3], cp->regs + REG_MAC_ADDRN(i*3 + 1)); - writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], + writel((ha->addr[0] << 8) | ha->addr[1], cp->regs + REG_MAC_ADDRN(i*3 + 2)); i++; } @@ -2978,7 +2978,7 @@ static void cas_process_mc_list(struct cas *cp) /* use hw hash table for the next series of * multicast addresses */ - crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); + crc = ether_crc_le(ETH_ALEN, ha->addr); crc >>= 24; hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); } diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index a6eb30a6e2b..13fd9628db1 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -376,12 +376,13 @@ static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN; } else if (t1_rx_mode_mc_cnt(rm)) { /* Accept one or more multicast(s). */ - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int bit; u16 mc_filter[4] = { 0, }; - netdev_for_each_mc_addr(dmi, t1_get_netdev(rm)) { - bit = (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 23) & 0x3f; /* bit[23:28] */ + netdev_for_each_mc_addr(ha, t1_get_netdev(rm)) { + /* bit[23:28] */ + bit = (ether_crc(ETH_ALEN, ha->addr) >> 23) & 0x3f; mc_filter[bit >> 4] |= 1 << (bit & 0xf); } pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]); diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 60777fd90b3..bdfff784645 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -328,7 +328,7 @@ static int cpmac_config(struct net_device *dev, struct ifmap *map) static void cpmac_set_multicast_list(struct net_device *dev) { - struct dev_mc_list *iter; + struct netdev_hw_addr *ha; u8 tmp; u32 mbp, bit, hash[2] = { 0, }; struct cpmac_priv *priv = netdev_priv(dev); @@ -348,19 +348,19 @@ static void cpmac_set_multicast_list(struct net_device *dev) * cpmac uses some strange mac address hashing * (not crc32) */ - netdev_for_each_mc_addr(iter, dev) { + netdev_for_each_mc_addr(ha, dev) { bit = 0; - tmp = iter->dmi_addr[0]; + tmp = ha->addr[0]; bit ^= (tmp >> 2) ^ (tmp << 4); - tmp = iter->dmi_addr[1]; + tmp = ha->addr[1]; bit ^= (tmp >> 4) ^ (tmp << 2); - tmp = iter->dmi_addr[2]; + tmp = ha->addr[2]; bit ^= (tmp >> 6) ^ tmp; - tmp = iter->dmi_addr[3]; + tmp = ha->addr[3]; bit ^= (tmp >> 2) ^ (tmp << 4); - tmp = iter->dmi_addr[4]; + tmp = ha->addr[4]; bit ^= (tmp >> 4) ^ (tmp << 2); - tmp = iter->dmi_addr[5]; + tmp = ha->addr[5]; bit ^= (tmp >> 6) ^ tmp; bit &= 0x3f; hash[bit / 32] |= 1 << (bit % 32); diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index dd24aadb778..59110bc119a 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1596,16 +1596,16 @@ set_multicast_list(struct net_device *dev) } else { /* MC mode, receive normal and MC packets */ char hash_ix; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *baddr; lo_bits = 0x00000000ul; hi_bits = 0x00000000ul; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { /* Calculate the hash index for the GA registers */ hash_ix = 0; - baddr = dmi->dmi_addr; + baddr = ha->addr; hash_ix ^= (*baddr) & 0x3f; hash_ix ^= ((*baddr) >> 6) & 0x03; ++baddr; diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index c142a2132e9..3af19a55037 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -311,16 +311,16 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev) if (dev->flags & IFF_ALLMULTI) hash_lo = hash_hi = 0xffffffff; else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int exact_addr_idx = mac->nucast; hash_lo = hash_hi = 0; - netdev_for_each_mc_addr(dmi, dev) + netdev_for_each_mc_addr(ha, dev) if (exact_addr_idx < EXACT_ADDR_FILTERS) set_addr_filter(mac, exact_addr_idx++, - dmi->dmi_addr); + ha->addr); else { - int hash = hash_hw_addr(dmi->dmi_addr); + int hash = hash_hw_addr(ha->addr); if (hash < 32) hash_lo |= (1 << hash); diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2b8edd2efbf..1f9df5c6a75 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -952,13 +952,14 @@ static void emac_dev_mcast_set(struct net_device *ndev) emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); } if (!netdev_mc_empty(ndev)) { - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; + mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); /* program multicast address list into EMAC hardware */ - netdev_for_each_mc_addr(mc_ptr, ndev) { + netdev_for_each_mc_addr(ha, ndev) { emac_add_mcast(priv, EMAC_MULTICAST_ADD, - (u8 *) mc_ptr->dmi_addr); + (u8 *) ha->addr); } } else { mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST); diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 8cf3cc6f20e..fb3f0984c28 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -940,7 +940,7 @@ static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile u16 *ib = (volatile u16 *)dev->mem_start; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; @@ -959,8 +959,8 @@ static void lance_load_multicast(struct net_device *dev) *lib_ptr(ib, filter[3], lp->type) = 0; /* Add addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index ed53a8d45f4..e5667c55844 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -2195,7 +2195,7 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) { DFX_board_t *bp = netdev_priv(dev); int i; /* used as index in for loop */ - struct dev_mc_list *dmi; /* ptr to multicast addr entry */ + struct netdev_hw_addr *ha; /* Enable LLC frame promiscuous mode, if necessary */ @@ -2241,9 +2241,9 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) /* Copy addresses to multicast address table, then update adapter CAM */ i = 0; - netdev_for_each_mc_addr(dmi, dev) + netdev_for_each_mc_addr(ha, dev) memcpy(&bp->mc_table[i++ * FDDI_K_ALEN], - dmi->dmi_addr, FDDI_K_ALEN); + ha->addr, FDDI_K_ALEN); if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS) { diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 744c1928dfc..a88300a0d1e 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1272,7 +1272,7 @@ static void set_multicast_list(struct net_device *dev) static void SetMulticastFilter(struct net_device *dev) { struct depca_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; int i, j, bit, byte; u16 hashcode; @@ -1287,8 +1287,8 @@ static void SetMulticastFilter(struct net_device *dev) lp->init_block.mcast_table[i] = 0; } /* Add multicast addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc(ETH_ALEN, addrs); hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index b05bad82982..6579225dbd9 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1132,14 +1132,14 @@ set_multicast (struct net_device *dev) /* Receive broadcast and multicast frames */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; /* Receive broadcast frames and multicast frames filtering by Hashtable */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { int bit, index = 0; - int crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); + 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++) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 1c67f1138ca..989f2beb123 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -724,7 +724,7 @@ static void dm9000_hash_table(struct net_device *dev) { board_info_t *db = netdev_priv(dev); - struct dev_mc_list *mcptr; + struct netdev_hw_addr *ha; int i, oft; u32 hash_val; u16 hash_table[4]; @@ -752,8 +752,8 @@ dm9000_hash_table(struct net_device *dev) rcr |= RCR_ALL; /* the multicast address in Hash Table : 64 bits */ - netdev_for_each_mc_addr(mcptr, dev) { - hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; + netdev_for_each_mc_addr(ha, dev) { + hash_val = ether_crc_le(6, ha->addr) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index c0cd5765668..3e8d0005540 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1545,16 +1545,16 @@ static int e100_hw_init(struct nic *nic) static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) { struct net_device *netdev = nic->netdev; - struct dev_mc_list *list; + struct netdev_hw_addr *ha; u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); cb->command = cpu_to_le16(cb_multi); cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); i = 0; - netdev_for_each_mc_addr(list, netdev) { + netdev_for_each_mc_addr(ha, netdev) { if (i == count) break; - memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &list->dmi_addr, + memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, ETH_ALEN); } } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 8be6faee43e..41330349b07 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2101,7 +2101,6 @@ static void e1000_set_rx_mode(struct net_device *netdev) struct e1000_hw *hw = &adapter->hw; struct netdev_hw_addr *ha; bool use_uc = false; - struct dev_addr_list *mc_ptr; u32 rctl; u32 hash_value; int i, rar_entries = E1000_RAR_ENTRIES; @@ -2161,17 +2160,17 @@ static void e1000_set_rx_mode(struct net_device *netdev) WARN_ON(i == rar_entries); - netdev_for_each_mc_addr(mc_ptr, netdev) { + netdev_for_each_mc_addr(ha, netdev) { if (i == rar_entries) { /* load any remaining addresses into the hash table */ u32 hash_reg, hash_bit, mta; - hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr); + hash_value = e1000_hash_mc_addr(hw, ha->addr); hash_reg = (hash_value >> 5) & 0x7F; hash_bit = hash_value & 0x1F; mta = (1 << hash_bit); mcarray[hash_reg] |= mta; } else { - e1000_rar_set(hw, mc_ptr->da_addr, i++); + e1000_rar_set(hw, ha->addr, i++); } } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 5304959ae1f..02f7d20f3c8 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2567,7 +2567,7 @@ static void e1000_set_multi(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 *mta_list; u32 rctl; int i; @@ -2599,9 +2599,8 @@ static void e1000_set_multi(struct net_device *netdev) /* prepare a packed array of only addresses. */ i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) - memcpy(mta_list + (i++ * ETH_ALEN), - mc_ptr->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); e1000_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 15d6266b80c..b01e6997403 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1287,7 +1287,7 @@ set_multicast_list(struct net_device *dev) struct eepro_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; unsigned short mode; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int mc_count = netdev_mc_count(dev); if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) @@ -1332,8 +1332,8 @@ set_multicast_list(struct net_device *dev) outw(0, ioaddr + IO_PORT); outw(6 * (mc_count + 1), ioaddr + IO_PORT); - netdev_for_each_mc_addr(dmi, dev) { - eaddrs = (unsigned short *) dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + eaddrs = (unsigned short *) ha->addr; outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 7013dc8a6cb..b3882fd8db6 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -1576,7 +1576,7 @@ static void eexp_hw_init586(struct net_device *dev) static void eexp_setup_filter(struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned short ioaddr = dev->base_addr; int count = netdev_mc_count(dev); int i; @@ -1589,8 +1589,8 @@ static void eexp_setup_filter(struct net_device *dev) outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR); outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST)); i = 0; - netdev_for_each_mc_addr(dmi, dev) { - unsigned short *data = (unsigned short *) dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + unsigned short *data = (unsigned short *) ha->addr; if (i == count) break; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index b004eaba3d7..b97411aaa77 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1966,7 +1966,7 @@ static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr) static void ehea_set_multicast_list(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); - struct dev_mc_list *k_mcl_entry; + struct netdev_hw_addr *ha; int ret; if (dev->flags & IFF_PROMISC) { @@ -1997,8 +1997,8 @@ static void ehea_set_multicast_list(struct net_device *dev) goto out; } - netdev_for_each_mc_addr(k_mcl_entry, dev) - ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + ehea_add_multicast_entry(port, ha->addr); } out: diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 6d70c349c95..1232887c243 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -822,7 +822,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr) static void enic_set_multicast_list(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); - struct dev_mc_list *list; + struct netdev_hw_addr *ha; int directed = 1; int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; @@ -852,10 +852,10 @@ static void enic_set_multicast_list(struct net_device *netdev) */ i = 0; - netdev_for_each_mc_addr(list, netdev) { + netdev_for_each_mc_addr(ha, netdev) { if (i == mc_count) break; - memcpy(mc_addr[i++], list->dmi_addr, ETH_ALEN); + memcpy(mc_addr[i++], ha->addr, ETH_ALEN); } for (i = 0; i < enic->mc_count; i++) { diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 39c271b6be4..f6584a1ad3b 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1400,12 +1400,12 @@ static void set_rx_mode(struct net_device *dev) outl(0x0004, ioaddr + RxCtrl); return; } else { /* Never executed, for now. */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { unsigned int bit_nr = - ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; + ether_crc_le(ETH_ALEN, ha->addr) & 0x3f; mc_filter[bit_nr >> 3] |= (1 << bit_nr); } } diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 209742304e2..f6be5aeaf94 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -755,7 +755,7 @@ static void ethoc_set_multicast_list(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); u32 mode = ethoc_read(priv, MODER); - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; u32 hash[2] = { 0, 0 }; /* set loopback mode if requested */ @@ -783,8 +783,8 @@ static void ethoc_set_multicast_list(struct net_device *dev) hash[0] = 0xffffffff; hash[1] = 0xffffffff; } else { - netdev_for_each_mc_addr(mc, dev) { - u32 crc = ether_crc(ETH_ALEN, mc->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + u32 crc = ether_crc(ETH_ALEN, ha->addr); int bit = (crc >> 26) & 0x3f; hash[bit >> 5] |= 1 << (bit & 0x1f); } diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index a2bade58688..11ba70f4997 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1169,7 +1169,7 @@ static void set_multicast_list(struct net_device *dev) static void SetMulticastFilter(struct net_device *dev) { struct ewrk3_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u_long iobase = dev->base_addr; int i; char *addrs, bit, byte; @@ -1213,8 +1213,8 @@ static void SetMulticastFilter(struct net_device *dev) } /* Update table */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 9d5ad08a119..e8a2705237b 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1792,12 +1792,12 @@ static void __set_rx_mode(struct net_device *dev) memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = CR_W_AB | CR_W_AM; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { unsigned int bit; - bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; + bit = (ether_crc(ETH_ALEN, ha->addr) >> 26) ^ 0x3F; mc_filter[bit >> 5] |= (1 << bit); } rx_mode = CR_W_AB | CR_W_AM; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 848eb1968ab..2b1651aee13 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -954,7 +954,7 @@ fec_enet_close(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned int i, bit, data, crc, tmp; unsigned char hash; @@ -984,16 +984,16 @@ static void set_multicast_list(struct net_device *dev) writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { /* Only support group multicast for now */ - if (!(dmi->dmi_addr[0] & 1)) + if (!(ha->addr[0] & 1)) continue; /* calculate crc32 value of mac address */ crc = 0xffffffff; - for (i = 0; i < dmi->dmi_addrlen; i++) { - data = dmi->dmi_addr[i]; + for (i = 0; i < dev->addr_len; i++) { + data = ha->addr[i]; for (bit = 0; bit < 8; bit++, data >>= 1) { crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0); diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 704155e2bdd..667ba1391b9 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -574,12 +574,12 @@ static void mpc52xx_fec_set_multicast_list(struct net_device *dev) out_be32(&fec->gaddr2, 0xffffffff); } else { u32 crc; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u32 gaddr1 = 0x00000000; u32 gaddr2 = 0x00000000; - netdev_for_each_mc_addr(dmi, dev) { - crc = ether_crc_le(6, dmi->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc_le(6, ha->addr) >> 26; if (crc >= 32) gaddr1 |= 1 << (crc-32); else diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index ca05e566202..6a2b64f0a7d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3103,12 +3103,14 @@ static void nv_set_multicast(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0; } else { - struct dev_mc_list *walk; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(walk, dev) { + netdev_for_each_mc_addr(ha, dev) { + unsigned char *addr = ha->addr; u32 a, b; - a = le32_to_cpu(*(__le32 *) walk->dmi_addr); - b = le16_to_cpu(*(__le16 *) (&walk->dmi_addr[4])); + + a = le32_to_cpu(*(__le32 *) addr); + b = le16_to_cpu(*(__le16 *) (&addr[4])); alwaysOn[0] &= a; alwaysOff[0] &= ~a; alwaysOn[1] &= b; diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index cf4f674f9e2..b3bad7c15d0 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -231,12 +231,12 @@ static void set_multicast_finish(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct dev_mc_list *pmc; + struct netdev_hw_addr *ha; if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - netdev_for_each_mc_addr(pmc, dev) - set_multicast_one(dev, pmc->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + set_multicast_one(dev, ha->addr); set_multicast_finish(dev); } else set_promiscuous_mode(dev); diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index cd2c6cca5f2..75974c6d201 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -232,12 +232,12 @@ static void set_multicast_finish(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct dev_mc_list *pmc; + struct netdev_hw_addr *ha; if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - netdev_for_each_mc_addr(pmc, dev) - set_multicast_one(dev, pmc->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + set_multicast_one(dev, ha->addr); set_multicast_finish(dev); } else set_promiscuous_mode(dev); diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index c490a466cae..0ab6a346a19 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -224,12 +224,12 @@ static void set_multicast_finish(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct dev_mc_list *pmc; + struct netdev_hw_addr *ha; if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - netdev_for_each_mc_addr(pmc, dev) - set_multicast_one(dev, pmc->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + set_multicast_one(dev, ha->addr); set_multicast_finish(dev); } else set_promiscuous_mode(dev); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b6715553cf1..fdd26c2b1a2 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2797,7 +2797,7 @@ static void adjust_link(struct net_device *dev) * whenever dev->flags is changed */ static void gfar_set_multi(struct net_device *dev) { - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; struct gfar_private *priv = netdev_priv(dev); struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 tempval; @@ -2870,13 +2870,12 @@ static void gfar_set_multi(struct net_device *dev) return; /* Parse the list, and set the appropriate bits */ - netdev_for_each_mc_addr(mc_ptr, dev) { + netdev_for_each_mc_addr(ha, dev) { if (idx < em_num) { - gfar_set_mac_for_addr(dev, idx, - mc_ptr->dmi_addr); + gfar_set_mac_for_addr(dev, idx, ha->addr); idx++; } else - gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr); + gfar_set_hash_for_addr(dev, ha->addr); } } diff --git a/drivers/net/greth.c b/drivers/net/greth.c index c5e0d28a6de..fbe6ab6b919 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -988,7 +988,7 @@ static u32 greth_hash_get_index(__u8 *addr) static void greth_set_hash_filter(struct net_device *dev) { - struct dev_mc_list *curr; + struct netdev_hw_addr *ha; struct greth_private *greth = netdev_priv(dev); struct greth_regs *regs = (struct greth_regs *) greth->regs; u32 mc_filter[2]; @@ -996,8 +996,8 @@ static void greth_set_hash_filter(struct net_device *dev) mc_filter[0] = mc_filter[1] = 0; - netdev_for_each_mc_addr(curr, dev) { - bitnr = greth_hash_get_index(curr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + bitnr = greth_hash_get_index(ha->addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 373546dd083..2bfcca6d180 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1858,12 +1858,12 @@ static void set_rx_mode(struct net_device *dev) /* Too many to match, or accept all multicasts. */ writew(0x000B, ioaddr + AddrMode); } else if (!netdev_mc_empty(dev)) { /* Must use the CAM filter. */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i = 0; - netdev_for_each_mc_addr(mclist, dev) { - writel(*(u32*)(mclist->dmi_addr), ioaddr + 0x100 + i*8); - writel(0x20000 | (*(u16*)&mclist->dmi_addr[4]), + netdev_for_each_mc_addr(ha, dev) { + writel(*(u32 *)(ha->addr), ioaddr + 0x100 + i*8); + writel(0x20000 | (*(u16 *)&ha->addr[4]), ioaddr + 0x104 + i*8); i++; } diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index b766a69bf0c..86b2b433234 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2100,15 +2100,15 @@ static void hp100_set_multicast_list(struct net_device *dev) } else { int i, idx; u_char *addrs; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; memset(&lp->hash_bytes, 0x00, 8); #ifdef HP100_DEBUG printk("hp100: %s: computing hash filter - mc_count = %i\n", dev->name, netdev_mc_count(dev)); #endif - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if ((*addrs & 0x01) == 0x01) { /* multicast address? */ #ifdef HP100_DEBUG printk("hp100: %s: multicast = %pM, ", diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index d8533a4ef82..40c78507ef1 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -388,18 +388,19 @@ static void emac_hash_mc(struct emac_instance *dev) const int regs = EMAC_XAHT_REGS(dev); u32 *gaht_base = emac_gaht_base(dev); u32 gaht_temp[regs]; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i; DBG(dev, "hash_mc %d" NL, netdev_mc_count(dev->ndev)); memset(gaht_temp, 0, sizeof (gaht_temp)); - netdev_for_each_mc_addr(dmi, dev->ndev) { + netdev_for_each_mc_addr(ha, dev->ndev) { int slot, reg, mask; - DBG2(dev, "mc %pM" NL, dmi->dmi_addr); + DBG2(dev, "mc %pM" NL, ha->addr); - slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr)); + slot = EMAC_XAHT_CRC_TO_SLOT(dev, + ether_crc(ETH_ALEN, ha->addr)); reg = EMAC_XAHT_SLOT_TO_REG(dev, slot); mask = EMAC_XAHT_SLOT_TO_MASK(dev, slot); @@ -1176,7 +1177,7 @@ static int emac_open(struct net_device *ndev) netif_carrier_on(dev->ndev); /* Required for Pause packet support in EMAC */ - dev_mc_add(ndev, default_mcast_addr, sizeof(default_mcast_addr), 1); + dev_mc_add_global(ndev, default_mcast_addr); emac_configure(dev); mal_poll_add(dev->mal, &dev->commac); diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index b5d0f4e973f..76949e08ee8 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -385,7 +385,7 @@ static void InitBoard(struct net_device *dev) int camcnt; camentry_t cams[16]; u32 cammask; - struct dev_mc_list *mcptr; + struct netdev_hw_addr *ha; u16 rcrval; /* reset the SONIC */ @@ -420,8 +420,8 @@ static void InitBoard(struct net_device *dev) /* start putting the multicast addresses into the CAM list. Stop if it is full. */ - netdev_for_each_mc_addr(mcptr, dev) { - putcam(cams, &camcnt, mcptr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + putcam(cams, &camcnt, ha->addr); if (camcnt == 16) break; } @@ -479,7 +479,7 @@ static void InitBoard(struct net_device *dev) /* if still multicast addresses left or ALLMULTI is set, set the multicast enable bit */ - if ((dev->flags & IFF_ALLMULTI) || (mcptr != NULL)) + if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > camcnt) rcrval |= RCREG_AMC; /* promiscous mode ? */ diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 0bc777bac9b..f468590ed45 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1072,7 +1072,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); } } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; /* clear the filter table & disable filtering */ lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableRecv | @@ -1083,10 +1083,10 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); } /* add the addresses to the filter table */ - netdev_for_each_mc_addr(mclist, netdev) { + netdev_for_each_mc_addr(ha, netdev) { // add the multicast address to the filter table unsigned long mcast_addr = 0; - memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); + memcpy(((char *)&mcast_addr)+2, ha->addr, 6); lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastAddFilter, mcast_addr); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ea875709f05..78cc742e233 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2864,7 +2864,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 *mta_list; int i; @@ -2881,8 +2881,8 @@ static int igb_write_mc_addr_list(struct net_device *netdev) /* The shared function expects a packed array of only addresses. */ i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) - memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); igb_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index a77afd8a14b..ea8abf5c1ef 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1399,7 +1399,7 @@ static void igbvf_set_multi(struct net_device *netdev) { struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 *mta_list = NULL; int i; @@ -1414,8 +1414,8 @@ static void igbvf_set_multi(struct net_device *netdev) /* prepare a packed array of only addresses. */ i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) - memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0); kfree(mta_list); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 70871b9b045..57d873da978 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1664,7 +1664,7 @@ static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static void ioc3_set_multicast_list(struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; struct ioc3_private *ip = netdev_priv(dev); struct ioc3 *ioc3 = ip->regs; u64 ehar = 0; @@ -1688,8 +1688,8 @@ static void ioc3_set_multicast_list(struct net_device *dev) ip->ehar_h = 0xffffffff; ip->ehar_l = 0xffffffff; } else { - netdev_for_each_mc_addr(dmi, dev) { - char *addr = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + char *addr = ha->addr; if (!(*addr & 1)) continue; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 0d7ad3f2d0f..67cfc7d9d89 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -569,7 +569,7 @@ static int ipg_config_autoneg(struct net_device *dev) static void ipg_nic_set_multicast_list(struct net_device *dev) { void __iomem *ioaddr = ipg_ioaddr(dev); - struct dev_mc_list *mc_list_ptr; + struct netdev_hw_addr *ha; unsigned int hashindex; u32 hashtable[2]; u8 receivemode; @@ -608,9 +608,9 @@ static void ipg_nic_set_multicast_list(struct net_device *dev) hashtable[1] = 0x00000000; /* Cycle through all multicast addresses to filter. */ - netdev_for_each_mc_addr(mc_list_ptr, dev) { + netdev_for_each_mc_addr(ha, dev) { /* Calculate CRC result for each multicast address. */ - hashindex = crc32_le(0xffffffff, mc_list_ptr->dmi_addr, + hashindex = crc32_le(0xffffffff, ha->addr, ETH_ALEN); /* Use only the least significant 6 bits. */ diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index e6e972d9b7c..cd65b8629bc 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -961,15 +961,15 @@ static void veth_set_multicast_list(struct net_device *dev) (netdev_mc_count(dev) > VETH_MAX_MCAST)) { port->promiscuous = 1; } else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; port->promiscuous = 0; /* Update table */ port->num_mcast = 0; - netdev_for_each_mc_addr(dmi, dev) { - u8 *addr = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + u8 *addr = ha->addr; u64 xaddr = 0; if (addr[0] & 0x01) {/* multicast address? */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index c9fef65cb98..912dd1d5772 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1058,7 +1058,7 @@ ixgb_set_multi(struct net_device *netdev) { struct ixgb_adapter *adapter = netdev_priv(netdev); struct ixgb_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u32 rctl; int i; @@ -1089,9 +1089,9 @@ ixgb_set_multi(struct net_device *netdev) IXGB_WRITE_REG(hw, RCTL, rctl); i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) + netdev_for_each_mc_addr(ha, netdev) memcpy(&mta[i++ * IXGB_ETH_LENGTH_OF_ADDRESS], - mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS); + ha->addr, IXGB_ETH_LENGTH_OF_ADDRESS); ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0); } diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 4d1c3a42945..6eb5814ca7d 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1494,7 +1494,7 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, struct net_device *netdev) { - struct dev_addr_list *dmi; + struct netdev_hw_addr *ha; u32 i; /* @@ -1510,9 +1510,9 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); /* Add the new addresses */ - netdev_for_each_mc_addr(dmi, netdev) { + netdev_for_each_mc_addr(ha, netdev) { hw_dbg(hw, " Adding the multicast addresses:\n"); - ixgbe_set_mta(hw, dmi->dmi_addr); + ixgbe_set_mta(hw, ha->addr); } /* Enable mta */ diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c index f457c52b5ed..852e9c4fd93 100644 --- a/drivers/net/ixgbevf/vf.c +++ b/drivers/net/ixgbevf/vf.c @@ -259,7 +259,7 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, struct net_device *netdev) { - struct dev_addr_list *dmi; + struct netdev_hw_addr *ha; struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; u16 *vector_list = (u16 *)&msgbuf[1]; @@ -281,10 +281,10 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT; i = 0; - netdev_for_each_mc_addr(dmi, netdev) { + netdev_for_each_mc_addr(ha, netdev) { if (i == cnt) break; - vector_list[i++] = ixgbevf_mta_vector(hw, dmi->dmi_addr); + vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr); } mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE); diff --git a/drivers/net/jme.c b/drivers/net/jme.c index c0b59a55538..10e816d2caf 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2009,12 +2009,12 @@ jme_set_multi(struct net_device *netdev) } else if (netdev->flags & IFF_ALLMULTI) { jme->reg_rxmcs |= RXMCS_ALLMULFRAME; } else if (netdev->flags & IFF_MULTICAST) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int bit_nr; jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; - netdev_for_each_mc_addr(mclist, netdev) { - bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; + netdev_for_each_mc_addr(ha, netdev) { + bit_nr = ether_crc(ETH_ALEN, ha->addr) & 0x3F; mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); } diff --git a/drivers/net/korina.c b/drivers/net/korina.c index edaedc7aa03..26bf1b76b99 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -482,7 +482,7 @@ static void korina_multicast_list(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); unsigned long flags; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u32 recognise = ETH_ARC_AB; /* always accept broadcasts */ int i; @@ -502,8 +502,8 @@ static void korina_multicast_list(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - char *addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + char *addrs = ha->addr; if (!(*addrs & 1)) continue; diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 66be4e449f0..4dcd61f81ec 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -956,13 +956,13 @@ static void ks8851_set_rx_mode(struct net_device *dev) rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA | RXCR1_RXMAFMA); } else if (dev->flags & IFF_MULTICAST && !netdev_mc_empty(dev)) { - struct dev_mc_list *mcptr; + struct netdev_hw_addr *ha; u32 crc; /* accept some multicast */ - netdev_for_each_mc_addr(mcptr, dev) { - crc = ether_crc(ETH_ALEN, mcptr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc(ETH_ALEN, ha->addr); crc >>= (32 - 6); /* get top six bits */ rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf)); diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index ee3fe30b2ad..70a3d98f4bd 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -362,7 +362,6 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; #define MAX_MCAST_LST 32 #define HW_MCAST_SIZE 8 -#define MAC_ADDR_LEN 6 /** * union ks_tx_hdr - tx header data @@ -450,7 +449,7 @@ struct ks_net { u16 promiscuous; u16 all_mcast; u16 mcast_lst_size; - u8 mcast_lst[MAX_MCAST_LST][MAC_ADDR_LEN]; + u8 mcast_lst[MAX_MCAST_LST][ETH_ALEN]; u8 mcast_bits[HW_MCAST_SIZE]; u8 mac_addr[6]; u8 fid; @@ -1170,7 +1169,7 @@ static void ks_set_mcast(struct ks_net *ks, u16 mcast) static void ks_set_rx_mode(struct net_device *netdev) { struct ks_net *ks = netdev_priv(netdev); - struct dev_mc_list *ptr; + struct netdev_hw_addr *ha; /* Turn on/off promiscuous mode. */ if ((netdev->flags & IFF_PROMISC) == IFF_PROMISC) @@ -1187,13 +1186,12 @@ static void ks_set_rx_mode(struct net_device *netdev) if (netdev_mc_count(netdev) <= MAX_MCAST_LST) { int i = 0; - netdev_for_each_mc_addr(ptr, netdev) { - if (!(*ptr->dmi_addr & 1)) + netdev_for_each_mc_addr(ha, netdev) { + if (!(*ha->addr & 1)) continue; if (i >= MAX_MCAST_LST) break; - memcpy(ks->mcast_lst[i++], ptr->dmi_addr, - MAC_ADDR_LEN); + memcpy(ks->mcast_lst[i++], ha->addr, ETH_ALEN); } ks->mcast_lst_size = (u8)i; ks_set_grpaddr(ks); diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index b843bf7d8c1..34876952161 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -5763,7 +5763,7 @@ static void netdev_set_rx_mode(struct net_device *dev) struct dev_priv *priv = netdev_priv(dev); struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; int multicast = (dev->flags & IFF_ALLMULTI); dev_set_promiscuous(dev, priv, hw, (dev->flags & IFF_PROMISC)); @@ -5780,7 +5780,7 @@ static void netdev_set_rx_mode(struct net_device *dev) int i = 0; /* List too big to support so turn on all multicast mode. */ - if (dev->mc_count > MAX_MULTICAST_LIST) { + if (netdev_mc_count(dev) > MAX_MULTICAST_LIST) { if (MAX_MULTICAST_LIST != hw->multi_list_size) { hw->multi_list_size = MAX_MULTICAST_LIST; ++hw->all_multi; @@ -5789,13 +5789,12 @@ static void netdev_set_rx_mode(struct net_device *dev) return; } - netdev_for_each_mc_addr(mc_ptr, dev) { - if (!(*mc_ptr->dmi_addr & 1)) + netdev_for_each_mc_addr(ha, dev) { + if (!(*ha->addr & 1)) continue; if (i >= MAX_MULTICAST_LIST) break; - memcpy(hw->multi_list[i++], mc_ptr->dmi_addr, - MAC_ADDR_LEN); + memcpy(hw->multi_list[i++], ha->addr, MAC_ADDR_LEN); } hw->multi_list_size = (u8) i; hw_set_grp_addr(hw); diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 443c39a3732..fddaf921885 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1388,7 +1388,7 @@ static void set_multicast_list(struct net_device *dev) } if (!netdev_mc_empty(dev)) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char *cp; struct mc_cmd *cmd; @@ -1396,10 +1396,10 @@ static void set_multicast_list(struct net_device *dev) cmd->cmd.command = SWAP16(CmdMulticastList); cmd->mc_cnt = SWAP16(netdev_mc_count(dev) * 6); cp = cmd->mc_addrs; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if (!cnt--) break; - memcpy(cp, dmi->dmi_addr, 6); + memcpy(cp, ha->addr, 6); if (i596_debug > 1) DEB(DEB_MULTI, printk(KERN_DEBUG diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 56f66f48540..526dc9cbc3c 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -905,10 +905,10 @@ static struct net_device_stats *__ei_get_stats(struct net_device *dev) static inline void make_mc_bits(u8 *bits, struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(dmi, dev) { - u32 crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + u32 crc = ether_crc(ETH_ALEN, ha->addr); /* * The 8390 uses the 6 most significant bits of the * CRC to index the multicast table. diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index a18e3485476..30474d6b15c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -250,20 +250,20 @@ static void temac_set_multicast_list(struct net_device *ndev) 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 dev_mc_list *mclist; + struct netdev_hw_addr *ha; i = 0; - netdev_for_each_mc_addr(mclist, ndev) { + netdev_for_each_mc_addr(ha, ndev) { if (i >= MULTICAST_CAM_TABLE_NUM) break; - multi_addr_msw = ((mclist->dmi_addr[3] << 24) | - (mclist->dmi_addr[2] << 16) | - (mclist->dmi_addr[1] << 8) | - (mclist->dmi_addr[0])); + 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 = ((mclist->dmi_addr[5] << 8) | - (mclist->dmi_addr[4]) | (i << 16)); + multi_addr_lsw = ((ha->addr[5] << 8) | + (ha->addr[4]) | (i << 16)); temac_indirect_out32(lp, XTE_MAW1_OFFSET, multi_addr_lsw); i++; diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 3e3cc04defd..72379c5439d 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1256,7 +1256,7 @@ static void set_multicast_list(struct net_device *dev) { dev->name, netdev_mc_count(dev)); if (!netdev_mc_empty(dev)) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *cp; cmd = kmalloc(sizeof(struct i596_cmd) + 2 + netdev_mc_count(dev) * 6, GFP_ATOMIC); @@ -1267,8 +1267,8 @@ static void set_multicast_list(struct net_device *dev) { cmd->command = CmdMulticastList; *((unsigned short *) (cmd + 1)) = netdev_mc_count(dev) * 6; cp = ((char *)(cmd + 1))+2; - netdev_for_each_mc_addr(dmi, dev) { - memcpy(cp, dmi->dmi_addr, 6); + netdev_for_each_mc_addr(ha, dev) { + memcpy(cp, ha->addr, 6); cp += 6; } if (i596_debug & LOG_SRCDST) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c8a18a6203c..eab121945d7 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -882,15 +882,15 @@ static int hash_get_index(__u8 *addr) */ static void macb_sethashtable(struct net_device *dev) { - struct dev_mc_list *curr; + struct netdev_hw_addr *ha; unsigned long mc_filter[2]; unsigned int bitnr; struct macb *bp = netdev_priv(dev); mc_filter[0] = mc_filter[1] = 0; - netdev_for_each_mc_addr(curr, dev) { - bitnr = hash_get_index(curr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + bitnr = hash_get_index(ha->addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } diff --git a/drivers/net/mace.c b/drivers/net/mace.c index ab5f0bf6d1a..2328a7399dc 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -598,7 +598,7 @@ static void mace_set_multicast(struct net_device *dev) mp->maccc |= PROM; } else { unsigned char multicast_filter[8]; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 8; i++) @@ -606,8 +606,8 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - crc = ether_crc_le(6, dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc_le(6, ha->addr); i = crc >> 26; /* bit number in multicast_filter */ multicast_filter[i >> 3] |= 1 << (i & 7); } diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 13ba8f4afb7..8a50c67e592 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -508,7 +508,7 @@ static void mace_set_multicast(struct net_device *dev) mb->maccc |= PROM; } else { unsigned char multicast_filter[8]; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 8; i++) { @@ -517,8 +517,8 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - crc = ether_crc_le(6, dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc_le(6, ha->addr); /* bit number in multicast_filter */ i = crc >> 26; multicast_filter[i >> 3] |= 1 << (i & 7); diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 5eb96fe6ec5..455464223b4 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -168,7 +168,7 @@ static void mlx4_en_clear_list(struct net_device *dev) static void mlx4_en_cache_mclist(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; char *mc_addrs; int mc_addrs_cnt = netdev_mc_count(dev); int i; @@ -179,8 +179,8 @@ static void mlx4_en_cache_mclist(struct net_device *dev) return; } i = 0; - netdev_for_each_mc_addr(mclist, dev) - memcpy(mc_addrs + i++ * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) + memcpy(mc_addrs + i++ * ETH_ALEN, ha->addr, ETH_ALEN); priv->mc_addrs = mc_addrs; priv->mc_addrs_cnt = mc_addrs_cnt; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index c97b6e4365a..d5ebe43b0e6 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1769,7 +1769,7 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) struct mv643xx_eth_private *mp = netdev_priv(dev); u32 *mc_spec; u32 *mc_other; - struct dev_addr_list *addr; + struct netdev_hw_addr *ha; int i; if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { @@ -1794,8 +1794,8 @@ oom: memset(mc_spec, 0, 0x100); memset(mc_other, 0, 0x100); - netdev_for_each_mc_addr(addr, dev) { - u8 *a = addr->da_addr; + netdev_for_each_mc_addr(ha, dev) { + u8 *a = ha->addr; u32 *table; int entry; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e84dd3ee9c5..6d33adf988d 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3001,7 +3001,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) { struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_cmd cmd; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; __be32 data[2] = { 0, 0 }; int err; @@ -3038,8 +3038,8 @@ static void myri10ge_set_multicast_list(struct net_device *dev) } /* Walk the multicast list, and add each address */ - netdev_for_each_mc_addr(mc_list, dev) { - memcpy(data, &mc_list->dmi_addr, 6); + netdev_for_each_mc_addr(ha, dev) { + memcpy(data, &ha->addr, 6); cmd.data0 = ntohl(data[0]); cmd.data1 = ntohl(data[1]); err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP, @@ -3047,7 +3047,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) if (err != 0) { netdev_err(dev, "Failed MXGEFW_JOIN_MULTICAST_GROUP, error status:%d %pM\n", - err, mc_list->dmi_addr); + err, ha->addr); goto abort; } } diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index e5203878324..9250bf6573e 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2493,12 +2493,12 @@ static void __set_rx_mode(struct net_device *dev) rx_mode = RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int b = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff; + netdev_for_each_mc_addr(ha, dev) { + int b = (ether_crc(ETH_ALEN, ha->addr) >> 23) & 0x1ff; mc_filter[b/8] |= (1 << (b & 0x07)); } rx_mode = RxFilterEnable | AcceptBroadcast diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index a945591298a..781ca893ee0 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -537,7 +537,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, void netxen_p2_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 null_addr[6]; int i; @@ -571,8 +571,8 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) netxen_nic_enable_mcast_filter(adapter); i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) - netxen_nic_set_mcast_addr(adapter, i++, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) + netxen_nic_set_mcast_addr(adapter, i++, ha->addr); /* Clear out remaining addresses */ while (i < adapter->max_mc_count) @@ -680,7 +680,7 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, void netxen_p3_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; LIST_HEAD(del_list); @@ -707,8 +707,8 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) } if (!netdev_mc_empty(netdev)) { - netdev_for_each_mc_addr(mc_ptr, netdev) - nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); + netdev_for_each_mc_addr(ha, netdev) + nx_p3_nic_add_mac(adapter, ha->addr, &del_list); } send_fw_cmd: diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 05c29c2cef2..a76fabe2629 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -596,7 +596,7 @@ static int init586(struct net_device *dev) struct iasetup_cmd_struct __iomem *ias_cmd; struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int num_addrs = netdev_mc_count(dev); ptr = p->scb + 1; @@ -725,8 +725,8 @@ static int init586(struct net_device *dev) writew(num_addrs * 6, &mc_cmd->mc_cnt); i = 0; - netdev_for_each_mc_addr(dmi, dev) - memcpy_toio(mc_cmd->mc_list[i++], dmi->dmi_addr, 6); + netdev_for_each_mc_addr(ha, dev) + memcpy_toio(mc_cmd->mc_list[i++], ha->addr, 6); writew(make16(mc_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 0678f3106cb..7b52c466cf4 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6313,7 +6313,6 @@ static void niu_set_rx_mode(struct net_device *dev) { struct niu *np = netdev_priv(dev); int i, alt_cnt, err; - struct dev_addr_list *addr; struct netdev_hw_addr *ha; unsigned long flags; u16 hash[16] = { 0, }; @@ -6365,8 +6364,8 @@ static void niu_set_rx_mode(struct net_device *dev) for (i = 0; i < 16; i++) hash[i] = 0xffff; } else if (!netdev_mc_empty(dev)) { - netdev_for_each_mc_addr(addr, dev) { - u32 crc = ether_crc_le(ETH_ALEN, addr->da_addr); + netdev_for_each_mc_addr(ha, dev) { + u32 crc = ether_crc_le(ETH_ALEN, ha->addr); crc >>= 24; hash[crc >> 4] |= (1 << (15 - (crc & 0xf))); diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index be368e5cbf7..ee894ed35f7 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -474,7 +474,7 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) unsigned int cam_mode = 1; /* 1 - Accept on CAM match */ unsigned int multicast_mode = 1; /* 1 - Reject all multicast. */ struct octeon_mgmt_cam_state cam_state; - struct dev_addr_list *list; + struct netdev_hw_addr *ha; struct list_head *pos; int available_cam_entries; @@ -510,8 +510,8 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) } } if (multicast_mode == 0) { - netdev_for_each_mc_addr(list, netdev) - octeon_mgmt_cam_state_add(&cam_state, list->da_addr); + netdev_for_each_mc_addr(ha, netdev) + octeon_mgmt_cam_state_add(&cam_state, ha->addr); } diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 36785853a14..dc3b4c7914f 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1813,12 +1813,12 @@ static void netdrv_set_rx_mode(struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + 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); } diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 09291e60d30..333cb3344d5 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1623,11 +1623,11 @@ static struct net_device_stats *get_stats(struct net_device *dev) static inline void make_mc_bits(u8 *bits, struct net_device *dev) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u32 crc; - netdev_for_each_mc_addr(dmi, dev) { - crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc(ETH_ALEN, ha->addr); /* * The 8390 uses the 6 most significant bits of the * CRC to index the multicast table. diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index b9dc80b9d04..6734f7d6da9 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -1196,11 +1196,11 @@ static void set_rx_mode(struct net_device *dev) memset(mc_filter, 0x00, sizeof(mc_filter)); outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, dev) { + unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26; mc_filter[bit >> 3] |= (1 << (bit & 7)); } outb(2, ioaddr + RX_MODE); /* Use normal mode. */ diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index c717b143f11..c516c199635 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1475,7 +1475,7 @@ static void set_multicast_list(struct net_device *dev) { mace_private *lp = netdev_priv(dev); int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */ - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; #ifdef PCMCIA_DEBUG { @@ -1495,8 +1495,8 @@ static void set_multicast_list(struct net_device *dev) if (num_addrs > 0) { /* Calculate multicast logical address filter */ memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); - netdev_for_each_mc_addr(dmi, dev) { - memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN); + netdev_for_each_mc_addr(ha, dev) { + memcpy(adr, ha->addr, ETHER_ADDR_LEN); BuildLAF(lp->multicast_ladrf, adr); } } diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 5adc662c4bf..f45c626003a 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1616,12 +1616,12 @@ static void set_rx_mode(struct net_device *dev) rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti; else { if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mc_addr; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(mc_addr, dev) { - u_int position = ether_crc(6, mc_addr->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + u_int position = ether_crc(6, ha->addr); #ifndef final_version /* Verify multicast address. */ - if ((mc_addr->dmi_addr[0] & 1) == 0) + if ((ha->addr[0] & 1) == 0) continue; #endif multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 4d1802e457b..656be931207 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1398,7 +1398,7 @@ static void set_addresses(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; struct set_address_info sa_info; int i; @@ -1413,10 +1413,10 @@ static void set_addresses(struct net_device *dev) set_address(&sa_info, dev->dev_addr); i = 0; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i++ == 9) break; - set_address(&sa_info, dmi->dmi_addr); + set_address(&sa_info, ha->addr); } while (i++ < 9) set_address(&sa_info, dev->dev_addr); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 084d78dd163..a2254f749a9 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2590,7 +2590,7 @@ static void pcnet32_load_multicast(struct net_device *dev) struct pcnet32_private *lp = netdev_priv(dev); volatile struct pcnet32_init_block *ib = lp->init_block; volatile __le16 *mcast_table = (__le16 *)ib->filter; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned long ioaddr = dev->base_addr; char *addrs; int i; @@ -2611,8 +2611,8 @@ static void pcnet32_load_multicast(struct net_device *dev) ib->filter[1] = 0; /* Add addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index a602da6418c..fed5df9c5ea 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -546,7 +546,7 @@ out: void gelic_net_set_multi(struct net_device *netdev) { struct gelic_card *card = netdev_card(netdev); - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; unsigned int i; uint8_t *p; u64 addr; @@ -580,9 +580,9 @@ void gelic_net_set_multi(struct net_device *netdev) } /* set multicast addresses */ - netdev_for_each_mc_addr(mc, netdev) { + netdev_for_each_mc_addr(ha, netdev) { addr = 0; - p = mc->dmi_addr; + p = ha->addr; for (i = 0; i < ETH_ALEN; i++) { addr <<= 8; addr |= *p++; diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 14c999ab422..9a1daa4ebe2 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -415,7 +415,7 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr) void qlcnic_set_multi(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; @@ -434,8 +434,8 @@ void qlcnic_set_multi(struct net_device *netdev) } if (!netdev_mc_empty(netdev)) { - netdev_for_each_mc_addr(mc_ptr, netdev) { - qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + qlcnic_nic_add_mac(adapter, ha->addr); } } diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index fd34f266c0a..76df96813a7 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4207,7 +4207,7 @@ static struct net_device_stats *qlge_get_stats(struct net_device static void qlge_set_multicast_list(struct net_device *ndev) { struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; int i, status; status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); @@ -4271,8 +4271,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (status) goto exit; i = 0; - netdev_for_each_mc_addr(mc_ptr, ndev) { - if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr, + netdev_for_each_mc_addr(ha, ndev) { + if (ql_set_mac_addr_reg(qdev, (u8 *) ha->addr, MAC_ADDR_TYPE_MULTI_MAC, i)) { netif_err(qdev, hw, qdev->ndev, "Failed to loadmulticast address.\n"); diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 15d5373dc8f..f5a0e963e68 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -938,7 +938,7 @@ static void r6040_multicast_list(struct net_device *dev) u16 *adrp; u16 reg; unsigned long flags; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i; /* MAC Address */ @@ -973,8 +973,8 @@ static void r6040_multicast_list(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - char *addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + char *addrs = ha->addr; if (!(*addrs & 1)) continue; @@ -994,9 +994,9 @@ static void r6040_multicast_list(struct net_device *dev) } /* Multicast Address 1~4 case */ i = 0; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i < MCAST_MAX) { - adrp = (u16 *) dmi->dmi_addr; + adrp = (u16 *) ha->addr; iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f7ffa5d8ffe..64cd250f642 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4785,12 +4785,12 @@ static void rtl_set_rx_mode(struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + 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); rx_mode |= AcceptMulticast; } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2eb7f8a0d92..ad5a6a873b2 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -4964,7 +4964,7 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev) static void s2io_set_multicast(struct net_device *dev) { int i, j, prev_cnt; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct s2io_nic *sp = netdev_priv(dev); struct XENA_dev_config __iomem *bar0 = sp->bar0; u64 val64 = 0, multi_mac = 0x010203040506ULL, mask = @@ -5093,12 +5093,12 @@ static void s2io_set_multicast(struct net_device *dev) /* Create the new Rx filter list and update the same in H/W. */ i = 0; - netdev_for_each_mc_addr(mclist, dev) { - memcpy(sp->usr_addrs[i].addr, mclist->dmi_addr, + netdev_for_each_mc_addr(ha, dev) { + memcpy(sp->usr_addrs[i].addr, ha->addr, ETH_ALEN); mac_addr = 0; for (j = 0; j < ETH_ALEN; j++) { - mac_addr |= mclist->dmi_addr[j]; + mac_addr |= ha->addr[j]; mac_addr <<= 8; } mac_addr >>= 8; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 9944e5d662c..f7de960ca06 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2112,7 +2112,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc) uint64_t reg; void __iomem *port; int idx; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct net_device *dev = sc->sbm_dev; /* @@ -2161,10 +2161,10 @@ static void sbmac_setmulti(struct sbmac_softc *sc) * XXX if the table overflows */ idx = 1; /* skip station address */ - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { if (idx == MAC_ADDR_COUNT) break; - reg = sbmac_addr2reg(mclist->dmi_addr); + reg = sbmac_addr2reg(ha->addr); port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); __raw_writeq(reg, port); idx++; diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index d87c4787fff..1b326058893 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -433,13 +433,13 @@ static void _sc92031_set_mar(struct net_device *dev) (dev->flags & IFF_ALLMULTI)) mar0 = mar1 = 0xffffffff; else if (dev->flags & IFF_MULTICAST) { - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(mc_list, dev) { + netdev_for_each_mc_addr(ha, dev) { u32 crc; unsigned bit = 0; - crc = ~ether_crc(ETH_ALEN, mc_list->dmi_addr); + crc = ~ether_crc(ETH_ALEN, ha->addr); crc >>= 24; if (crc & 0x01) bit |= 0x02; diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 88f2fb193ab..e07b82b266d 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1602,7 +1602,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) static void efx_set_multicast_list(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; union efx_multicast_hash *mc_hash = &efx->multicast_hash; u32 crc; int bit; @@ -1614,8 +1614,8 @@ static void efx_set_multicast_list(struct net_device *net_dev) memset(mc_hash, 0xff, sizeof(*mc_hash)); } else { memset(mc_hash, 0x00, sizeof(*mc_hash)); - netdev_for_each_mc_addr(mc_list, net_dev) { - crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr); + netdev_for_each_mc_addr(ha, net_dev) { + crc = ether_crc_le(ETH_ALEN, ha->addr); bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); set_bit_le(bit, mc_hash->byte); } diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 760d9e83a46..6a05b93ae6c 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -848,13 +848,13 @@ static void sis190_set_rx_mode(struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { int bit_nr = - ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; + ether_crc(ETH_ALEN, ha->addr) & 0x3f; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); rx_mode |= AcceptMulticast; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index bc7ff411aad..6293592635b 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -2298,12 +2298,14 @@ static void set_rx_mode(struct net_device *net_dev) /* Accept Broadcast packet, destination address matchs our * MAC address, use Receive Filter to reject unwanted MCAST * packets */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; rx_mode = RFAAB; - netdev_for_each_mc_addr(mclist, net_dev) { - unsigned int bit_nr = - sis900_mcast_bitnr(mclist->dmi_addr, sis_priv->chipset_rev); + netdev_for_each_mc_addr(ha, net_dev) { + unsigned int bit_nr; + + bit_nr = sis900_mcast_bitnr(ha->addr, + sis_priv->chipset_rev); mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf)); } } diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 1921a54ea99..7e5b9f310fb 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -852,7 +852,7 @@ static void skfp_ctl_set_multicast_list(struct net_device *dev) static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) { struct s_smc *smc = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; /* Enable promiscuous mode, if necessary */ if (dev->flags & IFF_PROMISC) { @@ -876,13 +876,13 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) /* use exact filtering */ // point to first multicast addr - netdev_for_each_mc_addr(dmi, dev) { - mac_add_multicast(smc, - (struct fddi_addr *)dmi->dmi_addr, - 1); + netdev_for_each_mc_addr(ha, dev) { + mac_add_multicast(smc, + (struct fddi_addr *)ha->addr, + 1); pr_debug(KERN_INFO "ENABLE MC ADDRESS: %pMF\n", - dmi->dmi_addr); + ha->addr); } } else { // more MC addresses than HW supports diff --git a/drivers/net/skge.c b/drivers/net/skge.c index bd8c5e8413b..de5ef3877ba 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2917,7 +2917,7 @@ static void genesis_set_multicast(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - struct dev_mc_list *list; + struct netdev_hw_addr *ha; u32 mode; u8 filter[8]; @@ -2937,8 +2937,8 @@ static void genesis_set_multicast(struct net_device *dev) skge->flow_status == FLOW_STAT_SYMMETRIC) genesis_add_filter(filter, pause_mc_addr); - netdev_for_each_mc_addr(list, dev) - genesis_add_filter(filter, list->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + genesis_add_filter(filter, ha->addr); } xm_write32(hw, port, XM_MODE, mode); @@ -2956,7 +2956,7 @@ static void yukon_set_multicast(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - struct dev_mc_list *list; + struct netdev_hw_addr *ha; int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND || skge->flow_status == FLOW_STAT_SYMMETRIC); u16 reg; @@ -2979,8 +2979,8 @@ static void yukon_set_multicast(struct net_device *dev) if (rx_pause) yukon_add_filter(filter, pause_mc_addr); - netdev_for_each_mc_addr(list, dev) - yukon_add_filter(filter, list->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + yukon_add_filter(filter, ha->addr); } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f1c0ec308bf..5b97edb7a35 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3627,7 +3627,7 @@ static void sky2_set_multicast(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - struct dev_mc_list *list; + struct netdev_hw_addr *ha; u16 reg; u8 filter[8]; int rx_pause; @@ -3651,8 +3651,8 @@ static void sky2_set_multicast(struct net_device *dev) if (rx_pause) sky2_add_filter(filter, pause_mc_addr); - netdev_for_each_mc_addr(list, dev) - sky2_add_filter(filter, list->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + sky2_add_filter(filter, ha->addr); } gma_write16(hw, port, GM_MC_ADDR_H1, diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 0f97b5af91e..6278734c735 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1341,7 +1341,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) * within that register. */ else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *cur_addr; + struct netdev_hw_addr *ha; /* Set the Hash perfec mode */ mcr |= MAC_CR_HPFILT_; @@ -1349,19 +1349,16 @@ static void smc911x_set_multicast_list(struct net_device *dev) /* start with a table of all zeros: reject all */ memset(multicast_table, 0, sizeof(multicast_table)); - netdev_for_each_mc_addr(cur_addr, dev) { + netdev_for_each_mc_addr(ha, dev) { u32 position; - /* do we have a pointer here? */ - if (!cur_addr) - break; /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */ - if (!(*cur_addr->dmi_addr & 1)) - continue; + if (!(*ha->addr & 1)) + continue; /* upper 6 bits are used as hash index */ - position = ether_crc(ETH_ALEN, cur_addr->dmi_addr)>>26; + position = ether_crc(ETH_ALEN, ha->addr)>>26; multicast_table[position>>5] |= 1 << (position&0x1f); } diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index ee1487791d5..9e5e9e792e8 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -417,7 +417,7 @@ static void smc_shutdown( int ioaddr ) /* - . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) + . Function: smc_setmulticast( int ioaddr, struct net_device *dev ) . Purpose: . This sets the internal hardware table to filter out unwanted multicast . packets before they take up memory. @@ -438,26 +438,23 @@ static void smc_setmulticast(int ioaddr, struct net_device *dev) { int i; unsigned char multicast_table[ 8 ]; - struct dev_mc_list *cur_addr; + struct netdev_hw_addr *ha; /* table for flipping the order of 3 bits */ unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; /* start with a table of all zeros: reject all */ memset( multicast_table, 0, sizeof( multicast_table ) ); - netdev_for_each_mc_addr(cur_addr, dev) { + netdev_for_each_mc_addr(ha, dev) { int position; - /* do we have a pointer here? */ - if ( !cur_addr ) - break; /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */ - if ( !( *cur_addr->dmi_addr & 1 ) ) + if (!(*ha->addr & 1)) continue; /* only use the low order bits */ - position = ether_crc_le(6, cur_addr->dmi_addr) & 0x3f; + position = ether_crc_le(6, ha->addr) & 0x3f; /* do some messy swapping to put the bit in the right spot */ multicast_table[invert3[position&7]] |= diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 2e8133809dc..20c75657763 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1413,7 +1413,7 @@ static void smc_set_multicast_list(struct net_device *dev) * within that register. */ else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *cur_addr; + struct netdev_hw_addr *ha; /* table for flipping the order of 3 bits */ static const unsigned char invert3[] = {0, 4, 2, 6, 1, 5, 3, 7}; @@ -1421,16 +1421,16 @@ static void smc_set_multicast_list(struct net_device *dev) /* start with a table of all zeros: reject all */ memset(multicast_table, 0, sizeof(multicast_table)); - netdev_for_each_mc_addr(cur_addr, dev) { + netdev_for_each_mc_addr(ha, dev) { int position; /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */ - if (!(*cur_addr->dmi_addr & 1)) + if (!(*ha->addr & 1)) continue; /* only use the low order bits */ - position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + position = crc32_le(~0, ha->addr, 6) & 0x3f; /* do some messy swapping to put the bit in the right spot */ multicast_table[invert3[position&7]] |= diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 4fd1d8b3878..d6e3a12d65d 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1383,13 +1383,13 @@ static void smsc911x_set_multicast_list(struct net_device *dev) /* Enabling specific multicast addresses */ unsigned int hash_high = 0; unsigned int hash_low = 0; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; pdata->set_bits_mask = MAC_CR_HPFILT_; pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_); - netdev_for_each_mc_addr(mc_list, dev) { - unsigned int bitnum = smsc911x_hash(mc_list->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + unsigned int bitnum = smsc911x_hash(ha->addr); unsigned int mask = 0x01 << (bitnum & 0x1F); if (bitnum & 0x20) diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 34fa10d8ad4..5409ec1a5fd 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1063,12 +1063,12 @@ static void smsc9420_set_multicast_list(struct net_device *dev) mac_cr |= MAC_CR_MCPAS_; mac_cr &= (~MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; u32 hash_lo = 0, hash_hi = 0; smsc_dbg(HW, "Multicast filter enabled"); - netdev_for_each_mc_addr(mc_list, dev) { - u32 bit_num = smsc9420_hash(mc_list->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + u32 bit_num = smsc9420_hash(ha->addr); u32 mask = 1 << (bit_num & 0x1F); if (bit_num & 0x20) diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index 287c251075e..e5d67327d70 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -531,7 +531,7 @@ static void sonic_multicast_list(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); unsigned int rcr; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char *addr; int i; @@ -550,8 +550,8 @@ static void sonic_multicast_list(struct net_device *dev) netdev_mc_count(dev)); sonic_set_cam_enable(dev, 1); /* always enable our own address */ i = 1; - netdev_for_each_mc_addr(dmi, dev) { - addr = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addr = ha->addr; sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]); sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]); sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 5ba9d989f8f..c04c8f9a2d9 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -625,7 +625,7 @@ spider_net_get_multicast_hash(struct net_device *netdev, __u8 *addr) static void spider_net_set_multi(struct net_device *netdev) { - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; u8 hash; int i; u32 reg; @@ -646,8 +646,8 @@ spider_net_set_multi(struct net_device *netdev) hash = spider_net_get_multicast_hash(netdev, netdev->broadcast); */ set_bit(0xfd, bitmask); - netdev_for_each_mc_addr(mc, netdev) { - hash = spider_net_get_multicast_hash(netdev, mc->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + hash = spider_net_get_multicast_hash(netdev, ha->addr); set_bit(hash, bitmask); } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 6dfa6989901..8a6d27cdc0b 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1766,7 +1766,7 @@ static void set_rx_mode(struct net_device *dev) struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->base; u32 rx_mode = MinVLANPrio; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i; #ifdef VLAN_SUPPORT @@ -1804,8 +1804,8 @@ static void set_rx_mode(struct net_device *dev) /* Use the 16 element perfect filter, skip first two entries. */ void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16; __be16 *eaddrs; - netdev_for_each_mc_addr(mclist, dev) { - eaddrs = (__be16 *)mclist->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + eaddrs = (__be16 *) ha->addr; writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8; @@ -1825,10 +1825,10 @@ static void set_rx_mode(struct net_device *dev) __le16 mc_filter[32] __attribute__ ((aligned(sizeof(long)))); /* Multicast hash filter */ memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { /* The chip uses the upper 9 CRC bits as index into the hash table */ - int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23; + int bit_nr = ether_crc_le(ETH_ALEN, ha->addr) >> 23; __le32 *fptr = (__le32 *) &mc_filter[(bit_nr >> 4) & ~1]; *fptr |= cpu_to_le32(1 << (bit_nr & 31)); diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c index a183de29c39..c0a1c9df3ac 100644 --- a/drivers/net/stmmac/dwmac100.c +++ b/drivers/net/stmmac/dwmac100.c @@ -316,7 +316,7 @@ static void dwmac100_set_filter(struct net_device *dev) MAC_CONTROL_HO | MAC_CONTROL_HP); } else { u32 mc_filter[2]; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; /* Perfect filter mode for physical address and Hash filter for multicast */ @@ -325,11 +325,11 @@ static void dwmac100_set_filter(struct net_device *dev) MAC_CONTROL_IF | MAC_CONTROL_HO); memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + 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, mclist->dmi_addr) >> 26; + 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. */ diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index a6538ae4694..bf73fda6adf 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -94,17 +94,17 @@ static void dwmac1000_set_filter(struct net_device *dev) writel(0xffffffff, ioaddr + GMAC_HASH_LOW); } else if (!netdev_mc_empty(dev)) { u32 mc_filter[2]; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; /* Hash filter for multicast */ value = GMAC_FRAME_FILTER_HMC; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { + 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 = - bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26; + bitrev32(~crc32_le(~0, ha->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. */ diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index 2f6a760e5f2..2cfa065c39c 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -413,7 +413,7 @@ static int init586(struct net_device *dev) volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int num_addrs=netdev_mc_count(dev); ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); @@ -537,9 +537,9 @@ static int init586(struct net_device *dev) mc_cmd->mc_cnt = swab16(num_addrs * 6); i = 0; - netdev_for_each_mc_addr(dmi, dev) + netdev_for_each_mc_addr(ha, dev) memcpy((char *) mc_cmd->mc_list[i++], - dmi->dmi_addr, ETH_ALEN); + ha->addr, ETH_ALEN); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd_cuc = CUC_START; diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index a0bd361d5ec..4dd159b4116 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -999,7 +999,7 @@ static void bigmac_set_multicast(struct net_device *dev) { struct bigmac *bp = netdev_priv(dev); void __iomem *bregs = bp->bregs; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; int i; u32 tmp, crc; @@ -1028,8 +1028,8 @@ static void bigmac_set_multicast(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index a855934dfc3..47e8cce10d1 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1523,13 +1523,13 @@ static void set_rx_mode(struct net_device *dev) memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int bit; int index; int crc; memset (mc_filter, 0, sizeof (mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + crc = ether_crc_le(ETH_ALEN, ha->addr); for (index=0, bit=0; bit < 6; bit++, crc <<= 1) if (crc & 0x80000000) index |= 1 << bit; mc_filter[index/16] |= (1 << (index % 16)); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 70196bc5fe6..58a27541ae3 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1846,12 +1846,12 @@ static u32 gem_setup_multicast(struct gem *gp) } else { u16 hash_table[16]; u32 crc; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(dmi, gp->dev) { - char *addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, gp->dev) { + char *addrs = ha->addr; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index b17dbb11bd6..20deb14e98f 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1523,13 +1523,13 @@ static int happy_meal_init(struct happy_meal *hp) hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff); } else if ((hp->dev->flags & IFF_PROMISC) == 0) { u16 hash_table[4]; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(dmi, hp->dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, hp->dev) { + addrs = ha->addr; if (!(*addrs & 1)) continue; @@ -2362,7 +2362,7 @@ static void happy_meal_set_multicast(struct net_device *dev) { struct happy_meal *hp = netdev_priv(dev); void __iomem *bregs = hp->bigmacregs; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; @@ -2380,8 +2380,8 @@ static void happy_meal_set_multicast(struct net_device *dev) u16 hash_table[4]; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index d7c73f478ef..674570584bd 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1170,7 +1170,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; char *addrs; u32 crc; u32 val; @@ -1195,8 +1195,8 @@ static void lance_load_multicast(struct net_device *dev) return; /* Add addresses */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index be637dce944..239f0977219 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -627,7 +627,7 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev) static void qe_set_multicast(struct net_device *dev) { struct sunqe *qep = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u8 new_mconfig = qep->mconfig; char *addrs; int i; @@ -651,8 +651,8 @@ static void qe_set_multicast(struct net_device *dev) u8 *hbytes = (unsigned char *) &hash_table[0]; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 6b1b7cea7f6..6cf8b06be5c 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -763,12 +763,12 @@ static struct vnet_mcast_entry *__vnet_mc_find(struct vnet *vp, u8 *addr) static void __update_mc_list(struct vnet *vp, struct net_device *dev) { - struct dev_addr_list *p; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(p, dev) { + netdev_for_each_mc_addr(ha, dev) { struct vnet_mcast_entry *m; - m = __vnet_mc_find(vp, p->dmi_addr); + m = __vnet_mc_find(vp, ha->addr); if (m) { m->hit = 1; continue; @@ -778,7 +778,7 @@ static void __update_mc_list(struct vnet *vp, struct net_device *dev) m = kzalloc(sizeof(*m), GFP_ATOMIC); if (!m) continue; - memcpy(m->addr, p->dmi_addr, ETH_ALEN); + memcpy(m->addr, ha->addr, ETH_ALEN); m->hit = 1; m->next = vp->mcast_list; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 49bd84c0d58..36149ddace4 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1954,16 +1954,16 @@ tc35815_set_multicast_list(struct net_device *dev) /* Disable promiscuous mode, use normal mode. */ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl); } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *cur_addr; + struct netdev_hw_addr *ha; int i; int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE); tc_writel(0, &tr->CAM_Ctl); /* Walk the address list, and load the filter */ i = 0; - netdev_for_each_mc_addr(cur_addr, dev) { + netdev_for_each_mc_addr(ha, dev) { /* entry 0,1 is reserved. */ - tc35815_set_cam_entry(dev, i + 2, cur_addr->dmi_addr); + tc35815_set_cam_entry(dev, i + 2, ha->addr); ena_bits |= CAM_Ena_Bit(i + 2); i++; } diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 068a47174fc..a38aede5c8d 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -808,7 +808,7 @@ static void bdx_setmulti(struct net_device *ndev) WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, ~0); } else if (!netdev_mc_empty(ndev)) { u8 hash; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u32 reg, val; /* set IMF to deny all multicast frames */ @@ -825,10 +825,10 @@ static void bdx_setmulti(struct net_device *ndev) * into RX_MAC_MCST regs. we skip this phase now and accept ALL * multicast frames throu IMF */ /* accept the rest of addresses throu IMF */ - netdev_for_each_mc_addr(mclist, ndev) { + netdev_for_each_mc_addr(ha, ndev) { hash = 0; for (i = 0; i < ETH_ALEN; i++) - hash ^= mclist->dmi_addr[i]; + hash ^= ha->addr[i]; reg = regRX_MCST_HASH0 + ((hash >> 5) << 2); val = READ_REG(priv, reg); val |= (1 << (hash % 32)); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 22cf1c446de..aff11f84f52 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9457,14 +9457,14 @@ static void __tg3_set_rx_mode(struct net_device *dev) tg3_set_multi (tp, 0); } else { /* Accept one or more multicast(s). */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u32 mc_filter[4] = { 0, }; u32 regidx; u32 bit; u32 crc; - netdev_for_each_mc_addr(mclist, dev) { - crc = calc_crc (mclist->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) { + crc = calc_crc(ha->addr, ETH_ALEN); bit = ~crc & 0x7f; regidx = (bit & 0x60) >> 5; bit &= 0x1f; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 05ea30a94e8..8ffec22b74b 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1314,7 +1314,7 @@ static struct net_device_stats *TLan_GetStats( struct net_device *dev ) static void TLan_SetMulticastList( struct net_device *dev ) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u32 hash1 = 0; u32 hash2 = 0; int i; @@ -1336,12 +1336,12 @@ static void TLan_SetMulticastList( struct net_device *dev ) TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF ); } else { i = 0; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if ( i < 3 ) { TLan_SetMac( dev, i + 1, - (char *) &dmi->dmi_addr ); + (char *) &ha->addr); } else { - offset = TLan_HashFunc( (u8 *) &dmi->dmi_addr ); + offset = TLan_HashFunc((u8 *)&ha->addr); if ( offset < 32 ) hash1 |= ( 1 << offset ); else diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 8c54d89e60d..4673e38c52a 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -1390,7 +1390,7 @@ static int xl_close(struct net_device *dev) static void xl_set_rx_mode(struct net_device *dev) { struct xl_private *xl_priv = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char dev_mc_address[4] ; u16 options ; @@ -1407,11 +1407,11 @@ static void xl_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - netdev_for_each_mc_addr(dmi, dev) { - dev_mc_address[0] |= dmi->dmi_addr[2] ; - dev_mc_address[1] |= dmi->dmi_addr[3] ; - dev_mc_address[2] |= dmi->dmi_addr[4] ; - dev_mc_address[3] |= dmi->dmi_addr[5] ; + netdev_for_each_mc_addr(ha, dev) { + dev_mc_address[0] |= ha->addr[2]; + dev_mc_address[1] |= ha->addr[3]; + dev_mc_address[2] |= ha->addr[4]; + dev_mc_address[3] |= ha->addr[5]; } if (memcmp(xl_priv->xl_functional_addr,dev_mc_address,4) != 0) { /* Options have changed, run the command */ diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 1a0967246e2..eebdaae2432 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -986,7 +986,7 @@ static void open_sap(unsigned char type, struct net_device *dev) static void tok_set_multicast_list(struct net_device *dev) { struct tok_info *ti = netdev_priv(dev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; unsigned char address[4]; int i; @@ -995,11 +995,11 @@ static void tok_set_multicast_list(struct net_device *dev) /*BMS ifconfig tr down or hot unplug a PCMCIA card ??hownowbrowncow*/ if (/*BMSHELPdev->start == 0 ||*/ ti->open_status != OPEN) return; address[0] = address[1] = address[2] = address[3] = 0; - netdev_for_each_mc_addr(mclist, dev) { - address[0] |= mclist->dmi_addr[2]; - address[1] |= mclist->dmi_addr[3]; - address[2] |= mclist->dmi_addr[4]; - address[3] |= mclist->dmi_addr[5]; + netdev_for_each_mc_addr(ha, dev) { + address[0] |= ha->addr[2]; + address[1] |= ha->addr[3]; + address[2] |= ha->addr[4]; + address[3] |= ha->addr[5]; } SET_PAGE(ti->srb_page); for (i = 0; i < sizeof(struct srb_set_funct_addr); i++) diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 01c780f25e9..88c893100c2 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -1266,7 +1266,7 @@ static void streamer_set_rx_mode(struct net_device *dev) netdev_priv(dev); __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio; __u8 options = 0; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char dev_mc_address[5]; writel(streamer_priv->srb, streamer_mmio + LAPA); @@ -1302,11 +1302,11 @@ static void streamer_set_rx_mode(struct net_device *dev) writel(streamer_priv->srb,streamer_mmio+LAPA); dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - netdev_for_each_mc_addr(dmi, dev) { - dev_mc_address[0] |= dmi->dmi_addr[2] ; - dev_mc_address[1] |= dmi->dmi_addr[3] ; - dev_mc_address[2] |= dmi->dmi_addr[4] ; - dev_mc_address[3] |= dmi->dmi_addr[5] ; + netdev_for_each_mc_addr(ha, dev) { + dev_mc_address[0] |= ha->addr[2]; + dev_mc_address[1] |= ha->addr[3]; + dev_mc_address[2] |= ha->addr[4]; + dev_mc_address[3] |= ha->addr[5]; } writew(htons(SRB_SET_FUNC_ADDRESS << 8),streamer_mmio+LAPDINC); diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 3decaf4b6cf..3d2fbe60b46 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1139,7 +1139,7 @@ static void olympic_set_rx_mode(struct net_device *dev) u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; u8 options = 0; u8 __iomem *srb; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; unsigned char dev_mc_address[4] ; writel(olympic_priv->srb,olympic_mmio+LAPA); @@ -1177,11 +1177,11 @@ static void olympic_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - netdev_for_each_mc_addr(dmi, dev) { - dev_mc_address[0] |= dmi->dmi_addr[2] ; - dev_mc_address[1] |= dmi->dmi_addr[3] ; - dev_mc_address[2] |= dmi->dmi_addr[4] ; - dev_mc_address[3] |= dmi->dmi_addr[5] ; + netdev_for_each_mc_addr(ha, dev) { + dev_mc_address[0] |= ha->addr[2]; + dev_mc_address[1] |= ha->addr[3]; + dev_mc_address[2] |= ha->addr[4]; + dev_mc_address[3] |= ha->addr[5]; } writeb(SRB_SET_FUNC_ADDRESS,srb+0); diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index b545e20d289..9fa2c36ff90 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -1212,17 +1212,17 @@ static void tms380tr_set_multicast_list(struct net_device *dev) } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { ((char *)(&tp->ocpl.FunctAddr))[0] |= - mclist->dmi_addr[2]; + ha->addr[2]; ((char *)(&tp->ocpl.FunctAddr))[1] |= - mclist->dmi_addr[3]; + ha->addr[3]; ((char *)(&tp->ocpl.FunctAddr))[2] |= - mclist->dmi_addr[4]; + ha->addr[4]; ((char *)(&tp->ocpl.FunctAddr))[3] |= - mclist->dmi_addr[5]; + ha->addr[5]; } } tms380tr_exec_cmd(dev, OC_SET_FUNCT_ADDR); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 80333a4d328..1366541c30a 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1186,15 +1186,15 @@ static void tsi108_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { int i; - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH; memset(data->mc_hash, 0, sizeof(data->mc_hash)); - netdev_for_each_mc_addr(mc, dev) { + netdev_for_each_mc_addr(ha, dev) { u32 hash, crc; - crc = ether_crc(6, mc->dmi_addr); + crc = ether_crc(6, ha->addr); hash = crc >> 23; __set_bit(hash, &data->mc_hash[0]); } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index cb429723b2c..a68b9176462 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -670,15 +670,15 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) { struct de_private *de = netdev_priv(dev); u16 hash_table[32]; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i; u16 *eaddrs; memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - netdev_for_each_mc_addr(mclist, dev) { - int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; + netdev_for_each_mc_addr(ha, dev) { + int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; set_bit_le(index, hash_table); } @@ -699,13 +699,13 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) { struct de_private *de = netdev_priv(dev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u16 *eaddrs; /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - netdev_for_each_mc_addr(mclist, dev) { - eaddrs = (u16 *)mclist->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + eaddrs = (u16 *) ha->addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 55ade8949a6..cac4bcc8318 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1951,7 +1951,7 @@ static void SetMulticastFilter(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; u_long iobase = dev->base_addr; int i, bit, byte; u16 hashcode; @@ -1966,8 +1966,8 @@ SetMulticastFilter(struct net_device *dev) if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 14)) { omr |= OMR_PM; /* Pass all multicasts */ } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ @@ -1983,8 +1983,8 @@ SetMulticastFilter(struct net_device *dev) } } } else { /* Perfect filtering */ - netdev_for_each_mc_addr(dmi, dev) { - addrs = dmi->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrs = ha->addr; for (i=0; ibase_addr+0xc0; /* ID Table */ u32 hash_val; @@ -1478,8 +1478,8 @@ static void dm9132_id_table(struct DEVICE *dev) hash_table[3] = 0x8000; /* the multicast address in Hash Table : 64 bits */ - netdev_for_each_mc_addr(mcptr, dev) { - hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f; + netdev_for_each_mc_addr(ha, dev) { + hash_val = cal_CRC((char *) ha->addr, 6, 0) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } @@ -1497,7 +1497,7 @@ static void dm9132_id_table(struct DEVICE *dev) static void send_filter_frame(struct DEVICE *dev) { struct dmfe_board_info *db = netdev_priv(dev); - struct dev_mc_list *mcptr; + struct netdev_hw_addr *ha; struct tx_desc *txptr; u16 * addrptr; u32 * suptr; @@ -1520,8 +1520,8 @@ static void send_filter_frame(struct DEVICE *dev) *suptr++ = 0xffff; /* fit the multicast address */ - netdev_for_each_mc_addr(mcptr, dev) { - addrptr = (u16 *) mcptr->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrptr = (u16 *) ha->addr; *suptr++ = addrptr[0]; *suptr++ = addrptr[1]; *suptr++ = addrptr[2]; diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 7f544ef2f5f..c4b7cd726b6 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -990,15 +990,15 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); u16 hash_table[32]; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; int i; u16 *eaddrs; memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - netdev_for_each_mc_addr(mclist, dev) { - int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; + netdev_for_each_mc_addr(ha, dev) { + int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; set_bit_le(index, hash_table); } @@ -1018,13 +1018,13 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u16 *eaddrs; /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - netdev_for_each_mc_addr(mclist, dev) { - eaddrs = (u16 *)mclist->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + eaddrs = (u16 *) ha->addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; @@ -1061,7 +1061,7 @@ static void set_rx_mode(struct net_device *dev) } else if (tp->flags & MC_HASH_ONLY) { /* Some work-alikes have only a 64-entry hash filter table. */ /* Should verify correctness on big-endian/__powerpc__ */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; if (netdev_mc_count(dev) > 64) { /* Arbitrary non-effective limit. */ tp->csr6 |= AcceptAllMulticast; @@ -1069,18 +1069,21 @@ static void set_rx_mode(struct net_device *dev) } else { u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ int filterbit; - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { if (tp->flags & COMET_MAC_ADDR) - filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr); + filterbit = ether_crc_le(ETH_ALEN, + ha->addr); else - filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + filterbit = ether_crc(ETH_ALEN, + ha->addr) >> 26; filterbit &= 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); if (tulip_debug > 2) dev_info(&dev->dev, "Added filter for %pM %08x bit %d\n", - mclist->dmi_addr, - ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit); + ha->addr, + ether_crc(ETH_ALEN, ha->addr), + filterbit); } if (mc_filter[0] == tp->mc_filter[0] && mc_filter[1] == tp->mc_filter[1]) diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 0ab05af237e..b79d908fe34 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -1392,7 +1392,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr) static void send_filter_frame(struct net_device *dev, int mc_cnt) { struct uli526x_board_info *db = netdev_priv(dev); - struct dev_mc_list *mcptr; + struct netdev_hw_addr *ha; struct tx_desc *txptr; u16 * addrptr; u32 * suptr; @@ -1415,8 +1415,8 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt) *suptr++ = 0xffff << FLT_SHIFT; /* fit the multicast address */ - netdev_for_each_mc_addr(mcptr, dev) { - addrptr = (u16 *) mcptr->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addrptr = (u16 *) ha->addr; *suptr++ = addrptr[0] << FLT_SHIFT; *suptr++ = addrptr[1] << FLT_SHIFT; *suptr++ = addrptr[2] << FLT_SHIFT; diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 304f43866c4..3e3822c98a0 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1367,13 +1367,15 @@ static u32 __set_rx_mode(struct net_device *dev) memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = RxAcceptBroadcast | AcceptMulticast | AcceptMyPhys; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int filterbit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; - filterbit &= 0x3f; - mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); + netdev_for_each_mc_addr(ha, dev) { + int filbit; + + filbit = (ether_crc(ETH_ALEN, ha->addr) >> 26) ^ 0x3F; + filbit &= 0x3f; + mc_filter[filbit >> 5] |= 1 << (filbit & 31); } rx_mode = RxAcceptBroadcast | AcceptMulticast | AcceptMyPhys; } diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index cd24e5f2b2a..3053f85aa06 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -921,11 +921,11 @@ typhoon_set_rx_mode(struct net_device *dev) /* Too many to match, or accept all multicasts. */ filter |= TYPHOON_RX_FILTER_ALL_MCAST; } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int bit = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; + netdev_for_each_mc_addr(ha, dev) { + int bit = ether_crc(ETH_ALEN, ha->addr) & 0x3f; mc_filter[bit >> 5] |= 1 << (bit & 0x1f); } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 75743a76bbe..081f76bff34 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1999,7 +1999,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) static void ucc_geth_set_multi(struct net_device *dev) { struct ucc_geth_private *ugeth; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; struct ucc_fast __iomem *uf_regs; struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; @@ -2028,16 +2028,16 @@ static void ucc_geth_set_multi(struct net_device *dev) out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { /* Only support group multicast for now. */ - if (!(dmi->dmi_addr[0] & 1)) + if (!(ha->addr[0] & 1)) continue; /* Ask CPM to run CRC and set bit in * filter mask. */ - hw_add_addr_in_hash(ugeth, dmi->dmi_addr); + hw_add_addr_in_hash(ugeth, ha->addr); } } } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 9e05639435f..763364f0972 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -557,16 +557,14 @@ static void asix_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; u32 crc_bits; memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - netdev_for_each_mc_addr(mc_list, net) { - crc_bits = - ether_crc(ETH_ALEN, - mc_list->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, net) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); } @@ -793,16 +791,14 @@ static void ax88172_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; u32 crc_bits; memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - netdev_for_each_mc_addr(mc_list, net) { - crc_bits = - ether_crc(ETH_ALEN, - mc_list->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, net) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); } diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 96f1ebe0d34..0c48ff97f47 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -629,7 +629,7 @@ static void catc_multicast(unsigned char *addr, u8 *multicast) static void catc_set_multicast_list(struct net_device *netdev) { struct catc *catc = netdev_priv(netdev); - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; u8 broadcast[6]; u8 rx = RxEnable | RxPolarity | RxMultiCast; @@ -647,8 +647,8 @@ static void catc_set_multicast_list(struct net_device *netdev) if (netdev->flags & IFF_ALLMULTI) { memset(catc->multicast, 0xff, 64); } else { - netdev_for_each_mc_addr(mc, netdev) { - u32 crc = ether_crc_le(6, mc->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + u32 crc = ether_crc_le(6, ha->addr); if (!catc->is_f5u011) { catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); } else { diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 269339769f4..4eb1fb31ff0 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -386,10 +386,10 @@ static void dm9601_set_multicast(struct net_device *net) netdev_mc_count(net) > DM_MAX_MCAST) { rx_ctl |= 0x04; } else if (!netdev_mc_empty(net)) { - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(mc_list, net) { - u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, net) { + u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } } diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 70978219e98..0dc92c8ba4b 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -452,12 +452,12 @@ static void mcs7830_data_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; u32 crc_bits; /* Build the multicast hash filter. */ - netdev_for_each_mc_addr(mc_list, net) { - crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, net) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); } } diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 300e3e764fa..b8b00d06ea7 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -444,14 +444,14 @@ static void smsc75xx_set_multicast(struct net_device *netdev) netif_dbg(dev, drv, dev->net, "receive all multicast enabled"); pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF; } else if (!netdev_mc_empty(dev->net)) { - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; netif_dbg(dev, drv, dev->net, "receive multicast hash filter"); pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF; - netdev_for_each_mc_addr(mc_list, netdev) { - u32 bitnum = smsc75xx_hash(mc_list->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + u32 bitnum = smsc75xx_hash(ha->addr); pdata->multicast_hash_table[bitnum / 32] |= (1 << (bitnum % 32)); } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 73f9a31cf94..ccd55ca3a06 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -384,13 +384,13 @@ static void smsc95xx_set_multicast(struct net_device *netdev) pdata->mac_cr |= MAC_CR_MCPAS_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev->net)) { - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; pdata->mac_cr |= MAC_CR_HPFILT_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); - netdev_for_each_mc_addr(mc_list, netdev) { - u32 bitnum = smsc95xx_hash(mc_list->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) { + u32 bitnum = smsc95xx_hash(ha->addr); u32 mask = 0x01 << (bitnum & 0x1F); if (bitnum & 0x20) hash_hi |= mask; diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 50f881aa393..d9133c62a2f 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1704,11 +1704,11 @@ static void rhine_set_rx_mode(struct net_device *dev) iowrite32(0xffffffff, ioaddr + MulticastFilter1); rx_mode = 0x0C; } else { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + 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); } diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 3a486f3bad3..91f3b841288 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1126,7 +1126,7 @@ static void velocity_set_multi(struct net_device *dev) struct mac_regs __iomem *regs = vptr->mac_regs; u8 rx_mode; int i; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ writel(0xffffffff, ®s->MARCAM[0]); @@ -1142,8 +1142,8 @@ static void velocity_set_multi(struct net_device *dev) mac_get_cam_mask(regs, vptr->mCAMmask); i = 0; - netdev_for_each_mc_addr(mclist, dev) { - mac_set_cam(regs, i + offset, mclist->dmi_addr); + netdev_for_each_mc_addr(ha, dev) { + mac_set_cam(regs, i + offset, ha->addr); vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7); i++; } diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3f5be35dea2..ecec9a8527f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -721,7 +721,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) struct scatterlist sg[2]; u8 promisc, allmulti; struct virtio_net_ctrl_mac *mac_data; - struct dev_addr_list *addr; struct netdev_hw_addr *ha; int uc_count; int mc_count; @@ -778,8 +777,8 @@ static void virtnet_set_rx_mode(struct net_device *dev) mac_data->entries = mc_count; i = 0; - netdev_for_each_mc_addr(addr, dev) - memcpy(&mac_data->macs[i++][0], addr->da_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) + memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); sg_set_buf(&sg[1], mac_data, sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index cff3485d967..58dfa367bf8 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1675,11 +1675,11 @@ vmxnet3_copy_mc(struct net_device *netdev) /* We may be called with BH disabled */ buf = kmalloc(sz, GFP_ATOMIC); if (buf) { - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; int i = 0; - netdev_for_each_mc_addr(mc, netdev) - memcpy(buf + i++ * ETH_ALEN, mc->dmi_addr, + netdev_for_each_mc_addr(ha, netdev) + memcpy(buf + i++ * ETH_ALEN, ha->addr, ETH_ALEN); } } diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index e5f2d3ee0df..37836a10d09 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -1117,7 +1117,7 @@ vxge_tx_term(void *dtrh, enum vxge_hw_txdl_state state, void *userdata) */ static void vxge_set_multicast(struct net_device *dev) { - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct vxgedev *vdev; int i, mcast_cnt = 0; struct __vxge_hw_device *hldev; @@ -1217,8 +1217,8 @@ static void vxge_set_multicast(struct net_device *dev) } /* Add new ones */ - netdev_for_each_mc_addr(mclist, dev) { - memcpy(mac_info.macaddr, mclist->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) { + memcpy(mac_info.macaddr, ha->addr, ETH_ALEN); for (vpath_idx = 0; vpath_idx < vdev->no_of_vpath; vpath_idx++) { mac_info.vpath_no = vpath_idx; diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 547912e6843..2277998b726 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1317,21 +1317,19 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev, } static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { - unsigned int bit_nr, i; + unsigned int bit_nr; u32 mc_filter[2]; + struct netdev_hw_addr *ha; mc_filter[1] = mc_filter[0] = 0; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_hw_addr_list_for_each(ha, mc_list) { + bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; bit_nr &= 0x3F; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - mclist = mclist->next; } return mc_filter[0] | ((u64)(mc_filter[1]) << 32); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 257c734733d..b43d4b006d7 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2045,21 +2045,17 @@ out: return err; } -static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mclist) +static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) { u64 mchash; - int i; + struct netdev_hw_addr *ha; /* always get broadcast frames */ mchash = 1ULL << (0xff >> 2); - for (i = 0; i < mc_count; i++) { - if (WARN_ON(!mclist)) - break; - mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); - mclist = mclist->next; - } + netdev_hw_addr_list_for_each(ha, mc_list) + mchash |= 1ULL << (ha->addr[5] >> 2); return mchash; } diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b142a78ed1e..53a2340f52b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -230,7 +230,7 @@ static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mc_list); + struct netdev_hw_addr_list *mc_list); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, @@ -2999,22 +2999,20 @@ unlock: } static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { u32 mfilt[2], val; - int i; u8 pos; + struct netdev_hw_addr *ha; mfilt[0] = 0; mfilt[1] = 1; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; + netdev_hw_addr_list_for_each(ha, mc_list) { /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); + val = get_unaligned_le32(ha->addr + 0); pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); + val = get_unaligned_le32(ha->addr + 3); pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; pos &= 0x3f; mfilt[pos / 32] |= (1 << (pos % 32)); @@ -3022,8 +3020,7 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, * but not sure, needs testing, if we do use this we'd * neet to inform below to not reset the mcast */ /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; + * ha->addr[5]); */ } return ((u64)(mfilt[1]) << 32) | mfilt[0]; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 3c889f43d90..ff7b0d0cca5 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -318,7 +318,7 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, struct net_device *dev, int nr_addrs) { int i = nr_addrs; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; int cnt; if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) @@ -326,19 +326,19 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, netif_addr_lock_bh(dev); cnt = netdev_mc_count(dev); - netdev_for_each_mc_addr(mc_list, dev) { - if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { + netdev_for_each_mc_addr(ha, dev) { + if (mac_in_list(cmd->maclist, nr_addrs, ha->addr)) { lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, - mc_list->dmi_addr); + ha->addr); cnt--; continue; } if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) break; - memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); + memcpy(&cmd->maclist[6*i], ha->addr, ETH_ALEN); lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, - mc_list->dmi_addr); + ha->addr); i++; cnt--; } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6ab30033c26..c20eef6b95c 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -367,22 +367,20 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) } static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct lbtf_private *priv = hw->priv; int i; + struct netdev_hw_addr *ha; + int mc_count = netdev_hw_addr_list_count(mc_list); if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) return mc_count; priv->nr_of_multicastmacaddr = mc_count; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - memcpy(&priv->multicastlist[i], mclist->da_addr, - ETH_ALEN); - mclist = mclist->next; - } + i = 0; + netdev_hw_addr_list_for_each(ha, mc_list) + memcpy(&priv->multicastlist[i++], ha->addr, ETH_ALEN); return mc_count; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ac65e13eb0d..6599fd15e67 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1938,11 +1938,15 @@ struct mwl8k_cmd_mac_multicast_adr { static struct mwl8k_cmd_pkt * __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_mac_multicast_adr *cmd; int size; + int mc_count = 0; + + if (mc_list) + mc_count = netdev_hw_addr_list_count(mc_list); if (allmulti || mc_count > priv->num_mcaddrs) { allmulti = 1; @@ -1963,17 +1967,13 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, if (allmulti) { cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST); } else if (mc_count) { - int i; + struct netdev_hw_addr *ha; + int i = 0; cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); cmd->numaddr = cpu_to_le16(mc_count); - for (i = 0; i < mc_count && mclist; i++) { - if (mclist->da_addrlen != ETH_ALEN) { - kfree(cmd); - return NULL; - } - memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); - mclist = mclist->next; + netdev_hw_addr_list_for_each(ha, mc_list) { + memcpy(cmd->addr[i], ha->addr, ETH_ALEN); } } @@ -3552,7 +3552,7 @@ mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct mwl8k_cmd_pkt *cmd; @@ -3563,7 +3563,7 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, * we'll end up throwing this packet away and creating a new * one in mwl8k_configure_filter(). */ - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_count, mclist); + cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_list); return (unsigned long)cmd; } @@ -3686,7 +3686,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, */ if (*total_flags & FIF_ALLMULTI) { kfree(cmd); - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, 0, NULL); + cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, NULL); } if (cmd != NULL) { diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 883b8f86862..9f657afaa3e 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -1056,14 +1056,14 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, * group address if either we want to multicast, or if we were * multicasting and want to stop */ if (!promisc && (mc_count || priv->mc_count)) { - struct dev_mc_list *p; + struct netdev_hw_addr *ha; struct hermes_multicast mclist; int i = 0; - netdev_for_each_mc_addr(p, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i == mc_count) break; - memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN); + memcpy(mclist.addr[i++], ha->addr, ETH_ALEN); } err = hermes_write_ltv(hw, USER_BAP, diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index 9799a1d14a6..97af71e7995 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h @@ -22,7 +22,6 @@ /* Forward declarations */ struct orinoco_private; -struct dev_addr_list; int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name, size_t fw_name_len, u32 *hw_ver); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 4f5bdb528ef..54680a3a5ac 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1875,17 +1875,17 @@ static void ray_update_multi_list(struct net_device *dev, int all) writeb(0xff, &pccs->var); local->num_multi = 0xff; } else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i = 0; /* Copy the kernel's list of MC addresses to card */ - netdev_for_each_mc_addr(dmi, dev) { - memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) { + memcpy_toio(p, ha->addr, ETH_ALEN); dev_dbg(&link->dev, "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", - dmi->dmi_addr[0], dmi->dmi_addr[1], - dmi->dmi_addr[2], dmi->dmi_addr[3], - dmi->dmi_addr[4], dmi->dmi_addr[5]); + ha->addr[0], ha->addr[1], + ha->addr[2], ha->addr[3], + ha->addr[4], ha->addr[5]); p += ETH_ALEN; i++; } diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index aceb95ef727..8ab9f094747 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1545,7 +1545,7 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) static void set_multicast_list(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; __le32 filter, basefilter; int ret; char *mc_addrs = NULL; @@ -1584,9 +1584,9 @@ static void set_multicast_list(struct usbnet *usbdev) return; } - netdev_for_each_mc_addr(mclist, usbdev->net) + netdev_for_each_mc_addr(ha, usbdev->net) memcpy(mc_addrs + i++ * ETH_ALEN, - mclist->dmi_addr, ETH_ALEN); + ha->addr, ETH_ALEN); } netif_addr_unlock_bh(usbdev->net); diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 2b928ecf47b..fb8a62f2b9b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -723,10 +723,10 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, priv->rf->conf_erp(dev, info); } -static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, - struct dev_addr_list *mc_list) +static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, + struct netdev_hw_addr_list *mc_list) { - return mc_count; + return netdev_hw_addr_list_count(mc_list); } static void rtl8180_configure_filter(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 0fb850e0c65..441d817ed48 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1193,9 +1193,9 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, } static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, - int mc_count, struct dev_addr_list *mc_list) + struct netdev_hw_addr_list *mc_list) { - return mc_count; + return netdev_hw_addr_list_count(mc_list); } static void rtl8187_configure_filter(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 3daba6c0c77..6036d0206fe 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1266,11 +1266,11 @@ struct wl1271_filter_params { u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; }; -static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mc_list) +static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) { struct wl1271_filter_params *fp; - int i; + struct netdev_hw_addr *ha; fp = kzalloc(sizeof(*fp), GFP_ATOMIC); if (!fp) { @@ -1279,21 +1279,16 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, } /* update multicast filtering parameters */ - fp->enabled = true; - if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { - mc_count = 0; - fp->enabled = false; - } - fp->mc_list_length = 0; - for (i = 0; i < mc_count; i++) { - if (mc_list->da_addrlen == ETH_ALEN) { + if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { + fp->enabled = false; + } else { + fp->enabled = true; + netdev_hw_addr_list_for_each(ha, mc_list) { memcpy(fp->mc_list[fp->mc_list_length], - mc_list->da_addr, ETH_ALEN); + ha->addr, ETH_ALEN); fp->mc_list_length++; - } else - wl1271_warning("Unknown mc address length."); - mc_list = mc_list->next; + } } return (u64)(unsigned long)fp; diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 6917286edca..74530b2d672 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -875,7 +875,7 @@ static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) static void zd1201_set_multicast(struct net_device *dev) { struct zd1201 *zd = netdev_priv(dev); - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; int i; @@ -883,8 +883,8 @@ static void zd1201_set_multicast(struct net_device *dev) return; i = 0; - netdev_for_each_mc_addr(mc, dev) - memcpy(reqbuf + i++ * ETH_ALEN, mc->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) + memcpy(reqbuf + i++ * ETH_ALEN, ha->addr, ETH_ALEN); zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, netdev_mc_count(dev) * ETH_ALEN, 0); } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 00e09e26c82..6d95e4d74d7 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -947,20 +947,17 @@ static void set_rx_filter_handler(struct work_struct *work) } static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct zd_mac *mac = zd_hw_mac(hw); struct zd_mc_hash hash; - int i; + struct netdev_hw_addr *ha; zd_mc_clear(&hash); - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); - zd_mc_add_addr(&hash, mclist->dmi_addr); - mclist = mclist->next; + netdev_hw_addr_list_for_each(ha, mc_list) { + dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", ha->addr); + zd_mc_add_addr(&hash, ha->addr); } return hash.low | ((u64)hash.high << 32); diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 7d4107f5eeb..34c91cf5d83 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1300,25 +1300,25 @@ static void set_rx_mode(struct net_device *dev) /* Too many to filter well, or accept all multicasts. */ iowrite16(0x000B, ioaddr + AddrMode); } else if (!netdev_mc_empty(dev)) { /* Must use the multicast hash table. */ - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; u16 hash_table[4]; int i; memset(hash_table, 0, sizeof(hash_table)); - netdev_for_each_mc_addr(mclist, dev) { + netdev_for_each_mc_addr(ha, dev) { unsigned int bit; /* Due to a bug in the early chip versions, multiple filter slots must be set for each address. */ if (yp->drv_flags & HasMulticastBug) { - bit = (ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f; + bit = (ether_crc_le(3, ha->addr) >> 3) & 0x3f; hash_table[bit >> 4] |= (1 << bit); - bit = (ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f; + bit = (ether_crc_le(4, ha->addr) >> 3) & 0x3f; hash_table[bit >> 4] |= (1 << bit); - bit = (ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f; + bit = (ether_crc_le(5, ha->addr) >> 3) & 0x3f; hash_table[bit >> 4] |= (1 << bit); } - bit = (ether_crc_le(6, mclist->dmi_addr) >> 3) & 0x3f; + bit = (ether_crc_le(6, ha->addr) >> 3) & 0x3f; hash_table[bit >> 4] |= (1 << bit); } /* Copy the hash table to the chip. */ diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 7576ad5a833..945f3e0a9f0 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -607,7 +607,6 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) static void qeth_l2_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; - struct dev_addr_list *dm; struct netdev_hw_addr *ha; if (card->info.type == QETH_CARD_TYPE_OSN) @@ -619,8 +618,8 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) return; qeth_l2_del_all_mc(card); spin_lock_bh(&card->mclock); - netdev_for_each_mc_addr(dm, dev) - qeth_l2_add_mc(card, dm->da_addr, 0); + netdev_for_each_mc_addr(ha, dev) + qeth_l2_add_mc(card, ha->addr, 0); netdev_for_each_uc_addr(ha, dev) qeth_l2_add_mc(card, ha->addr, 1); diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index de33e38a405..37de40e0168 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -311,7 +311,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, dev_uc_add(netdev, flogi_maddr); if (fip->spma) dev_uc_add(netdev, fip->ctl_src_addr); - dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); + dev_mc_add(netdev, FIP_ALL_ENODE_MACS); /* * setup the receive function from ethernet driver @@ -397,7 +397,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) dev_uc_del(netdev, flogi_maddr); if (fip->spma) dev_uc_del(netdev, fip->ctl_src_addr); - dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); + dev_mc_del(netdev, FIP_ALL_ENODE_MACS); /* Tell the LLD we are done w/ FCoE */ ops = netdev->netdev_ops; diff --git a/drivers/staging/arlan/arlan-main.c b/drivers/staging/arlan/arlan-main.c index 88fdd53cf5d..80284522c42 100644 --- a/drivers/staging/arlan/arlan-main.c +++ b/drivers/staging/arlan/arlan-main.c @@ -1458,7 +1458,7 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short !netdev_mc_empty(dev)) { char hw_dst_addr[6]; - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i; memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6); @@ -1469,12 +1469,13 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short printk(KERN_ERR "%s mcast 0x0100 \n", dev->name); else if (hw_dst_addr[1] == 0x40) printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name); - netdev_for_each_mc_entry(dmi, dev) { + netdev_for_each_mc_entry(ha, dev) { if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) printk(KERN_ERR "%s mcl %pM\n", - dev->name, dmi->dmi_addr); + dev->name, + ha->addr); for (i = 0; i < 6; i++) - if (dmi->dmi_addr[i] != hw_dst_addr[i]) + if (ha->addr[i] != hw_dst_addr[i]) break; if (i == 6) break; diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index 40f8954dde4..2fb89cddef1 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -405,7 +405,7 @@ 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; + struct netdev_hw_addr *ha; int i; spin_lock_irqsave(&adapter->Lock, flags); @@ -450,10 +450,10 @@ void et131x_multicast(struct net_device *netdev) /* Set values in the private adapter struct */ i = 0; - netdev_for_each_mc_addr(mclist, netdev) { + netdev_for_each_mc_addr(ha, netdev) { if (i == NIC_MAX_MCAST_LIST) break; - memcpy(adapter->MCList[i++], mclist->dmi_addr, ETH_ALEN); + memcpy(adapter->MCList[i++], ha->addr, ETH_ALEN); } adapter->MCAddressCount = i; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 7daeced317c..bebf0fd2af8 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1367,12 +1367,12 @@ static void slic_mcast_set_list(struct net_device *dev) struct adapter *adapter = netdev_priv(dev); int status = STATUS_SUCCESS; char *addresses; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; ASSERT(adapter); - netdev_for_each_mc_addr(mc_list, dev) { - addresses = (char *) &mc_list->dmi_addr; + netdev_for_each_mc_addr(ha, dev) { + addresses = (char *) &ha->addr; status = slic_mcast_add_list(adapter, addresses); if (status != STATUS_SUCCESS) break; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 1d643653a7e..b698de40a60 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -3079,7 +3079,7 @@ static void device_set_multi(struct net_device *dev) { PSMgmtObject pMgmt = pDevice->pMgmt; u32 mc_filter[2]; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); @@ -3099,8 +3099,8 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); } MACvSelectPage1(pDevice->PortOffset); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index a8e1adbc959..49270db98fb 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1596,7 +1596,7 @@ static void device_set_multi(struct net_device *dev) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); u32 mc_filter[2]; int ii; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; BYTE pbyData[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; BYTE byTmpMode = 0; int rc; @@ -1632,8 +1632,8 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); } for (ii = 0; ii < 4; ii++) { diff --git a/drivers/staging/wavelan/wavelan.c b/drivers/staging/wavelan/wavelan.c index 54ca63196fd..f44ef351647 100644 --- a/drivers/staging/wavelan/wavelan.c +++ b/drivers/staging/wavelan/wavelan.c @@ -3419,7 +3419,7 @@ static void wv_82586_config(struct net_device * dev) ac_cfg_t cfg; /* Configure action */ ac_ias_t ias; /* IA-setup action */ ac_mcs_t mcs; /* Multicast setup */ - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name); @@ -3531,16 +3531,16 @@ static void wv_82586_config(struct net_device * dev) /* Any address to set? */ if (lp->mc_count) { - netdev_for_each_mc_addr(dmi, dev) - outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr, + netdev_for_each_mc_addr(ha, dev) + outsw(PIOP1(ioaddr), (u16 *) ha->addr, WAVELAN_ADDR_SIZE >> 1); #ifdef DEBUG_CONFIG_INFO printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n", dev->name, lp->mc_count); - netdev_for_each_mc_addr(dmi, dev) - printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + printk(KERN_DEBUG " %pM\n", ha->addr); #endif } diff --git a/drivers/staging/wavelan/wavelan_cs.c b/drivers/staging/wavelan/wavelan_cs.c index 04f691d127b..a90132a204e 100644 --- a/drivers/staging/wavelan/wavelan_cs.c +++ b/drivers/staging/wavelan/wavelan_cs.c @@ -3591,20 +3591,20 @@ wv_82593_config(struct net_device * dev) /* If roaming is enabled, join the "Beacon Request" multicast group... */ /* But only if it's not in there already! */ if(do_roaming) - dev_mc_add(dev,WAVELAN_BEACON_ADDRESS, WAVELAN_ADDR_SIZE, 1); + dev_mc_add(dev, WAVELAN_BEACON_ADDRESS); #endif /* WAVELAN_ROAMING */ /* If any multicast address to set */ if(lp->mc_count) { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count; #ifdef DEBUG_CONFIG_INFO printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n", dev->name, lp->mc_count); - netdev_for_each_mc_addr(dmi, dev) - printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); + netdev_for_each_mc_addr(ha, dev) + printk(KERN_DEBUG " %pM\n", ha->addr); #endif /* Initialize adapter's ethernet multicast addresses */ @@ -3612,8 +3612,8 @@ wv_82593_config(struct net_device * dev) outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); outb(addrs_len & 0xff, PIOP(base)); /* byte count lsb */ outb((addrs_len >> 8), PIOP(base)); /* byte count msb */ - netdev_for_each_mc_addr(dmi, dev) - outsb(PIOP(base), dmi->dmi_addr, dmi->dmi_addrlen); + netdev_for_each_mc_addr(ha, dev) + outsb(PIOP(base), ha->addr, dev->addr_len); /* reset transmit DMA pointer */ hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index 3482eec1865..5d9499bba9c 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -92,10 +92,10 @@ static int wbsoft_get_stats(struct ieee80211_hw *hw, return 0; } -static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mc_list) +static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) { - return mc_count; + return netdev_hw_addr_list_count(mc_list); } static void wbsoft_configure_filter(struct ieee80211_hw *dev, diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c index fa082d90fca..d7532e89f5f 100644 --- a/drivers/staging/wlags49_h2/wl_netdev.c +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -1049,7 +1049,7 @@ void wl_multicast( struct net_device *dev ) //;?seems reasonable that even an AP-only driver could afford this small additional footprint int x; - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; struct wl_private *lp = wl_priv(dev); unsigned long flags; /*------------------------------------------------------------------------*/ @@ -1072,9 +1072,9 @@ void wl_multicast( struct net_device *dev ) DBG_PRINT( " mc_count: %d\n", netdev_mc_count(dev)); - netdev_for_each_mc_addr(mclist, dev) - DBG_PRINT( " %s (%d)\n", DbgHwAddr(mclist->dmi_addr), - mclist->dmi_addrlen ); + netdev_for_each_mc_addr(ha, dev) + DBG_PRINT(" %s (%d)\n", DbgHwAddr(ha->addr), + dev->addr_len); } #endif /* DBG */ @@ -1119,9 +1119,9 @@ void wl_multicast( struct net_device *dev ) lp->ltvRecord.typ = CFG_GROUP_ADDR; x = 0; - netdev_for_each_mc_addr(mclist, dev) + netdev_for_each_mc_addr(ha, dev) memcpy(&(lp->ltvRecord.u.u8[x++ * ETH_ALEN]), - mclist->dmi_addr, ETH_ALEN); + ha->addr, ETH_ALEN); DBG_PRINT( "Setting multicast list\n" ); hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); } else { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 60f0c83192f..a343a21ba8b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -228,25 +228,6 @@ struct netif_rx_stats { DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); -struct dev_addr_list { - struct dev_addr_list *next; - u8 da_addr[MAX_ADDR_LEN]; - u8 da_addrlen; - u8 da_synced; - int da_users; - int da_gusers; -}; - -/* - * We tag multicasts with these structures. - */ - -#define dev_mc_list dev_addr_list -#define dmi_addr da_addr -#define dmi_addrlen da_addrlen -#define dmi_users da_users -#define dmi_gusers da_gusers - struct netdev_hw_addr { struct list_head list; unsigned char addr[MAX_ADDR_LEN]; @@ -255,8 +236,10 @@ struct netdev_hw_addr { #define NETDEV_HW_ADDR_T_SAN 2 #define NETDEV_HW_ADDR_T_SLAVE 3 #define NETDEV_HW_ADDR_T_UNICAST 4 +#define NETDEV_HW_ADDR_T_MULTICAST 5 int refcount; bool synced; + bool global_use; struct rcu_head rcu_head; }; @@ -265,16 +248,20 @@ struct netdev_hw_addr_list { int count; }; -#define netdev_uc_count(dev) ((dev)->uc.count) -#define netdev_uc_empty(dev) ((dev)->uc.count == 0) -#define netdev_for_each_uc_addr(ha, dev) \ - list_for_each_entry(ha, &dev->uc.list, list) +#define netdev_hw_addr_list_count(l) ((l)->count) +#define netdev_hw_addr_list_empty(l) (netdev_hw_addr_list_count(l) == 0) +#define netdev_hw_addr_list_for_each(ha, l) \ + list_for_each_entry(ha, &(l)->list, list) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) +#define netdev_uc_count(dev) netdev_hw_addr_list_count(&(dev)->uc) +#define netdev_uc_empty(dev) netdev_hw_addr_list_empty(&(dev)->uc) +#define netdev_for_each_uc_addr(ha, dev) \ + netdev_hw_addr_list_for_each(ha, &(dev)->uc) +#define netdev_mc_count(dev) netdev_hw_addr_list_count(&(dev)->mc) +#define netdev_mc_empty(dev) netdev_hw_addr_list_empty(&(dev)->mc) #define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) + netdev_hw_addr_list_for_each(ha, &(dev)->mc) struct hh_cache { struct hh_cache *hh_next; /* Next entry */ @@ -862,12 +849,10 @@ struct net_device { unsigned char addr_len; /* hardware address length */ unsigned short dev_id; /* for shared network cards */ - struct netdev_hw_addr_list uc; /* Secondary unicast - mac addresses */ - int uc_promisc; spinlock_t addr_list_lock; - struct dev_addr_list *mc_list; /* Multicast mac addresses */ - int mc_count; /* Number of installed mcasts */ + struct netdev_hw_addr_list uc; /* Unicast mac addresses */ + struct netdev_hw_addr_list mc; /* Multicast mac addresses */ + int uc_promisc; unsigned int promiscuity; unsigned int allmulti; @@ -1980,6 +1965,22 @@ extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, extern int register_netdev(struct net_device *dev); extern void unregister_netdev(struct net_device *dev); +/* General hardware address lists handling functions */ +extern int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type); +extern void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type); +extern int __hw_addr_sync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len); +extern void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len); +extern void __hw_addr_flush(struct netdev_hw_addr_list *list); +extern void __hw_addr_init(struct netdev_hw_addr_list *list); + /* Functions used for device addresses handling */ extern int dev_addr_add(struct net_device *dev, unsigned char *addr, unsigned char addr_type); @@ -2002,18 +2003,19 @@ extern void dev_uc_unsync(struct net_device *to, struct net_device *from); extern void dev_uc_flush(struct net_device *dev); extern void dev_uc_init(struct net_device *dev); +/* Functions used for multicast addresses handling */ +extern int dev_mc_add(struct net_device *dev, unsigned char *addr); +extern int dev_mc_add_global(struct net_device *dev, unsigned char *addr); +extern int dev_mc_del(struct net_device *dev, unsigned char *addr); +extern int dev_mc_del_global(struct net_device *dev, unsigned char *addr); +extern int dev_mc_sync(struct net_device *to, struct net_device *from); +extern void dev_mc_unsync(struct net_device *to, struct net_device *from); +extern void dev_mc_flush(struct net_device *dev); +extern void dev_mc_init(struct net_device *dev); + /* Functions used for secondary unicast and multicast support */ extern void dev_set_rx_mode(struct net_device *dev); extern void __dev_set_rx_mode(struct net_device *dev); -extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); -extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); -extern int dev_mc_sync(struct net_device *to, struct net_device *from); -extern void dev_mc_unsync(struct net_device *to, struct net_device *from); -extern void dev_addr_discard(struct net_device *dev); -extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all); -extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly); -extern int __dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count); -extern void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count); extern int dev_set_promiscuity(struct net_device *dev, int inc); extern int dev_set_allmulti(struct net_device *dev, int inc); extern void netdev_state_change(struct net_device *dev); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1a8f50af49a..20823d04e03 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1626,7 +1626,7 @@ struct ieee80211_ops { struct ieee80211_bss_conf *info, u32 changed); u64 (*prepare_multicast)(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mc_list); + struct netdev_hw_addr_list *mc_list); void (*configure_filter)(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, diff --git a/net/802/garp.c b/net/802/garp.c index 1dcb0660c49..78cff9ec2cb 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -575,7 +575,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl) if (!app) goto err2; - err = dev_mc_add(dev, appl->proto.group_address, ETH_ALEN, 0); + err = dev_mc_add(dev, appl->proto.group_address); if (err < 0) goto err3; @@ -615,7 +615,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl garp_pdu_queue(app); garp_queue_xmit(app); - dev_mc_delete(dev, appl->proto.group_address, ETH_ALEN, 0); + dev_mc_del(dev, appl->proto.group_address); kfree(app); garp_release_port(dev); } diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 9fc4da56fb1..1d15a60b23a 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -781,7 +781,7 @@ static int atif_ioctl(int cmd, void __user *arg) atrtr_create(&rtdef, dev); } } - dev_mc_add(dev, aarp_mcast, 6, 1); + dev_mc_add_global(dev, aarp_mcast); return 0; case SIOCGIFADDR: diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 326ab453edb..260a9507e54 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -87,7 +87,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); r->len = htons(ETH_ALEN * 2); } else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i, len = skb->len; if (dev->flags & IFF_BROADCAST) { @@ -98,11 +98,11 @@ static void bnep_net_set_mc_list(struct net_device *dev) /* FIXME: We should group addresses here. */ i = 0; - netdev_for_each_mc_addr(dmi, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i == BNEP_MAX_MULTICAST_FILTERS) break; - memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); - memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); + memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); + memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); } r->len = htons(skb->len - len); } diff --git a/net/core/Makefile b/net/core/Makefile index 0a899f1aadb..51c3eec850e 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -7,9 +7,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o -obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ - neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ - dev_addr_lists.o +obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ + neighbour.o rtnetlink.o utils.o link_watch.o filter.o obj-$(CONFIG_XFRM) += flow.o obj-y += net-sysfs.o diff --git a/net/core/dev.c b/net/core/dev.c index 949c62dba71..2a9b7dd0bb6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3968,140 +3968,6 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } -/* multicast addresses handling functions */ - -int __dev_addr_delete(struct dev_addr_list **list, int *count, - void *addr, int alen, int glbl) -{ - struct dev_addr_list *da; - - for (; (da = *list) != NULL; list = &da->next) { - if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && - alen == da->da_addrlen) { - if (glbl) { - int old_glbl = da->da_gusers; - da->da_gusers = 0; - if (old_glbl == 0) - break; - } - if (--da->da_users) - return 0; - - *list = da->next; - kfree(da); - (*count)--; - return 0; - } - } - return -ENOENT; -} - -int __dev_addr_add(struct dev_addr_list **list, int *count, - void *addr, int alen, int glbl) -{ - struct dev_addr_list *da; - - for (da = *list; da != NULL; da = da->next) { - if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && - da->da_addrlen == alen) { - if (glbl) { - int old_glbl = da->da_gusers; - da->da_gusers = 1; - if (old_glbl) - return 0; - } - da->da_users++; - return 0; - } - } - - da = kzalloc(sizeof(*da), GFP_ATOMIC); - if (da == NULL) - return -ENOMEM; - memcpy(da->da_addr, addr, alen); - da->da_addrlen = alen; - da->da_users = 1; - da->da_gusers = glbl ? 1 : 0; - da->next = *list; - *list = da; - (*count)++; - return 0; -} - - -int __dev_addr_sync(struct dev_addr_list **to, int *to_count, - struct dev_addr_list **from, int *from_count) -{ - struct dev_addr_list *da, *next; - int err = 0; - - da = *from; - while (da != NULL) { - next = da->next; - if (!da->da_synced) { - err = __dev_addr_add(to, to_count, - da->da_addr, da->da_addrlen, 0); - if (err < 0) - break; - da->da_synced = 1; - da->da_users++; - } else if (da->da_users == 1) { - __dev_addr_delete(to, to_count, - da->da_addr, da->da_addrlen, 0); - __dev_addr_delete(from, from_count, - da->da_addr, da->da_addrlen, 0); - } - da = next; - } - return err; -} -EXPORT_SYMBOL_GPL(__dev_addr_sync); - -void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, - struct dev_addr_list **from, int *from_count) -{ - struct dev_addr_list *da, *next; - - da = *from; - while (da != NULL) { - next = da->next; - if (da->da_synced) { - __dev_addr_delete(to, to_count, - da->da_addr, da->da_addrlen, 0); - da->da_synced = 0; - __dev_addr_delete(from, from_count, - da->da_addr, da->da_addrlen, 0); - } - da = next; - } -} -EXPORT_SYMBOL_GPL(__dev_addr_unsync); - -static void __dev_addr_discard(struct dev_addr_list **list) -{ - struct dev_addr_list *tmp; - - while (*list != NULL) { - tmp = *list; - *list = tmp->next; - if (tmp->da_users > tmp->da_gusers) - printk("__dev_addr_discard: address leakage! " - "da_users=%d\n", tmp->da_users); - kfree(tmp); - } -} - -void dev_addr_discard(struct net_device *dev) -{ - netif_addr_lock_bh(dev); - - __dev_addr_discard(&dev->mc_list); - netdev_mc_count(dev) = 0; - - netif_addr_unlock_bh(dev); -} -EXPORT_SYMBOL(dev_addr_discard); - /** * dev_get_flags - get flags reported to userspace * @dev: device @@ -4412,8 +4278,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) return -EINVAL; if (!netif_device_present(dev)) return -ENODEV; - return dev_mc_add(dev, ifr->ifr_hwaddr.sa_data, - dev->addr_len, 1); + return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data); case SIOCDELMULTI: if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || @@ -4421,8 +4286,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) return -EINVAL; if (!netif_device_present(dev)) return -ENODEV; - return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data, - dev->addr_len, 1); + return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data); case SIOCSIFTXQLEN: if (ifr->ifr_qlen < 0) @@ -4730,7 +4594,7 @@ static void rollback_registered_many(struct list_head *head) * Flush the unicast and multicast chains */ dev_uc_flush(dev); - dev_addr_discard(dev); + dev_mc_flush(dev); if (dev->netdev_ops->ndo_uninit) dev->netdev_ops->ndo_uninit(dev); @@ -5310,6 +5174,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, if (dev_addr_init(dev)) goto free_rx; + dev_mc_init(dev); dev_uc_init(dev); dev_net_set(dev, &init_net); @@ -5545,7 +5410,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char * Flush the unicast and multicast chains */ dev_uc_flush(dev); - dev_addr_discard(dev); + dev_mc_flush(dev); netdev_unregister_kobject(dev); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 7e52b6d18ad..37d5975e18a 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -19,8 +19,9 @@ * General list handling functions */ -static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, - int addr_len, unsigned char addr_type) +static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, + unsigned char *addr, int addr_len, + unsigned char addr_type, bool global) { struct netdev_hw_addr *ha; int alloc_size; @@ -31,6 +32,13 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, list_for_each_entry(ha, &list->list, list) { if (!memcmp(ha->addr, addr, addr_len) && ha->type == addr_type) { + if (global) { + /* check if addr is already used as global */ + if (ha->global_use) + return 0; + else + ha->global_use = true; + } ha->refcount++; return 0; } @@ -46,12 +54,19 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, memcpy(ha->addr, addr, addr_len); ha->type = addr_type; ha->refcount = 1; + ha->global_use = global; ha->synced = false; list_add_tail_rcu(&ha->list, &list->list); list->count++; return 0; } +static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, + int addr_len, unsigned char addr_type) +{ + return __hw_addr_add_ex(list, addr, addr_len, addr_type, false); +} + static void ha_rcu_free(struct rcu_head *head) { struct netdev_hw_addr *ha; @@ -60,14 +75,21 @@ static void ha_rcu_free(struct rcu_head *head) kfree(ha); } -static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, - int addr_len, unsigned char addr_type) +static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, + unsigned char *addr, int addr_len, + unsigned char addr_type, bool global) { struct netdev_hw_addr *ha; list_for_each_entry(ha, &list->list, list) { if (!memcmp(ha->addr, addr, addr_len) && (ha->type == addr_type || !addr_type)) { + if (global) { + if (!ha->global_use) + break; + else + ha->global_use = false; + } if (--ha->refcount) return 0; list_del_rcu(&ha->list); @@ -79,10 +101,15 @@ static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, return -ENOENT; } -static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, - unsigned char addr_type) +static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, + int addr_len, unsigned char addr_type) +{ + return __hw_addr_del_ex(list, addr, addr_len, addr_type, false); +} + +int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type) { int err; struct netdev_hw_addr *ha, *ha2; @@ -105,11 +132,11 @@ unroll: } return err; } +EXPORT_SYMBOL(__hw_addr_add_multiple); -static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, - unsigned char addr_type) +void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type) { struct netdev_hw_addr *ha; unsigned char type; @@ -119,10 +146,11 @@ static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, __hw_addr_del(to_list, ha->addr, addr_len, addr_type); } } +EXPORT_SYMBOL(__hw_addr_del_multiple); -static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len) +int __hw_addr_sync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len) { int err = 0; struct netdev_hw_addr *ha, *tmp; @@ -142,10 +170,11 @@ static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, } return err; } +EXPORT_SYMBOL(__hw_addr_sync); -static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len) +void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len) { struct netdev_hw_addr *ha, *tmp; @@ -159,8 +188,9 @@ static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, } } } +EXPORT_SYMBOL(__hw_addr_unsync); -static void __hw_addr_flush(struct netdev_hw_addr_list *list) +void __hw_addr_flush(struct netdev_hw_addr_list *list) { struct netdev_hw_addr *ha, *tmp; @@ -170,12 +200,14 @@ static void __hw_addr_flush(struct netdev_hw_addr_list *list) } list->count = 0; } +EXPORT_SYMBOL(__hw_addr_flush); -static void __hw_addr_init(struct netdev_hw_addr_list *list) +void __hw_addr_init(struct netdev_hw_addr_list *list) { INIT_LIST_HEAD(&list->list); list->count = 0; } +EXPORT_SYMBOL(__hw_addr_init); /* * Device addresses handling functions @@ -475,4 +507,235 @@ EXPORT_SYMBOL(dev_uc_init); * Multicast list handling functions */ -/* To be filled here */ +static int __dev_mc_add(struct net_device *dev, unsigned char *addr, + bool global) +{ + int err; + + netif_addr_lock_bh(dev); + err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_MULTICAST, global); + if (!err) + __dev_set_rx_mode(dev); + netif_addr_unlock_bh(dev); + return err; +} +/** + * dev_mc_add - Add a multicast address + * @dev: device + * @addr: address to add + * + * Add a multicast address to the device or increase + * the reference count if it already exists. + */ +int dev_mc_add(struct net_device *dev, unsigned char *addr) +{ + return __dev_mc_add(dev, addr, false); +} +EXPORT_SYMBOL(dev_mc_add); + +/** + * dev_mc_add_global - Add a global multicast address + * @dev: device + * @addr: address to add + * + * Add a global multicast address to the device. + */ +int dev_mc_add_global(struct net_device *dev, unsigned char *addr) +{ + return __dev_mc_add(dev, addr, true); +} +EXPORT_SYMBOL(dev_mc_add_global); + +static int __dev_mc_del(struct net_device *dev, unsigned char *addr, + bool global) +{ + int err; + + netif_addr_lock_bh(dev); + err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_MULTICAST, global); + if (!err) + __dev_set_rx_mode(dev); + netif_addr_unlock_bh(dev); + return err; +} + +/** + * dev_mc_del - Delete a multicast address. + * @dev: device + * @addr: address to delete + * + * Release reference to a multicast address and remove it + * from the device if the reference count drops to zero. + */ +int dev_mc_del(struct net_device *dev, unsigned char *addr) +{ + return __dev_mc_del(dev, addr, false); +} +EXPORT_SYMBOL(dev_mc_del); + +/** + * dev_mc_del_global - Delete a global multicast address. + * @dev: device + * @addr: address to delete + * + * Release reference to a multicast address and remove it + * from the device if the reference count drops to zero. + */ +int dev_mc_del_global(struct net_device *dev, unsigned char *addr) +{ + return __dev_mc_del(dev, addr, true); +} +EXPORT_SYMBOL(dev_mc_del_global); + +/** + * dev_mc_sync - Synchronize device's unicast list to another device + * @to: destination device + * @from: source device + * + * Add newly added addresses to the destination device and release + * addresses that have no users left. The source device must be + * locked by netif_tx_lock_bh. + * + * This function is intended to be called from the dev->set_multicast_list + * or dev->set_rx_mode function of layered software devices. + */ +int dev_mc_sync(struct net_device *to, struct net_device *from) +{ + int err = 0; + + if (to->addr_len != from->addr_len) + return -EINVAL; + + netif_addr_lock_bh(to); + err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); + if (!err) + __dev_set_rx_mode(to); + netif_addr_unlock_bh(to); + return err; +} +EXPORT_SYMBOL(dev_mc_sync); + +/** + * dev_mc_unsync - Remove synchronized addresses from the destination device + * @to: destination device + * @from: source device + * + * Remove all addresses that were added to the destination device by + * dev_mc_sync(). This function is intended to be called from the + * dev->stop function of layered software devices. + */ +void dev_mc_unsync(struct net_device *to, struct net_device *from) +{ + if (to->addr_len != from->addr_len) + return; + + netif_addr_lock_bh(from); + netif_addr_lock(to); + __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); + __dev_set_rx_mode(to); + netif_addr_unlock(to); + netif_addr_unlock_bh(from); +} +EXPORT_SYMBOL(dev_mc_unsync); + +/** + * dev_mc_flush - Flush multicast addresses + * @dev: device + * + * Flush multicast addresses. + */ +void dev_mc_flush(struct net_device *dev) +{ + netif_addr_lock_bh(dev); + __hw_addr_flush(&dev->mc); + netif_addr_unlock_bh(dev); +} +EXPORT_SYMBOL(dev_mc_flush); + +/** + * dev_mc_flush - Init multicast address list + * @dev: device + * + * Init multicast address list. + */ +void dev_mc_init(struct net_device *dev) +{ + __hw_addr_init(&dev->mc); +} +EXPORT_SYMBOL(dev_mc_init); + +#ifdef CONFIG_PROC_FS +#include +#include + +static int dev_mc_seq_show(struct seq_file *seq, void *v) +{ + struct netdev_hw_addr *ha; + struct net_device *dev = v; + + if (v == SEQ_START_TOKEN) + return 0; + + netif_addr_lock_bh(dev); + netdev_for_each_mc_addr(ha, dev) { + int i; + + seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, + dev->name, ha->refcount, ha->global_use); + + for (i = 0; i < dev->addr_len; i++) + seq_printf(seq, "%02x", ha->addr[i]); + + seq_putc(seq, '\n'); + } + netif_addr_unlock_bh(dev); + return 0; +} + +static const struct seq_operations dev_mc_seq_ops = { + .start = dev_seq_start, + .next = dev_seq_next, + .stop = dev_seq_stop, + .show = dev_mc_seq_show, +}; + +static int dev_mc_seq_open(struct inode *inode, struct file *file) +{ + return seq_open_net(inode, file, &dev_mc_seq_ops, + sizeof(struct seq_net_private)); +} + +static const struct file_operations dev_mc_seq_fops = { + .owner = THIS_MODULE, + .open = dev_mc_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_net, +}; + +#endif + +static int __net_init dev_mc_net_init(struct net *net) +{ + if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) + return -ENOMEM; + return 0; +} + +static void __net_exit dev_mc_net_exit(struct net *net) +{ + proc_net_remove(net, "dev_mcast"); +} + +static struct pernet_operations __net_initdata dev_mc_net_ops = { + .init = dev_mc_net_init, + .exit = dev_mc_net_exit, +}; + +void __init dev_mcast_init(void) +{ + register_pernet_subsys(&dev_mc_net_ops); +} + diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c deleted file mode 100644 index 3dc295beb48..00000000000 --- a/net/core/dev_mcast.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Linux NET3: Multicast List maintenance. - * - * Authors: - * Tim Kordas - * Richard Underwood - * - * Stir fried together from the IP multicast and CAP patches above - * Alan Cox - * - * Fixes: - * Alan Cox : Update the device on a real delete - * rather than any time but... - * Alan Cox : IFF_ALLMULTI support. - * Alan Cox : New format set_multicast_list() calls. - * Gleb Natapov : Remove dev_mc_lock. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Device multicast list maintenance. - * - * This is used both by IP and by the user level maintenance functions. - * Unlike BSD we maintain a usage count on a given multicast address so - * that a casual user application can add/delete multicasts used by - * protocols without doing damage to the protocols when it deletes the - * entries. It also helps IP as it tracks overlapping maps. - * - * Device mc lists are changed by bh at least if IPv6 is enabled, - * so that it must be bh protected. - * - * We block accesses to device mc filters with netif_tx_lock. - */ - -/* - * Delete a device level multicast - */ - -int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) -{ - int err; - - netif_addr_lock_bh(dev); - err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, - addr, alen, glbl); - if (!err) { - /* - * We have altered the list, so the card - * loaded filter is now wrong. Fix it - */ - - __dev_set_rx_mode(dev); - } - netif_addr_unlock_bh(dev); - return err; -} - -/* - * Add a device level multicast - */ - -int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) -{ - int err; - - netif_addr_lock_bh(dev); - if (alen != dev->addr_len) - err = -EINVAL; - else - err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); - if (!err) - __dev_set_rx_mode(dev); - netif_addr_unlock_bh(dev); - return err; -} - -/** - * dev_mc_sync - Synchronize device's multicast list to another device - * @to: destination device - * @from: source device - * - * Add newly added addresses to the destination device and release - * addresses that have no users left. The source device must be - * locked by netif_tx_lock_bh. - * - * This function is intended to be called from the dev->set_multicast_list - * or dev->set_rx_mode function of layered software devices. - */ -int dev_mc_sync(struct net_device *to, struct net_device *from) -{ - int err = 0; - - netif_addr_lock_bh(to); - err = __dev_addr_sync(&to->mc_list, &to->mc_count, - &from->mc_list, &from->mc_count); - if (!err) - __dev_set_rx_mode(to); - netif_addr_unlock_bh(to); - - return err; -} -EXPORT_SYMBOL(dev_mc_sync); - - -/** - * dev_mc_unsync - Remove synchronized addresses from the destination - * device - * @to: destination device - * @from: source device - * - * Remove all addresses that were added to the destination device by - * dev_mc_sync(). This function is intended to be called from the - * dev->stop function of layered software devices. - */ -void dev_mc_unsync(struct net_device *to, struct net_device *from) -{ - netif_addr_lock_bh(from); - netif_addr_lock(to); - - __dev_addr_unsync(&to->mc_list, &to->mc_count, - &from->mc_list, &from->mc_count); - __dev_set_rx_mode(to); - - netif_addr_unlock(to); - netif_addr_unlock_bh(from); -} -EXPORT_SYMBOL(dev_mc_unsync); - -#ifdef CONFIG_PROC_FS -static int dev_mc_seq_show(struct seq_file *seq, void *v) -{ - struct dev_addr_list *m; - struct net_device *dev = v; - - if (v == SEQ_START_TOKEN) - return 0; - - netif_addr_lock_bh(dev); - for (m = dev->mc_list; m; m = m->next) { - int i; - - seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, - dev->name, m->dmi_users, m->dmi_gusers); - - for (i = 0; i < m->dmi_addrlen; i++) - seq_printf(seq, "%02x", m->dmi_addr[i]); - - seq_putc(seq, '\n'); - } - netif_addr_unlock_bh(dev); - return 0; -} - -static const struct seq_operations dev_mc_seq_ops = { - .start = dev_seq_start, - .next = dev_seq_next, - .stop = dev_seq_stop, - .show = dev_mc_seq_show, -}; - -static int dev_mc_seq_open(struct inode *inode, struct file *file) -{ - return seq_open_net(inode, file, &dev_mc_seq_ops, - sizeof(struct seq_net_private)); -} - -static const struct file_operations dev_mc_seq_fops = { - .owner = THIS_MODULE, - .open = dev_mc_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_net, -}; - -#endif - -static int __net_init dev_mc_net_init(struct net *net) -{ - if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) - return -ENOMEM; - return 0; -} - -static void __net_exit dev_mc_net_exit(struct net *net) -{ - proc_net_remove(net, "dev_mcast"); -} - -static struct pernet_operations __net_initdata dev_mc_net_ops = { - .init = dev_mc_net_init, - .exit = dev_mc_net_exit, -}; - -void __init dev_mcast_init(void) -{ - register_pernet_subsys(&dev_mc_net_ops); -} - -EXPORT_SYMBOL(dev_mc_add); -EXPORT_SYMBOL(dev_mc_delete); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 238af093495..f3e4734d207 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -349,7 +349,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de if (dn_db->dev->type == ARPHRD_ETHER) { if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { dn_dn2eth(mac_addr, ifa1->ifa_local); - dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); + dev_mc_del(dev, mac_addr); } } @@ -380,7 +380,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) if (dev->type == ARPHRD_ETHER) { if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { dn_dn2eth(mac_addr, ifa->ifa_local); - dev_mc_add(dev, mac_addr, ETH_ALEN, 0); + dev_mc_add(dev, mac_addr); } } @@ -1000,9 +1000,9 @@ static int dn_eth_up(struct net_device *dev) struct dn_dev *dn_db = dev->dn_ptr; if (dn_db->parms.forwarding == 0) - dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); + dev_mc_add(dev, dn_rt_all_end_mcast); else - dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); + dev_mc_add(dev, dn_rt_all_rt_mcast); dn_db->use_long = 1; @@ -1014,9 +1014,9 @@ static void dn_eth_down(struct net_device *dev) struct dn_dev *dn_db = dev->dn_ptr; if (dn_db->parms.forwarding == 0) - dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); + dev_mc_del(dev, dn_rt_all_end_mcast); else - dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); + dev_mc_del(dev, dn_rt_all_rt_mcast); } static void dn_dev_set_timer(struct net_device *dev); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 63bf298ca10..51824c42b77 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -997,7 +997,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr) --ANK */ if (arp_mc_map(addr, buf, dev, 0) == 0) - dev_mc_add(dev, buf, dev->addr_len, 0); + dev_mc_add(dev, buf); } /* @@ -1010,7 +1010,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr) struct net_device *dev = in_dev->dev; if (arp_mc_map(addr, buf, dev, 0) == 0) - dev_mc_delete(dev, buf, dev->addr_len, 0); + dev_mc_del(dev, buf); } #ifdef CONFIG_IP_MULTICAST diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 0886f96c736..a2208b7b313 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -87,7 +87,7 @@ clusterip_config_entry_put(struct clusterip_config *c) list_del(&c->list); write_unlock_bh(&clusterip_lock); - dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); + dev_mc_del(c->dev, c->clustermac); dev_put(c->dev); /* In case anyone still accesses the file, the open/close @@ -396,7 +396,7 @@ static bool clusterip_tg_check(const struct xt_tgchk_param *par) dev_put(dev); return false; } - dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); + dev_mc_add(config->dev, config->clustermac); } } cipinfo->config = config; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index bcd97191596..37d1868c006 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -714,7 +714,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc) if (!(mc->mca_flags&MAF_LOADED)) { mc->mca_flags |= MAF_LOADED; if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) - dev_mc_add(dev, buf, dev->addr_len, 0); + dev_mc_add(dev, buf); } spin_unlock_bh(&mc->mca_lock); @@ -740,7 +740,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc) if (mc->mca_flags&MAF_LOADED) { mc->mca_flags &= ~MAF_LOADED; if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) - dev_mc_delete(dev, buf, dev->addr_len, 0); + dev_mc_del(dev, buf); } if (mc->mca_flags & MAF_NOREPORT) diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index c3d844093a2..9179196da26 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -84,16 +84,14 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, } static inline u64 drv_prepare_multicast(struct ieee80211_local *local, - int mc_count, - struct dev_addr_list *mc_list) + struct netdev_hw_addr_list *mc_list) { u64 ret = 0; if (local->ops->prepare_multicast) - ret = local->ops->prepare_multicast(&local->hw, mc_count, - mc_list); + ret = local->ops->prepare_multicast(&local->hw, mc_list); - trace_drv_prepare_multicast(local, mc_count, ret); + trace_drv_prepare_multicast(local, mc_list->count, ret); return ret; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ab369e2a528..7fdacf9408b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -646,8 +646,7 @@ struct ieee80211_local { struct work_struct recalc_smps; /* aggregated multicast list */ - struct dev_addr_list *mc_list; - int mc_count; + struct netdev_hw_addr_list mc_list; bool tim_in_locked_section; /* see ieee80211_beacon_get() */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b4ec59a8dc0..00f3a93c6b0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -412,8 +412,7 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_lock_bh(dev); spin_lock_bh(&local->filter_lock); - __dev_addr_unsync(&local->mc_list, &local->mc_count, - &dev->mc_list, &dev->mc_count); + __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len); spin_unlock_bh(&local->filter_lock); netif_addr_unlock_bh(dev); @@ -596,8 +595,7 @@ static void ieee80211_set_multicast_list(struct net_device *dev) sdata->flags ^= IEEE80211_SDATA_PROMISC; } spin_lock_bh(&local->filter_lock); - __dev_addr_sync(&local->mc_list, &local->mc_count, - &dev->mc_list, &dev->mc_count); + __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); spin_unlock_bh(&local->filter_lock); ieee80211_queue_work(&local->hw, &local->reconfig_filter); } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e..84ad249a4e2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -71,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) spin_lock_bh(&local->filter_lock); changed_flags = local->filter_flags ^ new_flags; - mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); + mc = drv_prepare_multicast(local, &local->mc_list); spin_unlock_bh(&local->filter_lock); /* be a bit nasty */ diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 48c1e0ae565..b0f037cc899 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1691,9 +1691,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, if (i->alen != dev->addr_len) return -EINVAL; if (what > 0) - return dev_mc_add(dev, i->addr, i->alen, 0); + return dev_mc_add(dev, i->addr); else - return dev_mc_delete(dev, i->addr, i->alen, 0); + return dev_mc_del(dev, i->addr); break; case PACKET_MR_PROMISC: return dev_set_promiscuity(dev, what); -- cgit v1.2.3 From 18e225f257663c59ff9d4482f07ffd06361fc2ec Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 7 Apr 2010 16:40:09 -0700 Subject: net: fix definition of netdev_for_each_mc_addr() The first argument should be called ha, not mclist. All callers use the name "ha", but if they used a different name, there would be a compile error. Signed-off-by: Pavel Roskin Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a343a21ba8b..d1a21b576a4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -260,7 +260,7 @@ struct netdev_hw_addr_list { #define netdev_mc_count(dev) netdev_hw_addr_list_count(&(dev)->mc) #define netdev_mc_empty(dev) netdev_hw_addr_list_empty(&(dev)->mc) -#define netdev_for_each_mc_addr(mclist, dev) \ +#define netdev_for_each_mc_addr(ha, dev) \ netdev_hw_addr_list_for_each(ha, &(dev)->mc) struct hh_cache { -- cgit v1.2.3 From acbbc07145b919248c410e1852b953d385be5c97 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 11 Apr 2010 06:56:11 +0000 Subject: net: uninline skb_bond_should_drop() skb_bond_should_drop() is too big to be inlined. This patch reduces kernel text size, and its compilation time as well (shrinking include/linux/netdevice.h) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 48 ++++------------------------------------------ net/core/dev.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 44 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d1a21b576a4..470f7c951af 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2089,54 +2089,14 @@ static inline void netif_set_gso_max_size(struct net_device *dev, dev->gso_max_size = size; } -static inline void skb_bond_set_mac_by_master(struct sk_buff *skb, - struct net_device *master) -{ - if (skb->pkt_type == PACKET_HOST) { - u16 *dest = (u16 *) eth_hdr(skb)->h_dest; - - memcpy(dest, master->dev_addr, ETH_ALEN); - } -} +extern int __skb_bond_should_drop(struct sk_buff *skb, + struct net_device *master); -/* On bonding slaves other than the currently active slave, suppress - * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and - * ARP on active-backup slaves with arp_validate enabled. - */ static inline int skb_bond_should_drop(struct sk_buff *skb, struct net_device *master) { - if (master) { - struct net_device *dev = skb->dev; - - if (master->priv_flags & IFF_MASTER_ARPMON) - dev->last_rx = jiffies; - - if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) { - /* Do address unmangle. The local destination address - * will be always the one master has. Provides the right - * functionality in a bridge. - */ - skb_bond_set_mac_by_master(skb, master); - } - - if (dev->priv_flags & IFF_SLAVE_INACTIVE) { - if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && - skb->protocol == __cpu_to_be16(ETH_P_ARP)) - return 0; - - if (master->priv_flags & IFF_MASTER_ALB) { - if (skb->pkt_type != PACKET_BROADCAST && - skb->pkt_type != PACKET_MULTICAST) - return 0; - } - if (master->priv_flags & IFF_MASTER_8023AD && - skb->protocol == __cpu_to_be16(ETH_P_SLOW)) - return 0; - - return 1; - } - } + if (master) + return __skb_bond_should_drop(skb, master); return 0; } diff --git a/net/core/dev.c b/net/core/dev.c index ca4cdef74a1..876b1112d5b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2646,6 +2646,55 @@ void netif_nit_deliver(struct sk_buff *skb) rcu_read_unlock(); } +static inline void skb_bond_set_mac_by_master(struct sk_buff *skb, + struct net_device *master) +{ + if (skb->pkt_type == PACKET_HOST) { + u16 *dest = (u16 *) eth_hdr(skb)->h_dest; + + memcpy(dest, master->dev_addr, ETH_ALEN); + } +} + +/* On bonding slaves other than the currently active slave, suppress + * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and + * ARP on active-backup slaves with arp_validate enabled. + */ +int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master) +{ + struct net_device *dev = skb->dev; + + if (master->priv_flags & IFF_MASTER_ARPMON) + dev->last_rx = jiffies; + + if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) { + /* Do address unmangle. The local destination address + * will be always the one master has. Provides the right + * functionality in a bridge. + */ + skb_bond_set_mac_by_master(skb, master); + } + + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { + if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && + skb->protocol == __cpu_to_be16(ETH_P_ARP)) + return 0; + + if (master->priv_flags & IFF_MASTER_ALB) { + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + return 0; + } + if (master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __cpu_to_be16(ETH_P_SLOW)) + return 0; + + return 1; + } + return 0; +} +EXPORT_SYMBOL(__skb_bond_should_drop); + static int __netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; -- cgit v1.2.3 From fd793d8905720595caede6bd26c5df6c0ecd37f8 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Thu, 15 Apr 2010 00:16:59 -0700 Subject: net: CONFIG_SMP should be CONFIG_RPS Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 470f7c951af..55c2086e1f0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1331,7 +1331,7 @@ struct softnet_data { struct sk_buff *completion_queue; /* Elements below can be accessed between CPUs for RPS */ -#ifdef CONFIG_SMP +#ifdef CONFIG_RPS struct call_single_data csd ____cacheline_aligned_in_smp; #endif struct sk_buff_head input_pkt_queue; -- cgit v1.2.3 From fec5e652e58fa6017b2c9e06466cb2a6538de5b4 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Fri, 16 Apr 2010 16:01:27 -0700 Subject: rfs: Receive Flow Steering This patch implements receive flow steering (RFS). RFS steers received packets for layer 3 and 4 processing to the CPU where the application for the corresponding flow is running. RFS is an extension of Receive Packet Steering (RPS). The basic idea of RFS is that when an application calls recvmsg (or sendmsg) the application's running CPU is stored in a hash table that is indexed by the connection's rxhash which is stored in the socket structure. The rxhash is passed in skb's received on the connection from netif_receive_skb. For each received packet, the associated rxhash is used to look up the CPU in the hash table, if a valid CPU is set then the packet is steered to that CPU using the RPS mechanisms. The convolution of the simple approach is that it would potentially allow OOO packets. If threads are thrashing around CPUs or multiple threads are trying to read from the same sockets, a quickly changing CPU value in the hash table could cause rampant OOO packets-- we consider this a non-starter. To avoid OOO packets, this solution implements two types of hash tables: rps_sock_flow_table and rps_dev_flow_table. rps_sock_table is a global hash table. Each entry is just a CPU number and it is populated in recvmsg and sendmsg as described above. This table contains the "desired" CPUs for flows. rps_dev_flow_table is specific to each device queue. Each entry contains a CPU and a tail queue counter. The CPU is the "current" CPU for a matching flow. The tail queue counter holds the value of a tail queue counter for the associated CPU's backlog queue at the time of last enqueue for a flow matching the entry. Each backlog queue has a queue head counter which is incremented on dequeue, and so a queue tail counter is computed as queue head count + queue length. When a packet is enqueued on a backlog queue, the current value of the queue tail counter is saved in the hash entry of the rps_dev_flow_table. And now the trick: when selecting the CPU for RPS (get_rps_cpu) the rps_sock_flow table and the rps_dev_flow table for the RX queue are consulted. When the desired CPU for the flow (found in the rps_sock_flow table) does not match the current CPU (found in the rps_dev_flow table), the current CPU is changed to the desired CPU if one of the following is true: - The current CPU is unset (equal to RPS_NO_CPU) - Current CPU is offline - The current CPU's queue head counter >= queue tail counter in the rps_dev_flow table. This checks if the queue tail has advanced beyond the last packet that was enqueued using this table entry. This guarantees that all packets queued using this entry have been dequeued, thus preserving in order delivery. Making each queue have its own rps_dev_flow table has two advantages: 1) the tail queue counters will be written on each receive, so keeping the table local to interrupting CPU s good for locality. 2) this allows lockless access to the table-- the CPU number and queue tail counter need to be accessed together under mutual exclusion from netif_receive_skb, we assume that this is only called from device napi_poll which is non-reentrant. This patch implements RFS for TCP and connected UDP sockets. It should be usable for other flow oriented protocols. There are two configuration parameters for RFS. The "rps_flow_entries" kernel init parameter sets the number of entries in the rps_sock_flow_table, the per rxqueue sysfs entry "rps_flow_cnt" contains the number of entries in the rps_dev_flow table for the rxqueue. Both are rounded to power of two. The obvious benefit of RFS (over just RPS) is that it achieves CPU locality between the receive processing for a flow and the applications processing; this can result in increased performance (higher pps, lower latency). The benefits of RFS are dependent on cache hierarchy, application load, and other factors. On simple benchmarks, we don't necessarily see improvement and sometimes see degradation. However, for more complex benchmarks and for applications where cache pressure is much higher this technique seems to perform very well. Below are some benchmark results which show the potential benfit of this patch. The netperf test has 500 instances of netperf TCP_RR test with 1 byte req. and resp. The RPC test is an request/response test similar in structure to netperf RR test ith 100 threads on each host, but does more work in userspace that netperf. e1000e on 8 core Intel No RFS or RPS 104K tps at 30% CPU No RFS (best RPS config): 290K tps at 63% CPU RFS 303K tps at 61% CPU RPC test tps CPU% 50/90/99% usec latency Latency StdDev No RFS/RPS 103K 48% 757/900/3185 4472.35 RPS only: 174K 73% 415/993/2468 491.66 RFS 223K 73% 379/651/1382 315.61 Signed-off-by: Tom Herbert Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 69 +++++++++++++++++++++++++++- include/net/inet_sock.h | 38 ++++++++++++++++ net/core/dev.c | 111 +++++++++++++++++++++++++++++++++++++-------- net/core/net-sysfs.c | 94 ++++++++++++++++++++++++++++++++++++-- net/core/sysctl_net_core.c | 68 +++++++++++++++++++++++++++ net/ipv4/af_inet.c | 29 ++++++++++-- net/ipv4/tcp_ipv4.c | 2 + net/ipv4/udp.c | 7 ++- 8 files changed, 389 insertions(+), 29 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 55c2086e1f0..649a0252686 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -530,14 +530,73 @@ struct rps_map { }; #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16))) +/* + * The rps_dev_flow structure contains the mapping of a flow to a CPU and the + * tail pointer for that CPU's input queue at the time of last enqueue. + */ +struct rps_dev_flow { + u16 cpu; + u16 fill; + unsigned int last_qtail; +}; + +/* + * The rps_dev_flow_table structure contains a table of flow mappings. + */ +struct rps_dev_flow_table { + unsigned int mask; + struct rcu_head rcu; + struct work_struct free_work; + struct rps_dev_flow flows[0]; +}; +#define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \ + (_num * sizeof(struct rps_dev_flow))) + +/* + * The rps_sock_flow_table contains mappings of flows to the last CPU + * on which they were processed by the application (set in recvmsg). + */ +struct rps_sock_flow_table { + unsigned int mask; + u16 ents[0]; +}; +#define RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \ + (_num * sizeof(u16))) + +#define RPS_NO_CPU 0xffff + +static inline void rps_record_sock_flow(struct rps_sock_flow_table *table, + u32 hash) +{ + if (table && hash) { + unsigned int cpu, index = hash & table->mask; + + /* We only give a hint, preemption can change cpu under us */ + cpu = raw_smp_processor_id(); + + if (table->ents[index] != cpu) + table->ents[index] = cpu; + } +} + +static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table, + u32 hash) +{ + if (table && hash) + table->ents[hash & table->mask] = RPS_NO_CPU; +} + +extern struct rps_sock_flow_table *rps_sock_flow_table; + /* This structure contains an instance of an RX queue. */ struct netdev_rx_queue { struct rps_map *rps_map; + struct rps_dev_flow_table *rps_flow_table; struct kobject kobj; struct netdev_rx_queue *first; atomic_t count; } ____cacheline_aligned_in_smp; -#endif +#endif /* CONFIG_RPS */ /* * This structure defines the management hooks for network devices. @@ -1333,11 +1392,19 @@ struct softnet_data { /* Elements below can be accessed between CPUs for RPS */ #ifdef CONFIG_RPS struct call_single_data csd ____cacheline_aligned_in_smp; + unsigned int input_queue_head; #endif struct sk_buff_head input_pkt_queue; struct napi_struct backlog; }; +static inline void incr_input_queue_head(struct softnet_data *queue) +{ +#ifdef CONFIG_RPS + queue->input_queue_head++; +#endif +} + DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); #define HAVE_NETIF_QUEUE diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 83fd34437cf..b487bc1b99a 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ struct rtable; * @uc_ttl - Unicast TTL * @inet_sport - Source port * @inet_id - ID counter for DF pkts + * @rxhash - flow hash received from netif layer * @tos - TOS * @mc_ttl - Multicasting TTL * @is_icsk - is this an inet_connection_sock? @@ -124,6 +126,9 @@ struct inet_sock { __u16 cmsg_flags; __be16 inet_sport; __u16 inet_id; +#ifdef CONFIG_RPS + __u32 rxhash; +#endif struct ip_options *opt; __u8 tos; @@ -219,4 +224,37 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0; } +static inline void inet_rps_record_flow(const struct sock *sk) +{ +#ifdef CONFIG_RPS + struct rps_sock_flow_table *sock_flow_table; + + rcu_read_lock(); + sock_flow_table = rcu_dereference(rps_sock_flow_table); + rps_record_sock_flow(sock_flow_table, inet_sk(sk)->rxhash); + rcu_read_unlock(); +#endif +} + +static inline void inet_rps_reset_flow(const struct sock *sk) +{ +#ifdef CONFIG_RPS + struct rps_sock_flow_table *sock_flow_table; + + rcu_read_lock(); + sock_flow_table = rcu_dereference(rps_sock_flow_table); + rps_reset_sock_flow(sock_flow_table, inet_sk(sk)->rxhash); + rcu_read_unlock(); +#endif +} + +static inline void inet_rps_save_rxhash(const struct sock *sk, u32 rxhash) +{ +#ifdef CONFIG_RPS + if (unlikely(inet_sk(sk)->rxhash != rxhash)) { + inet_rps_reset_flow(sk); + inet_sk(sk)->rxhash = rxhash; + } +#endif +} #endif /* _INET_SOCK_H */ diff --git a/net/core/dev.c b/net/core/dev.c index e8041eb76ac..d7107ac835f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2203,19 +2203,28 @@ int weight_p __read_mostly = 64; /* old backlog weight */ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; #ifdef CONFIG_RPS + +/* One global table that all flow-based protocols share. */ +struct rps_sock_flow_table *rps_sock_flow_table; +EXPORT_SYMBOL(rps_sock_flow_table); + /* * get_rps_cpu is called from netif_receive_skb and returns the target * CPU from the RPS map of the receiving queue for a given skb. * rcu_read_lock must be held on entry. */ -static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb) +static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, + struct rps_dev_flow **rflowp) { struct ipv6hdr *ip6; struct iphdr *ip; struct netdev_rx_queue *rxqueue; struct rps_map *map; + struct rps_dev_flow_table *flow_table; + struct rps_sock_flow_table *sock_flow_table; int cpu = -1; u8 ip_proto; + u16 tcpu; u32 addr1, addr2, ports, ihl; if (skb_rx_queue_recorded(skb)) { @@ -2232,7 +2241,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb) } else rxqueue = dev->_rx; - if (!rxqueue->rps_map) + if (!rxqueue->rps_map && !rxqueue->rps_flow_table) goto done; if (skb->rxhash) @@ -2284,9 +2293,48 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb) skb->rxhash = 1; got_hash: + flow_table = rcu_dereference(rxqueue->rps_flow_table); + sock_flow_table = rcu_dereference(rps_sock_flow_table); + if (flow_table && sock_flow_table) { + u16 next_cpu; + struct rps_dev_flow *rflow; + + rflow = &flow_table->flows[skb->rxhash & flow_table->mask]; + tcpu = rflow->cpu; + + next_cpu = sock_flow_table->ents[skb->rxhash & + sock_flow_table->mask]; + + /* + * If the desired CPU (where last recvmsg was done) is + * different from current CPU (one in the rx-queue flow + * table entry), switch if one of the following holds: + * - Current CPU is unset (equal to RPS_NO_CPU). + * - Current CPU is offline. + * - The current CPU's queue tail has advanced beyond the + * last packet that was enqueued using this table entry. + * This guarantees that all previous packets for the flow + * have been dequeued, thus preserving in order delivery. + */ + if (unlikely(tcpu != next_cpu) && + (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || + ((int)(per_cpu(softnet_data, tcpu).input_queue_head - + rflow->last_qtail)) >= 0)) { + tcpu = rflow->cpu = next_cpu; + if (tcpu != RPS_NO_CPU) + rflow->last_qtail = per_cpu(softnet_data, + tcpu).input_queue_head; + } + if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { + *rflowp = rflow; + cpu = tcpu; + goto done; + } + } + map = rcu_dereference(rxqueue->rps_map); if (map) { - u16 tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32]; + tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32]; if (cpu_online(tcpu)) { cpu = tcpu; @@ -2320,13 +2368,14 @@ static void trigger_softirq(void *data) __napi_schedule(&queue->backlog); __get_cpu_var(netdev_rx_stat).received_rps++; } -#endif /* CONFIG_SMP */ +#endif /* CONFIG_RPS */ /* * enqueue_to_backlog is called to queue an skb to a per CPU backlog * queue (may be a remote CPU queue). */ -static int enqueue_to_backlog(struct sk_buff *skb, int cpu) +static int enqueue_to_backlog(struct sk_buff *skb, int cpu, + unsigned int *qtail) { struct softnet_data *queue; unsigned long flags; @@ -2341,6 +2390,10 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu) if (queue->input_pkt_queue.qlen) { enqueue: __skb_queue_tail(&queue->input_pkt_queue, skb); +#ifdef CONFIG_RPS + *qtail = queue->input_queue_head + + queue->input_pkt_queue.qlen; +#endif rps_unlock(queue); local_irq_restore(flags); return NET_RX_SUCCESS; @@ -2355,11 +2408,10 @@ enqueue: cpu_set(cpu, rcpus->mask[rcpus->select]); __raise_softirq_irqoff(NET_RX_SOFTIRQ); - } else - __napi_schedule(&queue->backlog); -#else - __napi_schedule(&queue->backlog); + goto enqueue; + } #endif + __napi_schedule(&queue->backlog); } goto enqueue; } @@ -2401,18 +2453,25 @@ int netif_rx(struct sk_buff *skb) #ifdef CONFIG_RPS { + struct rps_dev_flow voidflow, *rflow = &voidflow; int cpu; rcu_read_lock(); - cpu = get_rps_cpu(skb->dev, skb); + + cpu = get_rps_cpu(skb->dev, skb, &rflow); if (cpu < 0) cpu = smp_processor_id(); - ret = enqueue_to_backlog(skb, cpu); + + ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); + rcu_read_unlock(); } #else - ret = enqueue_to_backlog(skb, get_cpu()); - put_cpu(); + { + unsigned int qtail; + ret = enqueue_to_backlog(skb, get_cpu(), &qtail); + put_cpu(); + } #endif return ret; } @@ -2830,14 +2889,22 @@ out: int netif_receive_skb(struct sk_buff *skb) { #ifdef CONFIG_RPS - int cpu; + struct rps_dev_flow voidflow, *rflow = &voidflow; + int cpu, ret; + + rcu_read_lock(); - cpu = get_rps_cpu(skb->dev, skb); + cpu = get_rps_cpu(skb->dev, skb, &rflow); - if (cpu < 0) - return __netif_receive_skb(skb); - else - return enqueue_to_backlog(skb, cpu); + if (cpu >= 0) { + ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); + rcu_read_unlock(); + } else { + rcu_read_unlock(); + ret = __netif_receive_skb(skb); + } + + return ret; #else return __netif_receive_skb(skb); #endif @@ -2856,6 +2923,7 @@ static void flush_backlog(void *arg) if (skb->dev == dev) { __skb_unlink(skb, &queue->input_pkt_queue); kfree_skb(skb); + incr_input_queue_head(queue); } rps_unlock(queue); } @@ -3179,6 +3247,7 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_enable(); break; } + incr_input_queue_head(queue); rps_unlock(queue); local_irq_enable(); @@ -5542,8 +5611,10 @@ static int dev_cpu_callback(struct notifier_block *nfb, local_irq_enable(); /* Process offline CPU's input_pkt_queue */ - while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) + while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { netif_rx(skb); + incr_input_queue_head(oldsd); + } return NOTIFY_OK; } diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 96ed6905b82..143052a22b9 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "net-sysfs.h" @@ -601,22 +602,109 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue, return len; } +static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, + struct rx_queue_attribute *attr, + char *buf) +{ + struct rps_dev_flow_table *flow_table; + unsigned int val = 0; + + rcu_read_lock(); + flow_table = rcu_dereference(queue->rps_flow_table); + if (flow_table) + val = flow_table->mask + 1; + rcu_read_unlock(); + + return sprintf(buf, "%u\n", val); +} + +static void rps_dev_flow_table_release_work(struct work_struct *work) +{ + struct rps_dev_flow_table *table = container_of(work, + struct rps_dev_flow_table, free_work); + + vfree(table); +} + +static void rps_dev_flow_table_release(struct rcu_head *rcu) +{ + struct rps_dev_flow_table *table = container_of(rcu, + struct rps_dev_flow_table, rcu); + + INIT_WORK(&table->free_work, rps_dev_flow_table_release_work); + schedule_work(&table->free_work); +} + +ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, + struct rx_queue_attribute *attr, + const char *buf, size_t len) +{ + unsigned int count; + char *endp; + struct rps_dev_flow_table *table, *old_table; + static DEFINE_SPINLOCK(rps_dev_flow_lock); + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + count = simple_strtoul(buf, &endp, 0); + if (endp == buf) + return -EINVAL; + + if (count) { + int i; + + if (count > 1<<30) { + /* Enforce a limit to prevent overflow */ + return -EINVAL; + } + count = roundup_pow_of_two(count); + table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(count)); + if (!table) + return -ENOMEM; + + table->mask = count - 1; + for (i = 0; i < count; i++) + table->flows[i].cpu = RPS_NO_CPU; + } else + table = NULL; + + spin_lock(&rps_dev_flow_lock); + old_table = queue->rps_flow_table; + rcu_assign_pointer(queue->rps_flow_table, table); + spin_unlock(&rps_dev_flow_lock); + + if (old_table) + call_rcu(&old_table->rcu, rps_dev_flow_table_release); + + return len; +} + static struct rx_queue_attribute rps_cpus_attribute = __ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map); + +static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute = + __ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR, + show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt); + static struct attribute *rx_queue_default_attrs[] = { &rps_cpus_attribute.attr, + &rps_dev_flow_table_cnt_attribute.attr, NULL }; static void rx_queue_release(struct kobject *kobj) { struct netdev_rx_queue *queue = to_rx_queue(kobj); - struct rps_map *map = queue->rps_map; struct netdev_rx_queue *first = queue->first; - if (map) - call_rcu(&map->rcu, rps_map_release); + if (queue->rps_map) + call_rcu(&queue->rps_map->rcu, rps_map_release); + + if (queue->rps_flow_table) + call_rcu(&queue->rps_flow_table->rcu, + rps_dev_flow_table_release); if (atomic_dec_and_test(&first->count)) kfree(first); diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index b7b6b8208f7..dcc7d25996a 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -11,12 +11,72 @@ #include #include #include +#include #include #include #include #include +#ifdef CONFIG_RPS +static int rps_sock_flow_sysctl(ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + unsigned int orig_size, size; + int ret, i; + ctl_table tmp = { + .data = &size, + .maxlen = sizeof(size), + .mode = table->mode + }; + struct rps_sock_flow_table *orig_sock_table, *sock_table; + static DEFINE_MUTEX(sock_flow_mutex); + + mutex_lock(&sock_flow_mutex); + + orig_sock_table = rps_sock_flow_table; + size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0; + + ret = proc_dointvec(&tmp, write, buffer, lenp, ppos); + + if (write) { + if (size) { + if (size > 1<<30) { + /* Enforce limit to prevent overflow */ + mutex_unlock(&sock_flow_mutex); + return -EINVAL; + } + size = roundup_pow_of_two(size); + if (size != orig_size) { + sock_table = + vmalloc(RPS_SOCK_FLOW_TABLE_SIZE(size)); + if (!sock_table) { + mutex_unlock(&sock_flow_mutex); + return -ENOMEM; + } + + sock_table->mask = size - 1; + } else + sock_table = orig_sock_table; + + for (i = 0; i < size; i++) + sock_table->ents[i] = RPS_NO_CPU; + } else + sock_table = NULL; + + if (sock_table != orig_sock_table) { + rcu_assign_pointer(rps_sock_flow_table, sock_table); + synchronize_rcu(); + vfree(orig_sock_table); + } + } + + mutex_unlock(&sock_flow_mutex); + + return ret; +} +#endif /* CONFIG_RPS */ + static struct ctl_table net_core_table[] = { #ifdef CONFIG_NET { @@ -82,6 +142,14 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, +#ifdef CONFIG_RPS + { + .procname = "rps_sock_flow_entries", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = rps_sock_flow_sysctl + }, +#endif #endif /* CONFIG_NET */ { .procname = "netdev_budget", diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 193dcd6ed64..c5376c72550 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -419,6 +419,8 @@ int inet_release(struct socket *sock) if (sk) { long timeout; + inet_rps_reset_flow(sk); + /* Applications forget to leave groups before exiting */ ip_mc_drop_socket(sk); @@ -720,6 +722,8 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, { struct sock *sk = sock->sk; + inet_rps_record_flow(sk); + /* We may need to bind the socket. */ if (!inet_sk(sk)->inet_num && inet_autobind(sk)) return -EAGAIN; @@ -728,12 +732,13 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, } EXPORT_SYMBOL(inet_sendmsg); - static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { struct sock *sk = sock->sk; + inet_rps_record_flow(sk); + /* We may need to bind the socket. */ if (!inet_sk(sk)->inet_num && inet_autobind(sk)) return -EAGAIN; @@ -743,6 +748,22 @@ static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, return sock_no_sendpage(sock, page, offset, size, flags); } +int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + size_t size, int flags) +{ + struct sock *sk = sock->sk; + int addr_len = 0; + int err; + + inet_rps_record_flow(sk); + + err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, + flags & ~MSG_DONTWAIT, &addr_len); + if (err >= 0) + msg->msg_namelen = addr_len; + return err; +} +EXPORT_SYMBOL(inet_recvmsg); int inet_shutdown(struct socket *sock, int how) { @@ -872,7 +893,7 @@ const struct proto_ops inet_stream_ops = { .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = tcp_sendmsg, - .recvmsg = sock_common_recvmsg, + .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = tcp_sendpage, .splice_read = tcp_splice_read, @@ -899,7 +920,7 @@ const struct proto_ops inet_dgram_ops = { .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, - .recvmsg = sock_common_recvmsg, + .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, #ifdef CONFIG_COMPAT @@ -929,7 +950,7 @@ static const struct proto_ops inet_sockraw_ops = { .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, - .recvmsg = sock_common_recvmsg, + .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, #ifdef CONFIG_COMPAT diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a24995cdc4b..ad08392a738 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1672,6 +1672,8 @@ process: skb->dev = NULL; + inet_rps_save_rxhash(sk, skb->rxhash); + bh_lock_sock_nested(sk); ret = 0; if (!sock_owned_by_user(sk)) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8fef859db35..666b963496f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1217,6 +1217,7 @@ int udp_disconnect(struct sock *sk, int flags) sk->sk_state = TCP_CLOSE; inet->inet_daddr = 0; inet->inet_dport = 0; + inet_rps_save_rxhash(sk, 0); sk->sk_bound_dev_if = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); @@ -1258,8 +1259,12 @@ EXPORT_SYMBOL(udp_lib_unhash); static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { - int rc = sock_queue_rcv_skb(sk, skb); + int rc; + + if (inet_sk(sk)->inet_daddr) + inet_rps_save_rxhash(sk, skb->rxhash); + rc = sock_queue_rcv_skb(sk, skb); if (rc < 0) { int is_udplite = IS_UDPLITE(sk); -- cgit v1.2.3 From 88751275b8e867d756e4f86ae92afe0232de129f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 Apr 2010 05:07:33 +0000 Subject: rps: shortcut net_rps_action() net_rps_action() is a bit expensive on NR_CPUS=64..4096 kernels, even if RPS is not active. Tom Herbert used two bitmasks to hold information needed to send IPI, but a single LIFO list seems more appropriate. Move all RPS logic into net_rps_action() to cleanup net_rx_action() code (remove two ifdefs) Move rps_remote_softirq_cpus into softnet_data to share its first cache line, filling an existing hole. In a future patch, we could call net_rps_action() from process_backlog() to make sure we send IPI before handling this cpu backlog. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 9 ++++-- net/core/dev.c | 79 +++++++++++++++++++---------------------------- 2 files changed, 38 insertions(+), 50 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 649a0252686..83ab3da149a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1381,17 +1381,20 @@ static inline int unregister_gifconf(unsigned int family) } /* - * Incoming packets are placed on per-cpu queues so that - * no locking is needed. + * Incoming packets are placed on per-cpu queues */ struct softnet_data { struct Qdisc *output_queue; struct list_head poll_list; struct sk_buff *completion_queue; - /* Elements below can be accessed between CPUs for RPS */ #ifdef CONFIG_RPS + struct softnet_data *rps_ipi_list; + + /* Elements below can be accessed between CPUs for RPS */ struct call_single_data csd ____cacheline_aligned_in_smp; + struct softnet_data *rps_ipi_next; + unsigned int cpu; unsigned int input_queue_head; #endif struct sk_buff_head input_pkt_queue; diff --git a/net/core/dev.c b/net/core/dev.c index 8eb50e2292f..05a2b294906 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2345,21 +2345,6 @@ done: return cpu; } -/* - * This structure holds the per-CPU mask of CPUs for which IPIs are scheduled - * to be sent to kick remote softirq processing. There are two masks since - * the sending of IPIs must be done with interrupts enabled. The select field - * indicates the current mask that enqueue_backlog uses to schedule IPIs. - * select is flipped before net_rps_action is called while still under lock, - * net_rps_action then uses the non-selected mask to send the IPIs and clears - * it without conflicting with enqueue_backlog operation. - */ -struct rps_remote_softirq_cpus { - cpumask_t mask[2]; - int select; -}; -static DEFINE_PER_CPU(struct rps_remote_softirq_cpus, rps_remote_softirq_cpus); - /* Called from hardirq (IPI) context */ static void trigger_softirq(void *data) { @@ -2402,10 +2387,12 @@ enqueue: if (napi_schedule_prep(&queue->backlog)) { #ifdef CONFIG_RPS if (cpu != smp_processor_id()) { - struct rps_remote_softirq_cpus *rcpus = - &__get_cpu_var(rps_remote_softirq_cpus); + struct softnet_data *myqueue; + + myqueue = &__get_cpu_var(softnet_data); + queue->rps_ipi_next = myqueue->rps_ipi_list; + myqueue->rps_ipi_list = queue; - cpu_set(cpu, rcpus->mask[rcpus->select]); __raise_softirq_irqoff(NET_RX_SOFTIRQ); goto enqueue; } @@ -2910,7 +2897,9 @@ int netif_receive_skb(struct sk_buff *skb) } EXPORT_SYMBOL(netif_receive_skb); -/* Network device is going away, flush any packets still pending */ +/* Network device is going away, flush any packets still pending + * Called with irqs disabled. + */ static void flush_backlog(void *arg) { struct net_device *dev = arg; @@ -3338,24 +3327,33 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); -#ifdef CONFIG_RPS /* - * net_rps_action sends any pending IPI's for rps. This is only called from - * softirq and interrupts must be enabled. + * net_rps_action sends any pending IPI's for rps. + * Note: called with local irq disabled, but exits with local irq enabled. */ -static void net_rps_action(cpumask_t *mask) +static void net_rps_action(void) { - int cpu; +#ifdef CONFIG_RPS + struct softnet_data *locqueue = &__get_cpu_var(softnet_data); + struct softnet_data *remqueue = locqueue->rps_ipi_list; - /* Send pending IPI's to kick RPS processing on remote cpus. */ - for_each_cpu_mask_nr(cpu, *mask) { - struct softnet_data *queue = &per_cpu(softnet_data, cpu); - if (cpu_online(cpu)) - __smp_call_function_single(cpu, &queue->csd, 0); - } - cpus_clear(*mask); -} + if (remqueue) { + locqueue->rps_ipi_list = NULL; + + local_irq_enable(); + + /* Send pending IPI's to kick RPS processing on remote cpus. */ + while (remqueue) { + struct softnet_data *next = remqueue->rps_ipi_next; + if (cpu_online(remqueue->cpu)) + __smp_call_function_single(remqueue->cpu, + &remqueue->csd, 0); + remqueue = next; + } + } else #endif + local_irq_enable(); +} static void net_rx_action(struct softirq_action *h) { @@ -3363,10 +3361,6 @@ static void net_rx_action(struct softirq_action *h) unsigned long time_limit = jiffies + 2; int budget = netdev_budget; void *have; -#ifdef CONFIG_RPS - int select; - struct rps_remote_softirq_cpus *rcpus; -#endif local_irq_disable(); @@ -3429,17 +3423,7 @@ static void net_rx_action(struct softirq_action *h) netpoll_poll_unlock(have); } out: -#ifdef CONFIG_RPS - rcpus = &__get_cpu_var(rps_remote_softirq_cpus); - select = rcpus->select; - rcpus->select ^= 1; - - local_irq_enable(); - - net_rps_action(&rcpus->mask[select]); -#else - local_irq_enable(); -#endif + net_rps_action(); #ifdef CONFIG_NET_DMA /* @@ -5839,6 +5823,7 @@ static int __init net_dev_init(void) queue->csd.func = trigger_softirq; queue->csd.info = queue; queue->csd.flags = 0; + queue->cpu = i; #endif queue->backlog.poll = process_backlog; -- cgit v1.2.3 From e36fa2f7e92f25aab2e3d787dcfe3590817f19d3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 Apr 2010 21:17:14 +0000 Subject: rps: cleanups struct softnet_data holds many queues, so consistent use "sd" name instead of "queue" is better. Adds a rps_ipi_queued() helper to cleanup enqueue_to_backlog() Adds a _and_irq_disable suffix to net_rps_action() name, as David suggested. incr_input_queue_head() becomes input_queue_head_incr() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 +- net/core/dev.c | 149 +++++++++++++++++++++++++--------------------- 2 files changed, 82 insertions(+), 71 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 83ab3da149a..3c5ed5f5274 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1401,10 +1401,10 @@ struct softnet_data { struct napi_struct backlog; }; -static inline void incr_input_queue_head(struct softnet_data *queue) +static inline void input_queue_head_incr(struct softnet_data *sd) { #ifdef CONFIG_RPS - queue->input_queue_head++; + sd->input_queue_head++; #endif } diff --git a/net/core/dev.c b/net/core/dev.c index 05a2b294906..7f5755b0a57 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -208,17 +208,17 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; } -static inline void rps_lock(struct softnet_data *queue) +static inline void rps_lock(struct softnet_data *sd) { #ifdef CONFIG_RPS - spin_lock(&queue->input_pkt_queue.lock); + spin_lock(&sd->input_pkt_queue.lock); #endif } -static inline void rps_unlock(struct softnet_data *queue) +static inline void rps_unlock(struct softnet_data *sd) { #ifdef CONFIG_RPS - spin_unlock(&queue->input_pkt_queue.lock); + spin_unlock(&sd->input_pkt_queue.lock); #endif } @@ -2346,14 +2346,37 @@ done: } /* Called from hardirq (IPI) context */ -static void trigger_softirq(void *data) +static void rps_trigger_softirq(void *data) { - struct softnet_data *queue = data; - __napi_schedule(&queue->backlog); + struct softnet_data *sd = data; + + __napi_schedule(&sd->backlog); __get_cpu_var(netdev_rx_stat).received_rps++; } + #endif /* CONFIG_RPS */ +/* + * Check if this softnet_data structure is another cpu one + * If yes, queue it to our IPI list and return 1 + * If no, return 0 + */ +static int rps_ipi_queued(struct softnet_data *sd) +{ +#ifdef CONFIG_RPS + struct softnet_data *mysd = &__get_cpu_var(softnet_data); + + if (sd != mysd) { + sd->rps_ipi_next = mysd->rps_ipi_list; + mysd->rps_ipi_list = sd; + + __raise_softirq_irqoff(NET_RX_SOFTIRQ); + return 1; + } +#endif /* CONFIG_RPS */ + return 0; +} + /* * enqueue_to_backlog is called to queue an skb to a per CPU backlog * queue (may be a remote CPU queue). @@ -2361,48 +2384,36 @@ static void trigger_softirq(void *data) static int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail) { - struct softnet_data *queue; + struct softnet_data *sd; unsigned long flags; - queue = &per_cpu(softnet_data, cpu); + sd = &per_cpu(softnet_data, cpu); local_irq_save(flags); __get_cpu_var(netdev_rx_stat).total++; - rps_lock(queue); - if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { - if (queue->input_pkt_queue.qlen) { + rps_lock(sd); + if (sd->input_pkt_queue.qlen <= netdev_max_backlog) { + if (sd->input_pkt_queue.qlen) { enqueue: - __skb_queue_tail(&queue->input_pkt_queue, skb); + __skb_queue_tail(&sd->input_pkt_queue, skb); #ifdef CONFIG_RPS - *qtail = queue->input_queue_head + - queue->input_pkt_queue.qlen; + *qtail = sd->input_queue_head + sd->input_pkt_queue.qlen; #endif - rps_unlock(queue); + rps_unlock(sd); local_irq_restore(flags); return NET_RX_SUCCESS; } /* Schedule NAPI for backlog device */ - if (napi_schedule_prep(&queue->backlog)) { -#ifdef CONFIG_RPS - if (cpu != smp_processor_id()) { - struct softnet_data *myqueue; - - myqueue = &__get_cpu_var(softnet_data); - queue->rps_ipi_next = myqueue->rps_ipi_list; - myqueue->rps_ipi_list = queue; - - __raise_softirq_irqoff(NET_RX_SOFTIRQ); - goto enqueue; - } -#endif - __napi_schedule(&queue->backlog); + if (napi_schedule_prep(&sd->backlog)) { + if (!rps_ipi_queued(sd)) + __napi_schedule(&sd->backlog); } goto enqueue; } - rps_unlock(queue); + rps_unlock(sd); __get_cpu_var(netdev_rx_stat).dropped++; local_irq_restore(flags); @@ -2903,17 +2914,17 @@ EXPORT_SYMBOL(netif_receive_skb); static void flush_backlog(void *arg) { struct net_device *dev = arg; - struct softnet_data *queue = &__get_cpu_var(softnet_data); + struct softnet_data *sd = &__get_cpu_var(softnet_data); struct sk_buff *skb, *tmp; - rps_lock(queue); - skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) + rps_lock(sd); + skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) if (skb->dev == dev) { - __skb_unlink(skb, &queue->input_pkt_queue); + __skb_unlink(skb, &sd->input_pkt_queue); kfree_skb(skb); - incr_input_queue_head(queue); + input_queue_head_incr(sd); } - rps_unlock(queue); + rps_unlock(sd); } static int napi_gro_complete(struct sk_buff *skb) @@ -3219,23 +3230,23 @@ EXPORT_SYMBOL(napi_gro_frags); static int process_backlog(struct napi_struct *napi, int quota) { int work = 0; - struct softnet_data *queue = &__get_cpu_var(softnet_data); + struct softnet_data *sd = &__get_cpu_var(softnet_data); napi->weight = weight_p; do { struct sk_buff *skb; local_irq_disable(); - rps_lock(queue); - skb = __skb_dequeue(&queue->input_pkt_queue); + rps_lock(sd); + skb = __skb_dequeue(&sd->input_pkt_queue); if (!skb) { __napi_complete(napi); - rps_unlock(queue); + rps_unlock(sd); local_irq_enable(); break; } - incr_input_queue_head(queue); - rps_unlock(queue); + input_queue_head_incr(sd); + rps_unlock(sd); local_irq_enable(); __netif_receive_skb(skb); @@ -3331,24 +3342,25 @@ EXPORT_SYMBOL(netif_napi_del); * net_rps_action sends any pending IPI's for rps. * Note: called with local irq disabled, but exits with local irq enabled. */ -static void net_rps_action(void) +static void net_rps_action_and_irq_disable(void) { #ifdef CONFIG_RPS - struct softnet_data *locqueue = &__get_cpu_var(softnet_data); - struct softnet_data *remqueue = locqueue->rps_ipi_list; + struct softnet_data *sd = &__get_cpu_var(softnet_data); + struct softnet_data *remsd = sd->rps_ipi_list; - if (remqueue) { - locqueue->rps_ipi_list = NULL; + if (remsd) { + sd->rps_ipi_list = NULL; local_irq_enable(); /* Send pending IPI's to kick RPS processing on remote cpus. */ - while (remqueue) { - struct softnet_data *next = remqueue->rps_ipi_next; - if (cpu_online(remqueue->cpu)) - __smp_call_function_single(remqueue->cpu, - &remqueue->csd, 0); - remqueue = next; + while (remsd) { + struct softnet_data *next = remsd->rps_ipi_next; + + if (cpu_online(remsd->cpu)) + __smp_call_function_single(remsd->cpu, + &remsd->csd, 0); + remsd = next; } } else #endif @@ -3423,7 +3435,7 @@ static void net_rx_action(struct softirq_action *h) netpoll_poll_unlock(have); } out: - net_rps_action(); + net_rps_action_and_irq_disable(); #ifdef CONFIG_NET_DMA /* @@ -5595,7 +5607,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, /* Process offline CPU's input_pkt_queue */ while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { netif_rx(skb); - incr_input_queue_head(oldsd); + input_queue_head_incr(oldsd); } return NOTIFY_OK; @@ -5812,24 +5824,23 @@ static int __init net_dev_init(void) */ for_each_possible_cpu(i) { - struct softnet_data *queue; + struct softnet_data *sd = &per_cpu(softnet_data, i); - queue = &per_cpu(softnet_data, i); - skb_queue_head_init(&queue->input_pkt_queue); - queue->completion_queue = NULL; - INIT_LIST_HEAD(&queue->poll_list); + skb_queue_head_init(&sd->input_pkt_queue); + sd->completion_queue = NULL; + INIT_LIST_HEAD(&sd->poll_list); #ifdef CONFIG_RPS - queue->csd.func = trigger_softirq; - queue->csd.info = queue; - queue->csd.flags = 0; - queue->cpu = i; + sd->csd.func = rps_trigger_softirq; + sd->csd.info = sd; + sd->csd.flags = 0; + sd->cpu = i; #endif - queue->backlog.poll = process_backlog; - queue->backlog.weight = weight_p; - queue->backlog.gro_list = NULL; - queue->backlog.gro_count = 0; + sd->backlog.poll = process_backlog; + sd->backlog.weight = weight_p; + sd->backlog.gro_list = NULL; + sd->backlog.gro_count = 0; } dev_boot_phase = 0; -- cgit v1.2.3 From a9cbd588fdb71ea415754c885e2f9f03e6bf1ba0 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Mon, 26 Apr 2010 23:06:24 +0000 Subject: net: reimplement softnet_data.output_queue as a FIFO queue reimplement softnet_data.output_queue as a FIFO queue to keep the fairness among the qdiscs rescheduled. Signed-off-by: Changli Gao Acked-by: Eric Dumazet ---- include/linux/netdevice.h | 1 + net/core/dev.c | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + net/core/dev.c | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3c5ed5f5274..c04ca246395 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1385,6 +1385,7 @@ static inline int unregister_gifconf(unsigned int family) */ struct softnet_data { struct Qdisc *output_queue; + struct Qdisc **output_queue_tailp; struct list_head poll_list; struct sk_buff *completion_queue; diff --git a/net/core/dev.c b/net/core/dev.c index 4d43f1a80f7..3d314919a2c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1557,8 +1557,9 @@ static inline void __netif_reschedule(struct Qdisc *q) local_irq_save(flags); sd = &__get_cpu_var(softnet_data); - q->next_sched = sd->output_queue; - sd->output_queue = q; + q->next_sched = NULL; + *sd->output_queue_tailp = q; + sd->output_queue_tailp = &q->next_sched; raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_restore(flags); } @@ -2529,6 +2530,7 @@ static void net_tx_action(struct softirq_action *h) local_irq_disable(); head = sd->output_queue; sd->output_queue = NULL; + sd->output_queue_tailp = &sd->output_queue; local_irq_enable(); while (head) { @@ -5594,7 +5596,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, void *ocpu) { struct sk_buff **list_skb; - struct Qdisc **list_net; struct sk_buff *skb; unsigned int cpu, oldcpu = (unsigned long)ocpu; struct softnet_data *sd, *oldsd; @@ -5615,13 +5616,13 @@ static int dev_cpu_callback(struct notifier_block *nfb, *list_skb = oldsd->completion_queue; oldsd->completion_queue = NULL; - /* Find end of our output_queue. */ - list_net = &sd->output_queue; - while (*list_net) - list_net = &(*list_net)->next_sched; /* Append output queue from offline CPU. */ - *list_net = oldsd->output_queue; - oldsd->output_queue = NULL; + if (oldsd->output_queue) { + *sd->output_queue_tailp = oldsd->output_queue; + sd->output_queue_tailp = oldsd->output_queue_tailp; + oldsd->output_queue = NULL; + oldsd->output_queue_tailp = &oldsd->output_queue; + } raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -5851,7 +5852,8 @@ static int __init net_dev_init(void) skb_queue_head_init(&sd->input_pkt_queue); sd->completion_queue = NULL; INIT_LIST_HEAD(&sd->poll_list); - + sd->output_queue = NULL; + sd->output_queue_tailp = &sd->output_queue; #ifdef CONFIG_RPS sd->csd.func = rps_trigger_softirq; sd->csd.info = sd; -- cgit v1.2.3 From 6e7676c1a76aed6e957611d8d7a9e5592e23aeba Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 27 Apr 2010 15:07:33 -0700 Subject: net: batch skb dequeueing from softnet input_pkt_queue batch skb dequeueing from softnet input_pkt_queue to reduce potential lock contention when RPS is enabled. Note: in the worst case, the number of packets in a softnet_data may be double of netdev_max_backlog. Signed-off-by: Changli Gao Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 +++-- net/core/dev.c | 57 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 20 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c04ca246395..40d4c20d034 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1388,6 +1388,7 @@ struct softnet_data { struct Qdisc **output_queue_tailp; struct list_head poll_list; struct sk_buff *completion_queue; + struct sk_buff_head process_queue; #ifdef CONFIG_RPS struct softnet_data *rps_ipi_list; @@ -1402,10 +1403,11 @@ struct softnet_data { struct napi_struct backlog; }; -static inline void input_queue_head_incr(struct softnet_data *sd) +static inline void input_queue_head_add(struct softnet_data *sd, + unsigned int len) { #ifdef CONFIG_RPS - sd->input_queue_head++; + sd->input_queue_head += len; #endif } diff --git a/net/core/dev.c b/net/core/dev.c index 3d314919a2c..100dcbd2973 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2408,12 +2408,13 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, __get_cpu_var(netdev_rx_stat).total++; rps_lock(sd); - if (sd->input_pkt_queue.qlen <= netdev_max_backlog) { - if (sd->input_pkt_queue.qlen) { + if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) { + if (skb_queue_len(&sd->input_pkt_queue)) { enqueue: __skb_queue_tail(&sd->input_pkt_queue, skb); #ifdef CONFIG_RPS - *qtail = sd->input_queue_head + sd->input_pkt_queue.qlen; + *qtail = sd->input_queue_head + + skb_queue_len(&sd->input_pkt_queue); #endif rps_unlock(sd); local_irq_restore(flags); @@ -2934,13 +2935,21 @@ static void flush_backlog(void *arg) struct sk_buff *skb, *tmp; rps_lock(sd); - skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) + skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { if (skb->dev == dev) { __skb_unlink(skb, &sd->input_pkt_queue); kfree_skb(skb); - input_queue_head_incr(sd); + input_queue_head_add(sd, 1); } + } rps_unlock(sd); + + skb_queue_walk_safe(&sd->process_queue, skb, tmp) { + if (skb->dev == dev) { + __skb_unlink(skb, &sd->process_queue); + kfree_skb(skb); + } + } } static int napi_gro_complete(struct sk_buff *skb) @@ -3286,24 +3295,33 @@ static int process_backlog(struct napi_struct *napi, int quota) } #endif napi->weight = weight_p; - do { + local_irq_disable(); + while (work < quota) { struct sk_buff *skb; + unsigned int qlen; + + while ((skb = __skb_dequeue(&sd->process_queue))) { + local_irq_enable(); + __netif_receive_skb(skb); + if (++work >= quota) + return work; + local_irq_disable(); + } - local_irq_disable(); rps_lock(sd); - skb = __skb_dequeue(&sd->input_pkt_queue); - if (!skb) { + qlen = skb_queue_len(&sd->input_pkt_queue); + if (qlen) { + input_queue_head_add(sd, qlen); + skb_queue_splice_tail_init(&sd->input_pkt_queue, + &sd->process_queue); + } + if (qlen < quota - work) { __napi_complete(napi); - rps_unlock(sd); - local_irq_enable(); - break; + quota = work + qlen; } - input_queue_head_incr(sd); rps_unlock(sd); - local_irq_enable(); - - __netif_receive_skb(skb); - } while (++work < quota); + } + local_irq_enable(); return work; } @@ -5630,8 +5648,10 @@ static int dev_cpu_callback(struct notifier_block *nfb, /* Process offline CPU's input_pkt_queue */ while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { netif_rx(skb); - input_queue_head_incr(oldsd); + input_queue_head_add(oldsd, 1); } + while ((skb = __skb_dequeue(&oldsd->process_queue))) + netif_rx(skb); return NOTIFY_OK; } @@ -5850,6 +5870,7 @@ static int __init net_dev_init(void) struct softnet_data *sd = &per_cpu(softnet_data, i); skb_queue_head_init(&sd->input_pkt_queue); + skb_queue_head_init(&sd->process_queue); sd->completion_queue = NULL; INIT_LIST_HEAD(&sd->poll_list); sd->output_queue = NULL; -- cgit v1.2.3 From dee42870a423ad485129f43cddfe7275479f11d8 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sun, 2 May 2010 05:42:16 +0000 Subject: net: fix softnet_stat Per cpu variable softnet_data.total was shared between IRQ and SoftIRQ context without any protection. And enqueue_to_backlog should update the netdev_rx_stat of the target CPU. This patch renames softnet_data.total to softnet_data.processed: the number of packets processed in uppper levels(IP stacks). softnet_stat data is moved into softnet_data. Signed-off-by: Changli Gao ---- include/linux/netdevice.h | 17 +++++++---------- net/core/dev.c | 26 ++++++++++++-------------- net/sched/sch_generic.c | 2 +- 3 files changed, 20 insertions(+), 25 deletions(-) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 17 +++++++---------- net/core/dev.c | 26 ++++++++++++-------------- net/sched/sch_generic.c | 2 +- 3 files changed, 20 insertions(+), 25 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 40d4c20d034..c39938f8a8d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -218,16 +218,6 @@ struct neighbour; struct neigh_parms; struct sk_buff; -struct netif_rx_stats { - unsigned total; - unsigned dropped; - unsigned time_squeeze; - unsigned cpu_collision; - unsigned received_rps; -}; - -DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); - struct netdev_hw_addr { struct list_head list; unsigned char addr[MAX_ADDR_LEN]; @@ -1390,6 +1380,12 @@ struct softnet_data { struct sk_buff *completion_queue; struct sk_buff_head process_queue; + /* stats */ + unsigned processed; + unsigned time_squeeze; + unsigned cpu_collision; + unsigned received_rps; + #ifdef CONFIG_RPS struct softnet_data *rps_ipi_list; @@ -1399,6 +1395,7 @@ struct softnet_data { unsigned int cpu; unsigned int input_queue_head; #endif + unsigned dropped; struct sk_buff_head input_pkt_queue; struct napi_struct backlog; }; diff --git a/net/core/dev.c b/net/core/dev.c index 100dcbd2973..36d53be4fca 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2205,8 +2205,6 @@ int netdev_max_backlog __read_mostly = 1000; int netdev_budget __read_mostly = 300; int weight_p __read_mostly = 64; /* old backlog weight */ -DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; - #ifdef CONFIG_RPS /* One global table that all flow-based protocols share. */ @@ -2366,7 +2364,7 @@ static void rps_trigger_softirq(void *data) struct softnet_data *sd = data; __napi_schedule(&sd->backlog); - __get_cpu_var(netdev_rx_stat).received_rps++; + sd->received_rps++; } #endif /* CONFIG_RPS */ @@ -2405,7 +2403,6 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, sd = &per_cpu(softnet_data, cpu); local_irq_save(flags); - __get_cpu_var(netdev_rx_stat).total++; rps_lock(sd); if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) { @@ -2429,9 +2426,9 @@ enqueue: goto enqueue; } + sd->dropped++; rps_unlock(sd); - __get_cpu_var(netdev_rx_stat).dropped++; local_irq_restore(flags); kfree_skb(skb); @@ -2806,7 +2803,7 @@ static int __netif_receive_skb(struct sk_buff *skb) skb->dev = master; } - __get_cpu_var(netdev_rx_stat).total++; + __get_cpu_var(softnet_data).processed++; skb_reset_network_header(skb); skb_reset_transport_header(skb); @@ -3490,7 +3487,7 @@ out: return; softnet_break: - __get_cpu_var(netdev_rx_stat).time_squeeze++; + sd->time_squeeze++; __raise_softirq_irqoff(NET_RX_SOFTIRQ); goto out; } @@ -3691,17 +3688,17 @@ static int dev_seq_show(struct seq_file *seq, void *v) return 0; } -static struct netif_rx_stats *softnet_get_online(loff_t *pos) +static struct softnet_data *softnet_get_online(loff_t *pos) { - struct netif_rx_stats *rc = NULL; + struct softnet_data *sd = NULL; while (*pos < nr_cpu_ids) if (cpu_online(*pos)) { - rc = &per_cpu(netdev_rx_stat, *pos); + sd = &per_cpu(softnet_data, *pos); break; } else ++*pos; - return rc; + return sd; } static void *softnet_seq_start(struct seq_file *seq, loff_t *pos) @@ -3721,12 +3718,12 @@ static void softnet_seq_stop(struct seq_file *seq, void *v) static int softnet_seq_show(struct seq_file *seq, void *v) { - struct netif_rx_stats *s = v; + struct softnet_data *sd = v; seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", - s->total, s->dropped, s->time_squeeze, 0, + sd->processed, sd->dropped, sd->time_squeeze, 0, 0, 0, 0, 0, /* was fastroute */ - s->cpu_collision, s->received_rps); + sd->cpu_collision, sd->received_rps); return 0; } @@ -5869,6 +5866,7 @@ static int __init net_dev_init(void) for_each_possible_cpu(i) { struct softnet_data *sd = &per_cpu(softnet_data, i); + memset(sd, 0, sizeof(*sd)); skb_queue_head_init(&sd->input_pkt_queue); skb_queue_head_init(&sd->process_queue); sd->completion_queue = NULL; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index aeddabfb8e4..a969b111bd7 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -94,7 +94,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, * Another cpu is holding lock, requeue & delay xmits for * some time. */ - __get_cpu_var(netdev_rx_stat).cpu_collision++; + __get_cpu_var(softnet_data).cpu_collision++; ret = dev_requeue_skb(skb, q); } -- cgit v1.2.3 From cd7b5396e7e4d10c51116f59f414ff90312af8d4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 2 May 2010 22:27:59 -0700 Subject: net: Use explicit "unsigned int" instead of plain "unsigned" in netdevice.h Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c39938f8a8d..98112fbddef 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -878,7 +878,7 @@ struct net_device { unsigned char operstate; /* RFC2863 operstate */ unsigned char link_mode; /* mapping policy to operstate */ - unsigned mtu; /* interface MTU value */ + unsigned int mtu; /* interface MTU value */ unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ @@ -1381,10 +1381,10 @@ struct softnet_data { struct sk_buff_head process_queue; /* stats */ - unsigned processed; - unsigned time_squeeze; - unsigned cpu_collision; - unsigned received_rps; + unsigned int processed; + unsigned int time_squeeze; + unsigned int cpu_collision; + unsigned int received_rps; #ifdef CONFIG_RPS struct softnet_data *rps_ipi_list; -- cgit v1.2.3 From 0e34e93177fb1f642cab080e0bde664c06c7183a Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 6 May 2010 00:47:21 -0700 Subject: netpoll: add generic support for bridge and bonding devices This whole patchset is for adding netpoll support to bridge and bonding devices. I already tested it for bridge, bonding, bridge over bonding, and bonding over bridge. It looks fine now. To make bridge and bonding support netpoll, we need to adjust some netpoll generic code. This patch does the following things: 1) introduce two new priv_flags for struct net_device: IFF_IN_NETPOLL which identifies we are processing a netpoll; IFF_DISABLE_NETPOLL is used to disable netpoll support for a device at run-time; 2) introduce one new method for netdev_ops: ->ndo_netpoll_cleanup() is used to clean up netpoll when a device is removed. 3) introduce netpoll_poll_dev() which takes a struct net_device * parameter; export netpoll_send_skb() and netpoll_poll_dev() which will be used later; 4) hide a pointer to struct netpoll in struct netpoll_info, ditto. 5) introduce ->real_dev for struct netpoll. 6) introduce a new status NETDEV_BONDING_DESLAE, which is used to disable netconsole before releasing a slave, to avoid deadlocks. Cc: David Miller Cc: Neil Horman Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 15 +++++++++------ include/linux/if.h | 2 ++ include/linux/netdevice.h | 1 + include/linux/netpoll.h | 5 +++++ include/linux/notifier.h | 1 + net/core/netpoll.c | 26 +++++++++++++++++++++----- 6 files changed, 39 insertions(+), 11 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index a361dea3557..ca142c47b2e 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -665,7 +665,8 @@ static int netconsole_netdev_event(struct notifier_block *this, struct netconsole_target *nt; struct net_device *dev = ptr; - if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER)) + if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || + event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN)) goto done; spin_lock_irqsave(&target_list_lock, flags); @@ -677,19 +678,21 @@ static int netconsole_netdev_event(struct notifier_block *this, strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); break; case NETDEV_UNREGISTER: - if (!nt->enabled) - break; netpoll_cleanup(&nt->np); + /* Fall through */ + case NETDEV_GOING_DOWN: + case NETDEV_BONDING_DESLAVE: nt->enabled = 0; - printk(KERN_INFO "netconsole: network logging stopped" - ", interface %s unregistered\n", - dev->name); break; } } netconsole_target_put(nt); } spin_unlock_irqrestore(&target_list_lock, flags); + if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE) + printk(KERN_INFO "netconsole: network logging stopped, " + "interface %s %s\n", dev->name, + event == NETDEV_UNREGISTER ? "unregistered" : "released slaves"); done: return NOTIFY_DONE; diff --git a/include/linux/if.h b/include/linux/if.h index 3a9f410a296..be350e62a90 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -71,6 +71,8 @@ * release skb->dst */ #define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ +#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */ +#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 98112fbddef..69022d47d6f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -724,6 +724,7 @@ struct net_device_ops { unsigned short vid); #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); + void (*ndo_netpoll_cleanup)(struct net_device *dev); #endif int (*ndo_set_vf_mac)(struct net_device *dev, int queue, u8 *mac); diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index a765ea89854..017e604d05f 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -14,6 +14,7 @@ struct netpoll { struct net_device *dev; + struct net_device *real_dev; char dev_name[IFNAMSIZ]; const char *name; void (*rx_hook)(struct netpoll *, int, char *, int); @@ -36,8 +37,11 @@ struct netpoll_info { struct sk_buff_head txq; struct delayed_work tx_work; + + struct netpoll *netpoll; }; +void netpoll_poll_dev(struct net_device *dev); void netpoll_poll(struct netpoll *np); void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_print_options(struct netpoll *np); @@ -47,6 +51,7 @@ int netpoll_trap(void); void netpoll_set_trap(int trap); void netpoll_cleanup(struct netpoll *np); int __netpoll_rx(struct sk_buff *skb); +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb); #ifdef CONFIG_NETPOLL diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 9c5d3fad01f..7c360962233 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -206,6 +206,7 @@ static inline int notifier_to_errno(int ret) #define NETDEV_POST_TYPE_CHANGE 0x000F #define NETDEV_POST_INIT 0x0010 #define NETDEV_UNREGISTER_BATCH 0x0011 +#define NETDEV_BONDING_DESLAVE 0x0012 #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a58f59b9759..94825b10955 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -179,9 +179,8 @@ static void service_arp_queue(struct netpoll_info *npi) } } -void netpoll_poll(struct netpoll *np) +void netpoll_poll_dev(struct net_device *dev) { - struct net_device *dev = np->dev; const struct net_device_ops *ops; if (!dev || !netif_running(dev)) @@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np) zap_completion_queue(); } +void netpoll_poll(struct netpoll *np) +{ + netpoll_poll_dev(np->dev); +} + static void refill_skbs(void) { struct sk_buff *skb; @@ -282,7 +286,7 @@ static int netpoll_owner_active(struct net_device *dev) return 0; } -static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { int status = NETDEV_TX_BUSY; unsigned long tries; @@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) tries > 0; --tries) { if (__netif_tx_trylock(txq)) { if (!netif_tx_queue_stopped(txq)) { + dev->priv_flags |= IFF_IN_NETPOLL; status = ops->ndo_start_xmit(skb, dev); + dev->priv_flags &= ~IFF_IN_NETPOLL; if (status == NETDEV_TX_OK) txq_trans_update(txq); } @@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np) atomic_inc(&npinfo->refcnt); } - if (!ndev->netdev_ops->ndo_poll_controller) { + npinfo->netpoll = np; + + if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || + !ndev->netdev_ops->ndo_poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", np->name, np->dev_name); err = -ENOTSUPP; @@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np) } if (atomic_dec_and_test(&npinfo->refcnt)) { + const struct net_device_ops *ops; skb_queue_purge(&npinfo->arp_tx); skb_queue_purge(&npinfo->txq); cancel_rearming_delayed_work(&npinfo->tx_work); @@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np) /* clean after last, unfinished work */ __skb_queue_purge(&npinfo->txq); kfree(npinfo); - np->dev->npinfo = NULL; + ops = np->dev->netdev_ops; + if (ops->ndo_netpoll_cleanup) + ops->ndo_netpoll_cleanup(np->dev); + else + np->dev->npinfo = NULL; } } @@ -908,6 +922,7 @@ void netpoll_set_trap(int trap) atomic_dec(&trapped); } +EXPORT_SYMBOL(netpoll_send_skb); EXPORT_SYMBOL(netpoll_set_trap); EXPORT_SYMBOL(netpoll_trap); EXPORT_SYMBOL(netpoll_print_options); @@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options); EXPORT_SYMBOL(netpoll_setup); EXPORT_SYMBOL(netpoll_cleanup); EXPORT_SYMBOL(netpoll_send_udp); +EXPORT_SYMBOL(netpoll_poll_dev); EXPORT_SYMBOL(netpoll_poll); -- cgit v1.2.3 From 3b098e2d7c693796cc4dffb07caa249fc0f70771 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 15 May 2010 23:57:10 -0700 Subject: net: Consistent skb timestamping With RPS inclusion, skb timestamping is not consistent in RX path. If netif_receive_skb() is used, its deferred after RPS dispatch. If netif_rx() is used, its done before RPS dispatch. This can give strange tcpdump timestamps results. I think timestamping should be done as soon as possible in the receive path, to get meaningful values (ie timestamps taken at the time packet was delivered by NIC driver to our stack), even if NAPI already can defer timestamping a bit (RPS can help to reduce the gap) Tom Herbert prefer to sample timestamps after RPS dispatch. In case sampling is expensive (HPET/acpi_pm on x86), this makes sense. Let admins switch from one mode to another, using a new sysctl, /proc/sys/net/core/netdev_tstamp_prequeue Its default value (1), means timestamps are taken as soon as possible, before backlog queueing, giving accurate timestamps. Setting a 0 value permits to sample timestamps when processing backlog, after RPS dispatch, to lower the load of the pre-RPS cpu. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 10 +++++++++ include/linux/netdevice.h | 1 + net/core/dev.c | 50 +++++++++++++++++++++++++++----------------- net/core/sysctl_net_core.c | 7 +++++++ 4 files changed, 49 insertions(+), 19 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index df38ef046f8..cbd05ffc606 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -84,6 +84,16 @@ netdev_max_backlog Maximum number of packets, queued on the INPUT side, when the interface receives packets faster than kernel can process them. +netdev_tstamp_prequeue +---------------------- + +If set to 0, RX packet timestamps can be sampled after RPS processing, when +the target CPU processes packets. It might give some delay on timestamps, but +permit to distribute the load on several cpus. + +If set to 1 (default), timestamps are sampled as soon as possible, before +queueing. + optmem_max ---------- diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 69022d47d6f..c1b2341897c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2100,6 +2100,7 @@ extern const struct net_device_stats *dev_get_stats(struct net_device *dev); extern void dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats); extern int netdev_max_backlog; +extern int netdev_tstamp_prequeue; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int skb_checksum_help(struct sk_buff *skb); diff --git a/net/core/dev.c b/net/core/dev.c index 5cbba0927a8..988e42912e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1454,7 +1454,7 @@ void net_disable_timestamp(void) } EXPORT_SYMBOL(net_disable_timestamp); -static inline void net_timestamp(struct sk_buff *skb) +static inline void net_timestamp_set(struct sk_buff *skb) { if (atomic_read(&netstamp_needed)) __net_timestamp(skb); @@ -1462,6 +1462,12 @@ static inline void net_timestamp(struct sk_buff *skb) skb->tstamp.tv64 = 0; } +static inline void net_timestamp_check(struct sk_buff *skb) +{ + if (!skb->tstamp.tv64 && atomic_read(&netstamp_needed)) + __net_timestamp(skb); +} + /** * dev_forward_skb - loopback an skb to another netif * @@ -1508,9 +1514,9 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) #ifdef CONFIG_NET_CLS_ACT if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS))) - net_timestamp(skb); + net_timestamp_set(skb); #else - net_timestamp(skb); + net_timestamp_set(skb); #endif rcu_read_lock(); @@ -2201,6 +2207,7 @@ EXPORT_SYMBOL(dev_queue_xmit); =======================================================================*/ int netdev_max_backlog __read_mostly = 1000; +int netdev_tstamp_prequeue __read_mostly = 1; int netdev_budget __read_mostly = 300; int weight_p __read_mostly = 64; /* old backlog weight */ @@ -2465,8 +2472,8 @@ int netif_rx(struct sk_buff *skb) if (netpoll_rx(skb)) return NET_RX_DROP; - if (!skb->tstamp.tv64) - net_timestamp(skb); + if (netdev_tstamp_prequeue) + net_timestamp_check(skb); #ifdef CONFIG_RPS { @@ -2791,8 +2798,8 @@ static int __netif_receive_skb(struct sk_buff *skb) int ret = NET_RX_DROP; __be16 type; - if (!skb->tstamp.tv64) - net_timestamp(skb); + if (!netdev_tstamp_prequeue) + net_timestamp_check(skb); if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb)) return NET_RX_SUCCESS; @@ -2910,23 +2917,28 @@ out: */ int netif_receive_skb(struct sk_buff *skb) { + if (netdev_tstamp_prequeue) + net_timestamp_check(skb); + #ifdef CONFIG_RPS - struct rps_dev_flow voidflow, *rflow = &voidflow; - int cpu, ret; + { + struct rps_dev_flow voidflow, *rflow = &voidflow; + int cpu, ret; - rcu_read_lock(); + rcu_read_lock(); + + cpu = get_rps_cpu(skb->dev, skb, &rflow); - cpu = get_rps_cpu(skb->dev, skb, &rflow); + if (cpu >= 0) { + ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); + rcu_read_unlock(); + } else { + rcu_read_unlock(); + ret = __netif_receive_skb(skb); + } - if (cpu >= 0) { - ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); - rcu_read_unlock(); - } else { - rcu_read_unlock(); - ret = __netif_receive_skb(skb); + return ret; } - - return ret; #else return __netif_receive_skb(skb); #endif diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index dcc7d25996a..01eee5d984b 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -121,6 +121,13 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "netdev_tstamp_prequeue", + .data = &netdev_tstamp_prequeue, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { .procname = "message_cost", .data = &net_ratelimit_state.interval, -- cgit v1.2.3 From 57b610805ce92dbd79fc97509f80fa5391b99623 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 17 May 2010 22:49:55 -0700 Subject: net: Add netlink support for virtual port management (was iovnl) Add new netdev ops ndo_{set|get}_vf_port to allow setting of port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/ RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF (added to end of IFLA_cmd list). These are both nested atrtibutes using this layout: [IFLA_NUM_VF] [IFLA_VF_PORTS] [IFLA_VF_PORT] [IFLA_PORT_*], ... [IFLA_VF_PORT] [IFLA_PORT_*], ... ... [IFLA_PORT_SELF] [IFLA_PORT_*], ... These attributes are design to be set and get symmetrically. VF_PORTS is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV device. PORT_SELF is for the PF of the SR-IOV device, in case it wants to also have a port-profile, or for the case where the VF==PF, like in enic patch 2/2 of this patch set. A port-profile is used to configure/enable the external switch virtual port backing the netdev interface, not to configure the host-facing side of the netdev. A port-profile is an identifier known to the switch. How port- profiles are installed on the switch or how available port-profiles are made know to the host is outside the scope of this patch. There are two types of port-profiles specs in the netlink msg. The first spec is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices that run a similar protocol as VDP but in firmware, thus hiding the protocol details. In either case, the specs have much in common and makes sense to define the netlink msg as the union of the two specs. For example, both specs have a notition of associating/deassociating a port-profile. And both specs require some information from the hypervisor manager, such as client port instance ID. The general flow is the port-profile is applied to a host netdev interface using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the switch, and the switch virtual port backing the host netdev interface is configured/enabled based on the settings defined by the port-profile. What those settings comprise, and how those settings are managed is again outside the scope of this patch, since this patch only deals with the first step in the flow. Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller --- include/linux/if_link.h | 75 ++++++++++++++++++++ include/linux/netdevice.h | 8 +++ net/core/rtnetlink.c | 169 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 251 insertions(+), 1 deletion(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c3af67fce3f..85c812db5a3 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -113,6 +113,8 @@ enum { IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ IFLA_VFINFO_LIST, IFLA_STATS64, + IFLA_VF_PORTS, + IFLA_PORT_SELF, __IFLA_MAX }; @@ -274,4 +276,77 @@ struct ifla_vf_info { __u32 qos; __u32 tx_rate; }; + +/* VF ports management section + * + * Nested layout of set/get msg is: + * + * [IFLA_NUM_VF] + * [IFLA_VF_PORTS] + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * ... + * [IFLA_PORT_SELF] + * [IFLA_PORT_*], ... + */ + +enum { + IFLA_VF_PORT_UNSPEC, + IFLA_VF_PORT, /* nest */ + __IFLA_VF_PORT_MAX, +}; + +#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) + +enum { + IFLA_PORT_UNSPEC, + IFLA_PORT_VF, /* __u32 */ + IFLA_PORT_PROFILE, /* string */ + IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ + IFLA_PORT_INSTANCE_UUID, /* binary UUID */ + IFLA_PORT_HOST_UUID, /* binary UUID */ + IFLA_PORT_REQUEST, /* __u8 */ + IFLA_PORT_RESPONSE, /* __u16, output only */ + __IFLA_PORT_MAX, +}; + +#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) + +#define PORT_PROFILE_MAX 40 +#define PORT_UUID_MAX 16 +#define PORT_SELF_VF -1 + +enum { + PORT_REQUEST_PREASSOCIATE = 0, + PORT_REQUEST_PREASSOCIATE_RR, + PORT_REQUEST_ASSOCIATE, + PORT_REQUEST_DISASSOCIATE, +}; + +enum { + PORT_VDP_RESPONSE_SUCCESS = 0, + PORT_VDP_RESPONSE_INVALID_FORMAT, + PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_VDP_RESPONSE_UNUSED_VTID, + PORT_VDP_RESPONSE_VTID_VIOLATION, + PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, + PORT_VDP_RESPONSE_OUT_OF_SYNC, + /* 0x08-0xFF reserved for future VDP use */ + PORT_PROFILE_RESPONSE_SUCCESS = 0x100, + PORT_PROFILE_RESPONSE_INPROGRESS, + PORT_PROFILE_RESPONSE_INVALID, + PORT_PROFILE_RESPONSE_BADSTATE, + PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_PROFILE_RESPONSE_ERROR, +}; + +struct ifla_port_vsi { + __u8 vsi_mgr_id; + __u8 vsi_type_id[3]; + __u8 vsi_type_version; + __u8 pad[3]; +}; + #endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c1b2341897c..c3487a6bdf9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -686,6 +686,9 @@ struct netdev_rx_queue { * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); * int (*ndo_get_vf_config)(struct net_device *dev, * int vf, struct ifla_vf_info *ivf); + * int (*ndo_set_vf_port)(struct net_device *dev, int vf, + * struct nlattr *port[]); + * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb); */ #define HAVE_NET_DEVICE_OPS struct net_device_ops { @@ -735,6 +738,11 @@ struct net_device_ops { int (*ndo_get_vf_config)(struct net_device *dev, int vf, struct ifla_vf_info *ivf); + int (*ndo_set_vf_port)(struct net_device *dev, + int vf, + struct nlattr *port[]); + int (*ndo_get_vf_port)(struct net_device *dev, + int vf, struct sk_buff *skb); #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) int (*ndo_fcoe_enable)(struct net_device *dev); int (*ndo_fcoe_disable)(struct net_device *dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 66db1201da9..e4b9870e470 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -660,6 +660,31 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev) return 0; } +static size_t rtnl_port_size(const struct net_device *dev) +{ + size_t port_size = nla_total_size(4) /* PORT_VF */ + + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ + + nla_total_size(sizeof(struct ifla_port_vsi)) + /* PORT_VSI_TYPE */ + + nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */ + + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */ + + nla_total_size(1) /* PROT_VDP_REQUEST */ + + nla_total_size(2); /* PORT_VDP_RESPONSE */ + size_t vf_ports_size = nla_total_size(sizeof(struct nlattr)); + size_t vf_port_size = nla_total_size(sizeof(struct nlattr)) + + port_size; + size_t port_self_size = nla_total_size(sizeof(struct nlattr)) + + port_size; + + if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) + return 0; + if (dev_num_vf(dev->dev.parent)) + return port_self_size + vf_ports_size + + vf_port_size * dev_num_vf(dev->dev.parent); + else + return port_self_size; +} + static inline size_t if_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) @@ -680,9 +705,82 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) + nla_total_size(1) /* IFLA_LINKMODE */ + nla_total_size(4) /* IFLA_NUM_VF */ + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ + + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ } +static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) +{ + struct nlattr *vf_ports; + struct nlattr *vf_port; + int vf; + int err; + + vf_ports = nla_nest_start(skb, IFLA_VF_PORTS); + if (!vf_ports) + return -EMSGSIZE; + + for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { + vf_port = nla_nest_start(skb, IFLA_VF_PORT); + if (!vf_port) { + nla_nest_cancel(skb, vf_ports); + return -EMSGSIZE; + } + NLA_PUT_U32(skb, IFLA_PORT_VF, vf); + err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); + if (err) { +nla_put_failure: + nla_nest_cancel(skb, vf_port); + continue; + } + nla_nest_end(skb, vf_port); + } + + nla_nest_end(skb, vf_ports); + + return 0; +} + +static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) +{ + struct nlattr *port_self; + int err; + + port_self = nla_nest_start(skb, IFLA_PORT_SELF); + if (!port_self) + return -EMSGSIZE; + + err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); + if (err) { + nla_nest_cancel(skb, port_self); + return err; + } + + nla_nest_end(skb, port_self); + + return 0; +} + +static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) +{ + int err; + + if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) + return 0; + + err = rtnl_port_self_fill(skb, dev); + if (err) + return err; + + if (dev_num_vf(dev->dev.parent)) { + err = rtnl_vf_ports_fill(skb, dev); + if (err) + return err; + } + + return 0; +} + static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, unsigned int flags) @@ -754,13 +852,15 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, goto nla_put_failure; copy_rtnl_link_stats64(nla_data(attr), stats); + if (dev->dev.parent) + NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); + if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { int i; struct nlattr *vfinfo, *vf; int num_vfs = dev_num_vf(dev->dev.parent); - NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); if (!vfinfo) goto nla_put_failure; @@ -788,6 +888,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, } nla_nest_end(skb, vfinfo); } + + if (rtnl_port_fill(skb, dev)) + goto nla_put_failure; + if (dev->rtnl_link_ops) { if (rtnl_link_fill(skb, dev) < 0) goto nla_put_failure; @@ -849,6 +953,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_NET_NS_PID] = { .type = NLA_U32 }, [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, + [IFLA_VF_PORTS] = { .type = NLA_NESTED }, + [IFLA_PORT_SELF] = { .type = NLA_NESTED }, }; EXPORT_SYMBOL(ifla_policy); @@ -870,6 +976,20 @@ static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { .len = sizeof(struct ifla_vf_tx_rate) }, }; +static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { + [IFLA_PORT_VF] = { .type = NLA_U32 }, + [IFLA_PORT_PROFILE] = { .type = NLA_STRING, + .len = PORT_PROFILE_MAX }, + [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_port_vsi)}, + [IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY, + .len = PORT_UUID_MAX }, + [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING, + .len = PORT_UUID_MAX }, + [IFLA_PORT_REQUEST] = { .type = NLA_U8, }, + [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, +}; + struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) { struct net *net; @@ -1089,6 +1209,53 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, } err = 0; + if (tb[IFLA_VF_PORTS]) { + struct nlattr *port[IFLA_PORT_MAX+1]; + struct nlattr *attr; + int vf; + int rem; + + err = -EOPNOTSUPP; + if (!ops->ndo_set_vf_port) + goto errout; + + nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { + if (nla_type(attr) != IFLA_VF_PORT) + continue; + err = nla_parse_nested(port, IFLA_PORT_MAX, + attr, ifla_port_policy); + if (err < 0) + goto errout; + if (!port[IFLA_PORT_VF]) { + err = -EOPNOTSUPP; + goto errout; + } + vf = nla_get_u32(port[IFLA_PORT_VF]); + err = ops->ndo_set_vf_port(dev, vf, port); + if (err < 0) + goto errout; + modified = 1; + } + } + err = 0; + + if (tb[IFLA_PORT_SELF]) { + struct nlattr *port[IFLA_PORT_MAX+1]; + + err = nla_parse_nested(port, IFLA_PORT_MAX, + tb[IFLA_PORT_SELF], ifla_port_policy); + if (err < 0) + goto errout; + + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_port) + err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); + if (err < 0) + goto errout; + modified = 1; + } + err = 0; + errout: if (err < 0 && modified && net_ratelimit()) printk(KERN_WARNING "A link change request failed with " -- cgit v1.2.3