Netdev List
 help / color / mirror / Atom feed
* [PATCH RFC net-next 16/21] net: add a possibility to get private from netdev_adjacent->list
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev
  Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
	Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

It will be useful to get first/last element.

CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 include/linux/netdevice.h |  1 +
 net/core/dev.c            | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 20afdf98..bde2244 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2819,6 +2819,7 @@ extern void *netdev_lower_neigh_get_next_private_rcu(struct net_device *dev,
 	     priv; \
 	     priv = netdev_lower_neigh_get_next_private_rcu(dev, &(iter)))
 
+extern void *netdev_adjacent_get_private(struct list_head *adj_list);
 extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
 extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
 extern int netdev_upper_dev_link(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 1b9862b..6df11a0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4530,6 +4530,16 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_get);
 
+void *netdev_adjacent_get_private(struct list_head *adj_list)
+{
+	struct netdev_adjacent *adj;
+
+	adj = list_entry(adj_list, struct netdev_adjacent, list);
+
+	return adj->private;
+}
+EXPORT_SYMBOL(netdev_adjacent_get_private);
+
 /* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
  * @dev: device
  * @iter: list_head ** of the current position
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 18/21] net: add a function to get the next/prev private
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev
  Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
	Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

The boolean flag specifies which direction to go.

CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 include/linux/netdevice.h |  2 ++
 net/core/dev.c            | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bde2244..a112ccc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2835,6 +2835,8 @@ extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
 					      struct net_device *lower_dev);
 extern void *netdev_lower_dev_get_private(struct net_device *dev,
 					  struct net_device *lower_dev);
+extern void *netdev_lower_dev_get_next_private(struct net_device *dev,
+					       void *private, bool prev);
 extern int skb_checksum_help(struct sk_buff *skb);
 extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 	netdev_features_t features, bool tx_path);
diff --git a/net/core/dev.c b/net/core/dev.c
index 6df11a0..c694059 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5163,6 +5163,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_lower_dev_get_private);
 
+extern void *netdev_lower_dev_get_next_private(struct net_device *dev,
+					       void *private, bool prev)
+{
+	struct netdev_adjacent *lower;
+
+	list_for_each_entry(lower, &dev->neighbour_dev_list.lower, list)
+		if (lower->private == private)
+			break;
+
+	if (&lower->list == &dev->neighbour_dev_list.lower)
+		return NULL;
+
+	lower = prev ? list_entry(lower->list.prev, struct netdev_adjacent, list) :
+		       list_entry(lower->list.next, struct netdev_adjacent, list);
+	if (&lower->list != &dev->neighbour_dev_list.lower)
+		return lower->private;
+
+	lower = prev ? list_entry(lower->list.prev, struct netdev_adjacent, list) :
+		       list_entry(lower->list.next, struct netdev_adjacent, list);
+
+	return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_next_private);
+
 static void dev_change_rx_flags(struct net_device *dev, int flags)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 19/21] bonding: use neighbours for bond_next/prev_slave()
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

Use netdev_lower_dev_get_next_private(), it will return NULL in case the
list is empty, so no need to verify.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bonding.h | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 6731281..b8047f3 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -76,8 +76,6 @@
 
 #define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))
 
-#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
-
 /* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
 #define bond_first_slave(bond) \
 	(bond_has_slaves(bond) ? \
@@ -93,12 +91,10 @@
 
 /* Since bond_first/last_slave can return NULL, these can return NULL too */
 #define bond_next_slave(bond, pos) \
-	(bond_is_last_slave(bond, pos) ? bond_first_slave(bond) : \
-					 bond_to_slave((pos)->list.next))
+	netdev_lower_dev_get_next_private((bond)->dev, pos, false)
 
 #define bond_prev_slave(bond, pos) \
-	(bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \
-					  bond_to_slave((pos)->list.prev))
+	netdev_lower_dev_get_next_private((bond)->dev, pos, true)
 
 /**
  * bond_for_each_slave_from - iterate the slaves list from a starting point
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 20/21] bonding: use bond_for_each_slave() in bond_uninit()
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

We're safe agains removal there, cause we use neighbours primitives.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bond_main.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 59814c9..ce1b0fb 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4099,12 +4099,13 @@ static void bond_setup(struct net_device *bond_dev)
 static void bond_uninit(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *tmp_slave;
+	struct list_head *iter;
+	struct slave *slave;
 
 	bond_netpoll_cleanup(bond_dev);
 
 	/* Release the bonded slaves */
-	list_for_each_entry_safe(slave, tmp_slave, &bond->slave_list, list)
+	bond_for_each_slave(bond, slave, iter)
 		__bond_release_one(bond_dev, slave->dev, true);
 	pr_info("%s: released all slaves\n", bond_dev->name);
 
-- 
1.8.4

^ permalink raw reply related

* 3.11rc7 net/ipv6 addrlabel OOPS
From: Michele Baldessari @ 2013-09-02 21:31 UTC (permalink / raw)
  To: netdev, Hideaki YOSHIFUJI; +Cc: David S.  Miller

Hi,

with the latest linux master git tree from Linus
(248d296d6d9df384996c2ed95676b367d876d48c - 2 Sep) I can reproduceably oops 
the kernel with the following commands:
ip addrlabel flush
ip addrlabel add prefix ::1/128              label 0
ip addrlabel add prefix ::/0                 label 1

The backtrace is:
[   15.129204] BUG: unable to handle kernel NULL pointer dereference at 0000000000000028
[   15.129220] IP: [<ffffffff815f3720>] ip6addrlbl_add+0x210/0x370
[   15.129235] PGD 114f64067 PUD 115bdc067 PMD 0 
[   15.129248] Oops: 0000 [#1] SMP 
[   15.129257] Modules linked in: nf_conntrack_netbios_ns
nf_conntrack_broadcast ipt_MASQUERADE ip6table_nat nf_nat_ipv6
ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat
nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4
xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter
ip6_tables snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device
snd_pcm snd_page_alloc snd_timer joydev pcspkr serio_raw virtio_balloon
microcode snd soundcore i2c_piix4 mperf xfs libcrc32c qxl drm_kms_helper
ttm drm virtio_net virtio_blk i2c_core ata_generic pata_acpi floppy
[   15.129401] CPU: 3 PID: 1122 Comm: ip Not tainted 3.11.0-rc7+ #2
[   15.129407] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[   15.129414] task: ffff88011481eac0 ti: ffff8801149ac000 task.ti: ffff8801149ac000
[   15.129422] RIP: 0010:[<ffffffff815f3720>]  [<ffffffff815f3720>] ip6addrlbl_add+0x210/0x370
[   15.129434] RSP: 0018:ffff8801149ad9c8  EFLAGS: 00010246
[   15.129440] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88011453b900
[   15.129447] RDX: 0000000000000007 RSI: 0000000000000000 RDI: 0000000000000246
[   15.129455] RBP: ffff8801149ada18 R08: 0000000000000000 R09: 00000000000002a1
[   15.129578] R10: 00000000127c7901 R11: ffffffff81855500 R12: ffff880119baaa28
[   15.129700] R13: 0000000000000000 R14: 0000000000000000 R15: ffff880114e34ea0
[   15.129828] FS:  00007f4449519740(0000) GS:ffff88011fd80000(0000) knlGS:0000000000000000
[   15.129952] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[   15.130125] CR2: 0000000000000028 CR3: 0000000114280000 CR4: 00000000000006e0
[   15.130133] Stack:
[   15.130133]  0000000000000000 0000000000000000 00000000149ada18 ffffffff81cbd940
[   15.130133]  0000000000000001 ffff880119baaa00 ffffffff81cbd940 0000000000000038
[   15.130133]  ffff880119baaa24 ffff880119baaa28 ffff8801149ada98 ffffffff815f3b3e
[   15.130133] Call Trace:
[   15.130133]  [<ffffffff815f3b3e>] ip6addrlbl_newdel+0x24e/0x2d0
[   15.130133]  [<ffffffff8129843e>] ? selinux_capable+0x2e/0x40
[   15.130133]  [<ffffffff8154e669>] rtnetlink_rcv_msg+0x99/0x260
[   15.130133]  [<ffffffff812956c5>] ? sock_has_perm+0x75/0x90
[   15.130133]  [<ffffffff8154e5d0>] ? rtnetlink_rcv+0x30/0x30
[   15.130133]  [<ffffffff8156d0a9>] netlink_rcv_skb+0xa9/0xc0
[   15.130133]  [<ffffffff8154e5c8>] rtnetlink_rcv+0x28/0x30
[   15.130133]  [<ffffffff8156c6fd>] netlink_unicast+0xdd/0x190
[   15.130133]  [<ffffffff8156caaf>] netlink_sendmsg+0x2ff/0x740
[   15.130133]  [<ffffffff815296b9>] sock_sendmsg+0x99/0xd0
[   15.130133]  [<ffffffff812f848e>] ? radix_tree_lookup_slot+0xe/0x10
[   15.130133]  [<ffffffff81529aac>] ___sys_sendmsg+0x36c/0x380
[   15.130133]  [<ffffffff81164e11>] ? handle_mm_fault+0x291/0x660
[   15.130133]  [<ffffffff81646f74>] ? __do_page_fault+0x1f4/0x510
[   15.130133]  [<ffffffff8156c096>] ? netlink_autobind.isra.43+0x106/0x170
[   15.130133]  [<ffffffff8152852f>] ? move_addr_to_user+0xaf/0xd0
[   15.130133]  [<ffffffff8152862c>] ? SYSC_getsockname+0xdc/0xf0
[   15.130133]  [<ffffffff8152a892>] __sys_sendmsg+0x42/0x80
[   15.130133]  [<ffffffff8152a8e2>] SyS_sendmsg+0x12/0x20
[   15.130133]  [<ffffffff8164b9d9>] system_call_fastpath+0x16/0x1b
[   15.130133] Code: 30 83 05 0f a7 9e 00 01 31 db 80 05 02 a7 9e 00 01
31 c0 85 db 0f 85 e0 00 00 00 48 83 c4 28 5b 41 5c 41 5d 41 5e 41 5f 5d
c3 90 <48> 8b 04 25 28 00 00 00 49 8d 57 28 49 c7 47 30 28 00 00 00 49 
[   15.130133] RIP  [<ffffffff815f3720>] ip6addrlbl_add+0x210/0x370
[   15.130133]  RSP <ffff8801149ad9c8>
[   15.130133] CR2: 0000000000000028

I believe I've bisected it down to (although it might very well be that
this patch just brought the root issue to surface):
b67bfe0 - 2013-02-27 - hlist: drop the node parameter from iterators

cheers,
Michele
-- 
Michele Baldessari            <michele@acksyn.org>
C2A5 9DA3 9961 4FFB E01B  D0BC DDD4 DCCB 7515 5C6D

^ permalink raw reply

* [PATCH RFC net-next 21/21] bonding: remove slave lists
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

And all the initialization.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bond_main.c | 4 ----
 drivers/net/bonding/bonding.h   | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ce1b0fb..9c24bab 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -992,7 +992,6 @@ void bond_select_active_slave(struct bonding *bond)
  */
 static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
 {
-	list_add_tail_rcu(&new_slave->list, &bond->slave_list);
 	bond->slave_cnt++;
 }
 
@@ -1008,7 +1007,6 @@ static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
  */
 static void bond_detach_slave(struct bonding *bond, struct slave *slave)
 {
-	list_del_rcu(&slave->list);
 	bond->slave_cnt--;
 }
 
@@ -1402,7 +1400,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		res = -ENOMEM;
 		goto err_undo_flags;
 	}
-	INIT_LIST_HEAD(&new_slave->list);
 	/*
 	 * Set the new_slave's queue_id to be zero.  Queue ID mapping
 	 * is set via sysfs or module option if desired.
@@ -4043,7 +4040,6 @@ static void bond_setup(struct net_device *bond_dev)
 	/* initialize rwlocks */
 	rwlock_init(&bond->lock);
 	rwlock_init(&bond->curr_slave_lock);
-	INIT_LIST_HEAD(&bond->slave_list);
 	bond->params = bonding_defaults;
 
 	/* Initialize pointers */
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index b8047f3..57b95d2 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -180,7 +180,6 @@ struct bond_parm_tbl {
 
 struct slave {
 	struct net_device *dev; /* first - useful for panic debug */
-	struct list_head list;
 	struct bonding *bond; /* our master */
 	int    delay;
 	unsigned long jiffies;
@@ -220,7 +219,6 @@ struct slave {
  */
 struct bonding {
 	struct   net_device *dev; /* first - useful for panic debug */
-	struct   list_head slave_list;
 	struct   slave *curr_active_slave;
 	struct   slave *current_arp_slave;
 	struct   slave *primary_slave;
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 0/21] bonding: use neighbours instead of own lists
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Andy Gospodarek, David S. Miller, Patrick McHardy,
	Eric Dumazet, Jiri Pirko, Alexander Duyck, Veaceslav Falico

(on top of "net: correctly interlink lower/upper devices" - the fix is
vital)

Hi,

I'm sending it as early as possible, because it's quite a big patchset and
some of the approaches I've chosen are not really easy/straightforward. It
will require a lot of work, obviously, before I can send it as a proper
patchset ready to be considered for inclusion, even though it works now.

I'm sending it to gather any feedback possible.

This patchset introduces all the needed infrastructure, on top of current
adjacent lists, to be able to remove bond's slave_list/slave->list. The
overhead in memory/CPU is minimal, and after the patchset bonding can rely
on its slave-related functions, given the proper locking.

It also automatically creates slave/upper and master symlinks in dev's
sysfs directory.

The current version works ok, as first tests have shown. I'm testing it
further.

Here is a short description of each:

net: add neighbour_dev_list to save only neighbours
	Adding two new lists, each for the device neighbours only - it's
	done for speed when going through slaves.
net: add RCU variant to search for netdev_adjacent link
net: add netdev_adjacent->private and allow to use it
	These two patches add infrastructure for the netdev_adjacent new
	member - private, which contains master's private info for the
	slave - in case of bonding it's struct slave *.
net: expose the master link to sysfs, and remove it from bond
	Create sysfs link for master devices.
vlan: link the upper neighbour only after registering
	vlan linked itself before registering, which ends badly if we'll
	have a user before it registers, and is not ready for sysfs
	operations.
net: create sysfs symlinks for neighbour devices
	Create sysfs links to slave/upper devices.
bonding: add bond_has_slaves() and use it
	It'll be easier for modification in the future.
bonding: convert bond_has_slaves() to use the neighbour list
	First usage of the neighbour_dev_list.lower - bonding's lower
	devices are *always* slaves, so we can verify if it's empty or not.
bonding: populate neighbour's private on enslave
	Attach struct slave * to each lower link.
bonding: modify bond_get_slave_by_dev() to use neighbours
	We can search already for ->private here.
bonding: remove bond_for_each_slave_reverse()
	It's useless and hard to read sometimes.
net: add for_each iterators through neighbour lower link's private
bonding: make bond_for_each_slave() use lower neighbour's private
	These two patches convert bond_for_each_slave() to use neighbours
	lower list.
net: add netdev_for_each_lower_neigh_private_continue()
bonding: use neighbour list for bond_for_each_slave_continue()
	These two - bond_for_each_slave_continue().
net: add a possibility to get private from netdev_adjacent->list
bonding: convert first/last slave logic to use neighbours
	Convert those little helpers without huge functions - just use the
	list's next/prev.
net: add a function to get the next/prev private
bonding: use neighbours for bond_next/prev_slave()
	Same.
bonding: use bond_for_each_slave() in bond_uninit()
	We can safely use it - we're using the ->next field.
bonding: remove slave lists
	Finally.

I'll update if anything comes up.

Thanks in advance.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
CC: Patrick McHardy <kaber@trash.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>

---
 drivers/net/bonding/bond_3ad.c    |  13 +-
 drivers/net/bonding/bond_alb.c    |  42 ++--
 drivers/net/bonding/bond_main.c   | 204 +++++++++-------
 drivers/net/bonding/bond_procfs.c |   5 +-
 drivers/net/bonding/bond_sysfs.c  |  62 ++---
 drivers/net/bonding/bonding.h     |  65 ++---
 include/linux/netdevice.h         |  67 +++++-
 net/8021q/vlan.c                  |  14 +-
 net/core/dev.c                    | 483 +++++++++++++++++++++++++++++++++-----
 9 files changed, 686 insertions(+), 269 deletions(-)

^ permalink raw reply

* [PATCH RFC net-next 13/21] bonding: make bond_for_each_slave() use lower neighbour's private
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

It needs a list_head *iter, so add it wherever needed. Use both non-rcu and
rcu variants.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bond_3ad.c    |  8 ++--
 drivers/net/bonding/bond_alb.c    | 18 ++++----
 drivers/net/bonding/bond_main.c   | 88 +++++++++++++++++++++++++--------------
 drivers/net/bonding/bond_procfs.c |  5 ++-
 drivers/net/bonding/bond_sysfs.c  | 23 ++++++----
 drivers/net/bonding/bonding.h     | 12 +++---
 6 files changed, 98 insertions(+), 56 deletions(-)

diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index f0cca88..7430cbb 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2419,6 +2419,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 {
 	struct slave *slave, *start_at;
 	struct bonding *bond = netdev_priv(dev);
+	struct list_head *iter;
 	int slave_agg_no;
 	int slaves_in_agg;
 	int agg_id;
@@ -2444,7 +2445,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
 	slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
@@ -2514,14 +2515,15 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
  */
 void bond_3ad_update_lacp_rate(struct bonding *bond)
 {
-	struct slave *slave;
 	struct port *port = NULL;
+	struct list_head *iter;
+	struct slave *slave;
 	int lacp_fast;
 
 	write_lock_bh(&bond->lock);
 	lacp_fast = bond->params.lacp_fast;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		port = &(SLAVE_AD_INFO(slave).port);
 		if (port->slave == NULL)
 			continue;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index bda976f..738eeae 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -223,13 +223,14 @@ static long long compute_gap(struct slave *slave)
 static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
 {
 	struct slave *slave, *least_loaded;
+	struct list_head *iter;
 	long long max_gap;
 
 	least_loaded = NULL;
 	max_gap = LLONG_MIN;
 
 	/* Find the slave with the largest gap */
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (SLAVE_IS_OK(slave)) {
 			long long gap = compute_gap(slave);
 
@@ -1174,8 +1175,9 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
  */
 static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *tmp_slave1, *free_mac_slave = NULL;
 	struct slave *has_bond_addr = bond->curr_active_slave;
+	struct slave *tmp_slave1, *free_mac_slave = NULL;
+	struct list_head *iter;
 
 	if (!bond_has_slaves(bond)) {
 		/* this is the first slave */
@@ -1198,7 +1200,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 	/* The slave's address is equal to the address of the bond.
 	 * Search for a spare address in the bond for this slave.
 	 */
-	bond_for_each_slave(bond, tmp_slave1) {
+	bond_for_each_slave(bond, tmp_slave1, iter) {
 		if (!bond_slave_has_mac(bond, tmp_slave1->perm_hwaddr)) {
 			/* no slave has tmp_slave1's perm addr
 			 * as its curr addr
@@ -1249,6 +1251,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 static int alb_set_mac_address(struct bonding *bond, void *addr)
 {
 	struct slave *slave, *rollback_slave;
+	struct list_head *iter;
 	struct sockaddr sa;
 	char tmp_addr[ETH_ALEN];
 	int res;
@@ -1256,7 +1259,7 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
 	if (bond->alb_info.rlb_enabled)
 		return 0;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		/* save net_device's current hw address */
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 
@@ -1276,7 +1279,7 @@ unwind:
 	sa.sa_family = bond->dev->type;
 
 	/* unwind from head to the slave that failed */
-	bond_for_each_slave(bond, rollback_slave) {
+	bond_for_each_slave(bond, rollback_slave, iter) {
 		if (rollback_slave == slave)
 			break;
 		memcpy(tmp_addr, rollback_slave->dev->dev_addr, ETH_ALEN);
@@ -1462,6 +1465,7 @@ void bond_alb_monitor(struct work_struct *work)
 	struct bonding *bond = container_of(work, struct bonding,
 					    alb_work.work);
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct list_head *iter;
 	struct slave *slave;
 
 	read_lock(&bond->lock);
@@ -1484,7 +1488,7 @@ void bond_alb_monitor(struct work_struct *work)
 		 */
 		read_lock(&bond->curr_slave_lock);
 
-		bond_for_each_slave(bond, slave)
+		bond_for_each_slave(bond, slave, iter)
 			alb_send_learning_packets(slave, slave->dev->dev_addr);
 
 		read_unlock(&bond->curr_slave_lock);
@@ -1497,7 +1501,7 @@ void bond_alb_monitor(struct work_struct *work)
 
 		read_lock(&bond->curr_slave_lock);
 
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			tlb_clear_slave(bond, slave, 1);
 			if (slave == bond->curr_active_slave) {
 				SLAVE_TLB_INFO(slave).load =
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 0a4aa0d..297b910 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -333,9 +333,10 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave, *rollback_slave;
+	struct list_head *iter;
 	int res;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		res = vlan_vid_add(slave->dev, proto, vid);
 		if (res)
 			goto unwind;
@@ -345,7 +346,7 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
 
 unwind:
 	/* unwind to the slave that failed */
-	bond_for_each_slave(bond, rollback_slave) {
+	bond_for_each_slave(bond, rollback_slave, iter) {
 		if (rollback_slave == slave)
 			break;
 
@@ -364,9 +365,10 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
 				 __be16 proto, u16 vid)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct list_head *iter;
 	struct slave *slave;
 
-	bond_for_each_slave(bond, slave)
+	bond_for_each_slave(bond, slave, iter)
 		vlan_vid_del(slave->dev, proto, vid);
 
 	if (bond_is_lb(bond))
@@ -386,6 +388,7 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
  */
 static int bond_set_carrier(struct bonding *bond)
 {
+	struct list_head *iter;
 	struct slave *slave;
 
 	if (!bond_has_slaves(bond))
@@ -394,7 +397,7 @@ static int bond_set_carrier(struct bonding *bond)
 	if (bond->params.mode == BOND_MODE_8023AD)
 		return bond_3ad_set_carrier(bond);
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (slave->link == BOND_LINK_UP) {
 			if (!netif_carrier_ok(bond->dev)) {
 				netif_carrier_on(bond->dev);
@@ -526,7 +529,9 @@ static int bond_check_dev_link(struct bonding *bond,
  */
 static int bond_set_promiscuity(struct bonding *bond, int inc)
 {
+	struct list_head *iter;
 	int err = 0;
+
 	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
@@ -536,7 +541,7 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
 	} else {
 		struct slave *slave;
 
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			err = dev_set_promiscuity(slave->dev, inc);
 			if (err)
 				return err;
@@ -550,7 +555,9 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
  */
 static int bond_set_allmulti(struct bonding *bond, int inc)
 {
+	struct list_head *iter;
 	int err = 0;
+
 	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
@@ -560,7 +567,7 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
 	} else {
 		struct slave *slave;
 
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			err = dev_set_allmulti(slave->dev, inc);
 			if (err)
 				return err;
@@ -1051,9 +1058,10 @@ static void bond_poll_controller(struct net_device *bond_dev)
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct list_head *iter;
 	struct slave *slave;
 
-	bond_for_each_slave(bond, slave)
+	bond_for_each_slave(bond, slave, iter)
 		if (IS_UP(slave->dev))
 			slave_disable_netpoll(slave);
 }
@@ -1061,10 +1069,11 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
 static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp)
 {
 	struct bonding *bond = netdev_priv(dev);
+	struct list_head *iter;
 	struct slave *slave;
 	int err = 0;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		err = slave_enable_netpoll(slave);
 		if (err) {
 			bond_netpoll_cleanup(dev);
@@ -1091,8 +1100,9 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
 static netdev_features_t bond_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	struct slave *slave;
 	struct bonding *bond = netdev_priv(dev);
+	struct list_head *iter;
+	struct slave *slave;
 	netdev_features_t mask;
 
 	read_lock(&bond->lock);
@@ -1107,7 +1117,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	features &= ~NETIF_F_ONE_FOR_ALL;
 	features |= NETIF_F_ALL_FOR_ALL;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		features = netdev_increment_features(features,
 						     slave->dev->features,
 						     mask);
@@ -1125,9 +1135,10 @@ out:
 
 static void bond_compute_features(struct bonding *bond)
 {
-	struct slave *slave;
-	struct net_device *bond_dev = bond->dev;
 	netdev_features_t vlan_features = BOND_VLAN_FEATURES;
+	struct net_device *bond_dev = bond->dev;
+	struct list_head *iter;
+	struct slave *slave;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int gso_max_size = GSO_MAX_SIZE;
 	u16 gso_max_segs = GSO_MAX_SEGS;
@@ -1138,7 +1149,7 @@ static void bond_compute_features(struct bonding *bond)
 	if (!bond_has_slaves(bond))
 		goto done;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		vlan_features = netdev_increment_features(vlan_features,
 			slave->dev->vlan_features, BOND_VLAN_FEATURES);
 
@@ -1993,11 +2004,12 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
 static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct list_head *iter;
 	int i = 0, res = -ENODEV;
 	struct slave *slave;
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (i++ == (int)info->slave_id) {
 			res = 0;
 			strcpy(info->slave_name, slave->dev->name);
@@ -2018,12 +2030,13 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 static int bond_miimon_inspect(struct bonding *bond)
 {
 	int link_state, commit = 0;
+	struct list_head *iter;
 	struct slave *slave;
 	bool ignore_updelay;
 
 	ignore_updelay = !bond->curr_active_slave ? true : false;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		slave->new_link = BOND_LINK_NOCHANGE;
 
 		link_state = bond_check_dev_link(bond, slave->dev, 0);
@@ -2117,9 +2130,10 @@ static int bond_miimon_inspect(struct bonding *bond)
 
 static void bond_miimon_commit(struct bonding *bond)
 {
+	struct list_head *iter;
 	struct slave *slave;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		switch (slave->new_link) {
 		case BOND_LINK_NOCHANGE:
 			continue;
@@ -2515,6 +2529,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 	struct bonding *bond = container_of(work, struct bonding,
 					    arp_work.work);
 	struct slave *slave, *oldcurrent;
+	struct list_head *iter;
 	int do_failover = 0;
 
 	read_lock(&bond->lock);
@@ -2531,7 +2546,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 	 * TODO: what about up/down delay in arp mode? it wasn't here before
 	 *       so it can wait
 	 */
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		unsigned long trans_start = dev_trans_start(slave->dev);
 
 		if (slave->link != BOND_LINK_UP) {
@@ -2622,10 +2637,11 @@ re_arm:
 static int bond_ab_arp_inspect(struct bonding *bond)
 {
 	unsigned long trans_start, last_rx;
+	struct list_head *iter;
 	struct slave *slave;
 	int commit = 0;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		slave->new_link = BOND_LINK_NOCHANGE;
 		last_rx = slave_last_rx(bond, slave);
 
@@ -2692,9 +2708,10 @@ static int bond_ab_arp_inspect(struct bonding *bond)
 static void bond_ab_arp_commit(struct bonding *bond)
 {
 	unsigned long trans_start;
+	struct list_head *iter;
 	struct slave *slave;
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		switch (slave->new_link) {
 		case BOND_LINK_NOCHANGE:
 			continue;
@@ -3158,13 +3175,14 @@ static void bond_work_cancel_all(struct bonding *bond)
 static int bond_open(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct list_head *iter;
 	struct slave *slave;
 
 	/* reset slave->backup and slave->inactive */
 	read_lock(&bond->lock);
 	if (bond_has_slaves(bond)) {
 		read_lock(&bond->curr_slave_lock);
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
 				&& (slave != bond->curr_active_slave)) {
 				bond_set_slave_inactive_flags(slave);
@@ -3231,12 +3249,13 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct rtnl_link_stats64 temp;
+	struct list_head *iter;
 	struct slave *slave;
 
 	memset(stats, 0, sizeof(*stats));
 
 	read_lock_bh(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		const struct rtnl_link_stats64 *sstats =
 			dev_get_stats(slave->dev, &temp);
 
@@ -3403,6 +3422,7 @@ static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 static void bond_set_rx_mode(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct list_head *iter;
 	struct slave *slave;
 
 	ASSERT_RTNL();
@@ -3414,7 +3434,7 @@ static void bond_set_rx_mode(struct net_device *bond_dev)
 			dev_mc_sync(slave->dev, bond_dev);
 		}
 	} else {
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			dev_uc_sync_multiple(slave->dev, bond_dev);
 			dev_mc_sync_multiple(slave->dev, bond_dev);
 		}
@@ -3482,6 +3502,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave, *rollback_slave;
+	struct list_head *iter;
 	int res = 0;
 
 	pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
@@ -3502,7 +3523,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 	 * call to the base driver.
 	 */
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		pr_debug("s %p s->p %p c_m %p\n",
 			 slave,
 			 bond_prev_slave(bond, slave),
@@ -3530,7 +3551,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 
 unwind:
 	/* unwind from head to the slave that failed */
-	bond_for_each_slave(bond, rollback_slave) {
+	bond_for_each_slave(bond, rollback_slave, iter) {
 		int tmp_res;
 
 		if (rollback_slave == slave);
@@ -3558,6 +3579,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave, *rollback_slave;
 	struct sockaddr *sa = addr, tmp_sa;
+	struct list_head *iter;
 	int res = 0;
 
 	if (bond->params.mode == BOND_MODE_ALB)
@@ -3591,7 +3613,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 	 * call to the base driver.
 	 */
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
 		pr_debug("slave %p %s\n", slave, slave->dev->name);
 
@@ -3623,7 +3645,7 @@ unwind:
 	tmp_sa.sa_family = bond_dev->type;
 
 	/* unwind from head to the slave that failed */
-	bond_for_each_slave(bond, rollback_slave) {
+	bond_for_each_slave(bond, rollback_slave, iter) {
 		int tmp_res;
 
 		if (rollback_slave == slave)
@@ -3651,11 +3673,12 @@ unwind:
  */
 void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
 {
+	struct list_head *iter;
 	struct slave *slave;
 	int i = slave_id;
 
 	/* Here we start from the slave with slave_id */
-	bond_for_each_slave_rcu(bond, slave) {
+	bond_for_each_slave_rcu(bond, slave, iter) {
 		if (--i < 0) {
 			if (slave_can_tx(slave)) {
 				bond_dev_queue_xmit(bond, skb, slave->dev);
@@ -3666,7 +3689,7 @@ void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
 
 	/* Here we start from the first slave up to slave_id */
 	i = slave_id;
-	bond_for_each_slave_rcu(bond, slave) {
+	bond_for_each_slave_rcu(bond, slave, iter) {
 		if (--i < 0)
 			break;
 		if (slave_can_tx(slave)) {
@@ -3743,8 +3766,9 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave = NULL;
+	struct list_head *iter;
 
-	bond_for_each_slave_rcu(bond, slave) {
+	bond_for_each_slave_rcu(bond, slave, iter) {
 		if (bond_is_last_slave(bond, slave))
 			break;
 		if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
@@ -3793,13 +3817,14 @@ static inline int bond_slave_override(struct bonding *bond,
 {
 	struct slave *slave = NULL;
 	struct slave *check_slave;
+	struct list_head *iter;
 	int res = 1;
 
 	if (!skb->queue_mapping)
 		return 1;
 
 	/* Find out if any slaves have the same mapping as this skb. */
-	bond_for_each_slave_rcu(bond, check_slave) {
+	bond_for_each_slave_rcu(bond, check_slave, iter) {
 		if (check_slave->queue_id == skb->queue_mapping) {
 			slave = check_slave;
 			break;
@@ -3931,6 +3956,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	unsigned long speed = 0;
+	struct list_head *iter;
 	struct slave *slave;
 
 	ecmd->duplex = DUPLEX_UNKNOWN;
@@ -3942,7 +3968,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
 	 * this is an accurate maximum.
 	 */
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (SLAVE_IS_OK(slave)) {
 			if (slave->speed != SPEED_UNKNOWN)
 				speed += slave->speed;
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 20a6ee2..7af5646 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -10,8 +10,9 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 	__acquires(&bond->lock)
 {
 	struct bonding *bond = seq->private;
-	loff_t off = 0;
+	struct list_head *iter;
 	struct slave *slave;
+	loff_t off = 0;
 
 	/* make sure the bond won't be taken away */
 	rcu_read_lock();
@@ -20,7 +21,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	bond_for_each_slave(bond, slave)
+	bond_for_each_slave(bond, slave, iter)
 		if (++off == *pos)
 			return slave;
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 8721dcb..b4ae9f5 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -175,11 +175,12 @@ static ssize_t bonding_show_slaves(struct device *d,
 				   struct device_attribute *attr, char *buf)
 {
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	struct slave *slave;
 	int res = 0;
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (res > (PAGE_SIZE - IFNAMSIZ)) {
 			/* not enough space for another interface name */
 			if ((PAGE_SIZE - res) > 10)
@@ -602,6 +603,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 					 const char *buf, size_t count)
 {
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	struct slave *slave;
 	__be32 newtarget, *targets;
 	unsigned long *targets_rx;
@@ -634,7 +636,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 			 &newtarget);
 		/* not to race with bond_arp_rcv */
 		write_lock_bh(&bond->lock);
-		bond_for_each_slave(bond, slave)
+		bond_for_each_slave(bond, slave, iter)
 			slave->target_last_arp_rx[ind] = jiffies;
 		targets[ind] = newtarget;
 		write_unlock_bh(&bond->lock);
@@ -660,7 +662,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 			&newtarget);
 
 		write_lock_bh(&bond->lock);
-		bond_for_each_slave(bond, slave) {
+		bond_for_each_slave(bond, slave, iter) {
 			targets_rx = slave->target_last_arp_rx;
 			j = ind;
 			for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++)
@@ -1052,6 +1054,7 @@ static ssize_t bonding_store_primary(struct device *d,
 				     const char *buf, size_t count)
 {
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	char ifname[IFNAMSIZ];
 	struct slave *slave;
 
@@ -1079,7 +1082,7 @@ static ssize_t bonding_store_primary(struct device *d,
 		goto out;
 	}
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
 			pr_info("%s: Setting %s as primary slave.\n",
 				bond->dev->name, slave->dev->name);
@@ -1227,6 +1230,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
 {
 	struct slave *slave, *old_active, *new_active;
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	char ifname[IFNAMSIZ];
 
 	if (!rtnl_trylock())
@@ -1254,7 +1258,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
 		goto out;
 	}
 
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
 			old_active = bond->curr_active_slave;
 			new_active = slave;
@@ -1434,6 +1438,7 @@ static ssize_t bonding_show_queue_id(struct device *d,
 				     char *buf)
 {
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	struct slave *slave;
 	int res = 0;
 
@@ -1441,7 +1446,7 @@ static ssize_t bonding_show_queue_id(struct device *d,
 		return restart_syscall();
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
 			/* not enough space for another interface_name:queue_id pair */
 			if ((PAGE_SIZE - res) > 10)
@@ -1470,6 +1475,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
 {
 	struct slave *slave, *update_slave;
 	struct bonding *bond = to_bond(d);
+	struct list_head *iter;
 	u16 qid;
 	int ret = count;
 	char *delim;
@@ -1506,7 +1512,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
 
 	/* Search for thes slave and check for duplicate qids */
 	update_slave = NULL;
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (sdev == slave->dev)
 			/*
 			 * We don't need to check the matching
@@ -1560,6 +1566,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
 {
 	struct bonding *bond = to_bond(d);
 	int new_value, ret = count;
+	struct list_head *iter;
 	struct slave *slave;
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
@@ -1582,7 +1589,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
 	}
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave) {
+	bond_for_each_slave(bond, slave, iter) {
 		if (!bond_is_active_slave(slave)) {
 			if (new_value)
 				slave->inactive = 0;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 8c11f96..b6dc9db 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -112,15 +112,16 @@
  * bond_for_each_slave - iterate over all slaves
  * @bond:	the bond holding this list
  * @pos:	current slave
+ * @iter:	list_head * iterator
  *
  * Caller must hold bond->lock
  */
-#define bond_for_each_slave(bond, pos) \
-	list_for_each_entry(pos, &(bond)->slave_list, list)
+#define bond_for_each_slave(bond, pos, iter) \
+	netdev_for_each_lower_neigh_private((bond)->dev, pos, iter)
 
 /* Caller must have rcu_read_lock */
-#define bond_for_each_slave_rcu(bond, pos) \
-	list_for_each_entry_rcu(pos, &(bond)->slave_list, list)
+#define bond_for_each_slave_rcu(bond, pos, iter) \
+	netdev_for_each_lower_neigh_private_rcu((bond)->dev, pos, iter)
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 extern atomic_t netpoll_block_tx;
@@ -493,9 +494,10 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
 static inline struct slave *bond_slave_has_mac(struct bonding *bond,
 					       const u8 *mac)
 {
+	struct list_head *iter;
 	struct slave *tmp;
 
-	bond_for_each_slave(bond, tmp)
+	bond_for_each_slave(bond, tmp, iter)
 		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
 			return tmp;
 
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 10/21] bonding: modify bond_get_slave_by_dev() to use neighbours
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

It should be used under rtnl/bonding lock, so use the non-RCU version.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bonding.h | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 37055cd..7cb60f9 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -295,13 +295,8 @@ static inline bool bond_vlan_used(struct bonding *bond)
 static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
 						  struct net_device *slave_dev)
 {
-	struct slave *slave = NULL;
-
-	bond_for_each_slave(bond, slave)
-		if (slave->dev == slave_dev)
-			return slave;
-
-	return NULL;
+	return (struct slave *)netdev_lower_dev_get_private(bond->dev,
+							    slave_dev);
 }
 
 static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
-- 
1.8.4

^ permalink raw reply related

* [PATCH RFC net-next 17/21] bonding: convert first/last slave logic to use neighbours
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
  To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>

For that, use netdev_adjacent_get_private(list_head) on bond's lower
neighbour list members.

CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
 drivers/net/bonding/bonding.h | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 583077d..6731281 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -72,19 +72,24 @@
 	res; })
 
 /* slave list primitives */
-#define bond_has_slaves(bond) !list_empty(&(bond)->dev->neighbour_dev_list.lower)
+#define bond_slave_list(bond) (&(bond)->dev->neighbour_dev_list.lower)
+
+#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))
 
 #define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
 
 /* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
 #define bond_first_slave(bond) \
-	list_first_entry_or_null(&(bond)->slave_list, struct slave, list)
+	(bond_has_slaves(bond) ? \
+		netdev_adjacent_get_private(bond_slave_list(bond)->next) : \
+		NULL)
 #define bond_last_slave(bond) \
-	(list_empty(&(bond)->slave_list) ? NULL : \
-					   bond_to_slave((bond)->slave_list.prev))
+	(bond_has_slaves(bond) ? \
+		netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \
+		NULL)
 
-#define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list)
-#define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list)
+#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond))
+#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
 
 /* Since bond_first/last_slave can return NULL, these can return NULL too */
 #define bond_next_slave(bond, pos) \
-- 
1.8.4

^ permalink raw reply related

* [PATCH] sh_eth: NAPI requires netif_receive_skb()
From: Sergei Shtylyov @ 2013-09-02 23:03 UTC (permalink / raw)
  To: netdev; +Cc: nobuhiro.iwamatsu.yj, linux-sh

Driver supporting NAPI should use NAPI-specific function for receiving packets,
so netif_rx() should be changed to netif_receive_skb().

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
This patch is against Dave's 'net-next.git' repo (it also applies to 'net.git'
with offset). Perhaps it should  be backported to 3.11 once it is out...

 drivers/net/ethernet/renesas/sh_eth.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: net-next/drivers/net/ethernet/renesas/sh_eth.c
===================================================================
--- net-next.orig/drivers/net/ethernet/renesas/sh_eth.c
+++ net-next/drivers/net/ethernet/renesas/sh_eth.c
@@ -1347,7 +1347,7 @@ static int sh_eth_rx(struct net_device *
 				skb_reserve(skb, NET_IP_ALIGN);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, ndev);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			ndev->stats.rx_packets++;
 			ndev->stats.rx_bytes += pkt_len;
 		}

^ permalink raw reply

* [PATCH V2] net: netx-eth: remove unnecessary casting
From: Jingoo Han @ 2013-09-02 23:54 UTC (permalink / raw)
  To: 'David S. Miller'
  Cc: netdev, 'Sergei Shtylyov', 'Jingoo Han'
In-Reply-To: <004b01cea774$975b48b0$c611da10$%han@samsung.com>

Casting from 'void *' is unnecessary, because casting from 'void *'
to any pointer type is automatic.

Reported-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/net/ethernet/netx-eth.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index 235fd51..e6f0a43 100644
--- a/drivers/net/ethernet/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -390,7 +390,7 @@ static int netx_eth_drv_probe(struct platform_device *pdev)
 
 	priv = netdev_priv(ndev);
 
-	pdata = (struct netxeth_platform_data *)dev_get_platdata(&pdev->dev);
+	pdata = dev_get_platdata(&pdev->dev);
 	priv->xc = request_xc(pdata->xcno, &pdev->dev);
 	if (!priv->xc) {
 		dev_err(&pdev->dev, "unable to request xc engine\n");
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] ibmveth: Fix little endian issues
From: Anton Blanchard @ 2013-09-02 23:55 UTC (permalink / raw)
  To: santil, netdev


The hypervisor is big endian, so little endian kernel builds need
to byteswap.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 70fd559..5d41aee 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -106,7 +106,7 @@ struct ibmveth_stat ibmveth_stats[] = {
 /* simple methods of getting data from the current rxq entry */
 static inline u32 ibmveth_rxq_flags(struct ibmveth_adapter *adapter)
 {
-	return adapter->rx_queue.queue_addr[adapter->rx_queue.index].flags_off;
+	return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].flags_off);
 }
 
 static inline int ibmveth_rxq_toggle(struct ibmveth_adapter *adapter)
@@ -132,7 +132,7 @@ static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
 
 static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
 {
-	return adapter->rx_queue.queue_addr[adapter->rx_queue.index].length;
+	return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
 }
 
 static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
index 43a794f..84066ba 100644
--- a/drivers/net/ethernet/ibm/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
@@ -164,14 +164,26 @@ struct ibmveth_adapter {
     u64 tx_send_failed;
 };
 
+/*
+ * We pass struct ibmveth_buf_desc_fields to the hypervisor in registers,
+ * so we don't need to byteswap the two elements. However since we use
+ * a union (ibmveth_buf_desc) to convert from the struct to a u64 we
+ * do end up with endian specific ordering of the elements and that
+ * needs correcting.
+ */
 struct ibmveth_buf_desc_fields {
+#ifdef __BIG_ENDIAN
+	u32 flags_len;
+	u32 address;
+#else
+	u32 address;
 	u32 flags_len;
+#endif
 #define IBMVETH_BUF_VALID	0x80000000
 #define IBMVETH_BUF_TOGGLE	0x40000000
 #define IBMVETH_BUF_NO_CSUM	0x02000000
 #define IBMVETH_BUF_CSUM_GOOD	0x01000000
 #define IBMVETH_BUF_LEN_MASK	0x00FFFFFF
-	u32 address;
 };
 
 union ibmveth_buf_desc {
@@ -180,7 +192,7 @@ union ibmveth_buf_desc {
 };
 
 struct ibmveth_rx_q_entry {
-	u32 flags_off;
+	__be32 flags_off;
 #define IBMVETH_RXQ_TOGGLE		0x80000000
 #define IBMVETH_RXQ_TOGGLE_SHIFT	31
 #define IBMVETH_RXQ_VALID		0x40000000
@@ -188,7 +200,8 @@ struct ibmveth_rx_q_entry {
 #define IBMVETH_RXQ_CSUM_GOOD		0x01000000
 #define IBMVETH_RXQ_OFF_MASK		0x0000FFFF
 
-	u32 length;
+	__be32 length;
+	/* correlator is only used by the OS, no need to byte swap */
 	u64 correlator;
 };
 

^ permalink raw reply related

* [PATCH] ipv6: fix null pointer dereference in __ip6addrlbl_add
From: Hannes Frederic Sowa @ 2013-09-03  0:13 UTC (permalink / raw)
  To: Michele Baldessari
  Cc: netdev, Hideaki YOSHIFUJI, David S. Miller, Sasha Levin
In-Reply-To: <20130902213128.GB14301@marquez.int.rhx>

Hi!

On Mon, Sep 02, 2013 at 10:31:28PM +0100, Michele Baldessari wrote:
> with the latest linux master git tree from Linus
> (248d296d6d9df384996c2ed95676b367d876d48c - 2 Sep) I can reproduceably oops 
> the kernel with the following commands:
> ip addrlabel flush
> ip addrlabel add prefix ::1/128              label 0
> ip addrlabel add prefix ::/0                 label 1

Thanks for the report! This patch should fix this issue:

[PATCH] ipv6: fix null pointer dereference in __ip6addrlbl_add

Commit b67bfe0d42cac56c512dd5da4b1b347a23f4b70a ("hlist: drop
the node parameter from iterators") changed the behavior of
hlist_for_each_entry_safe to leave the p argument NULL.

Fix this up by tracking the last argument.

Reported-by: Michele Baldessari <michele@acksyn.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 net/ipv6/addrlabel.c | 48 +++++++++++++++++++++++-------------------------
 1 file changed, 23 insertions(+), 25 deletions(-)

diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index f083a58..b30ad37 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -251,38 +251,36 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
 /* add a label */
 static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
 {
+	struct hlist_node *n;
+	struct ip6addrlbl_entry *last = NULL, *p = NULL;
 	int ret = 0;
 
-	ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n",
-			__func__,
-			newp, replace);
+	ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp,
+		  replace);
 
-	if (hlist_empty(&ip6addrlbl_table.head)) {
-		hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
-	} else {
-		struct hlist_node *n;
-		struct ip6addrlbl_entry *p = NULL;
-		hlist_for_each_entry_safe(p, n,
-					  &ip6addrlbl_table.head, list) {
-			if (p->prefixlen == newp->prefixlen &&
-			    net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
-			    p->ifindex == newp->ifindex &&
-			    ipv6_addr_equal(&p->prefix, &newp->prefix)) {
-				if (!replace) {
-					ret = -EEXIST;
-					goto out;
-				}
-				hlist_replace_rcu(&p->list, &newp->list);
-				ip6addrlbl_put(p);
-				goto out;
-			} else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
-				   (p->prefixlen < newp->prefixlen)) {
-				hlist_add_before_rcu(&newp->list, &p->list);
+	hlist_for_each_entry_safe(p, n,	&ip6addrlbl_table.head, list) {
+		if (p->prefixlen == newp->prefixlen &&
+		    net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
+		    p->ifindex == newp->ifindex &&
+		    ipv6_addr_equal(&p->prefix, &newp->prefix)) {
+			if (!replace) {
+				ret = -EEXIST;
 				goto out;
 			}
+			hlist_replace_rcu(&p->list, &newp->list);
+			ip6addrlbl_put(p);
+			goto out;
+		} else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
+			   (p->prefixlen < newp->prefixlen)) {
+			hlist_add_before_rcu(&newp->list, &p->list);
+			goto out;
 		}
-		hlist_add_after_rcu(&p->list, &newp->list);
+		last = p;
 	}
+	if (last)
+		hlist_add_after_rcu(&last->list, &newp->list);
+	else
+		hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
 out:
 	if (!ret)
 		ip6addrlbl_table.seq++;
-- 
1.8.3.1

^ permalink raw reply related

* Re: Is fallback vhost_net to qemu for live migrate available?
From: Qin Chuanyu @ 2013-09-03  1:28 UTC (permalink / raw)
  To: Wei Liu
  Cc: Anthony Liguori, Michael S. Tsirkin, jasowang, KVM list, netdev,
	qianhuibin, xen-devel@lists.xen.org, wangfuhai, likunyun,
	liuyongan, liuyingdong
In-Reply-To: <20130902075722.GZ15729@zion.uk.xensource.com>

On 2013/9/2 15:57, Wei Liu wrote:
> On Sat, Aug 31, 2013 at 12:45:11PM +0800, Qin Chuanyu wrote:
>> On 2013/8/30 0:08, Anthony Liguori wrote:
>>> Hi Qin,
>>
>>>> By change the memory copy and notify mechanism ,currently virtio-net with
>>>> vhost_net could run on Xen with good performance。
>>>
>>> I think the key in doing this would be to implement a property
>>> ioeventfd and irqfd interface in the driver domain kernel.  Just
>>> hacking vhost_net with Xen specific knowledge would be pretty nasty
>>> IMHO.
>>>
>> Yes, I add a kernel module which persist virtio-net pio_addr and
>> msix address as what kvm module did. Guest wake up vhost thread by
>> adding a hook func in evtchn_interrupt.
>>
>>> Did you modify the front end driver to do grant table mapping or is
>>> this all being done by mapping the domain's memory?
>>>
>> There is nothing changed in front end driver. Currently I use
>> alloc_vm_area to get address space, and map the domain's memory as
>> what what qemu did.
>>
>
> You mean you're using xc_map_foreign_range and friends in the backend to
> map guest memory? That's not very desirable as it violates Xen's
> security model. It would not be too hard to pass grant references
> instead of guest physical memory address IMHO.
>
In fact, I did what virtio-net have done in Qemu. I think security
is a pseudo question because Dom0 is under control.

Host could access memory of guest in KVM much easier than Xen,
but I hadn't heard someone said KVM is un-secret.

Regards
Qin chuanyu

^ permalink raw reply

* RE: [PATCH] net: fec: fix the error to get the previous BD entry
From: Duan Fugang-B38611 @ 2013-09-03  1:39 UTC (permalink / raw)
  To: Li Frank-B20596, davem@davemloft.net
  Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
	stephen@networkplumber.org
In-Reply-To: <1F990F8245A4214A8CC4BFFBD9F790F908B45674@039-SN1MPN1-001.039d.mgd.msft.net>

From: Li Frank-B20596
Data: Monday, September 02, 2013 10:30 PM

> To: Duan Fugang-B38611; davem@davemloft.net
> Cc: netdev@vger.kernel.org; bhutchings@solarflare.com;
> stephen@networkplumber.org
> Subject: RE: [PATCH] net: fec: fix the error to get the previous BD entry
> 
> 
> 
> > -----Original Message-----
> > From: Duan Fugang-B38611
> > Sent: Monday, September 02, 2013 6:36 AM
> > To: Li Frank-B20596; davem@davemloft.net
> > Cc: netdev@vger.kernel.org; bhutchings@solarflare.com;
> > stephen@networkplumber.org
> > Subject: [PATCH] net: fec: fix the error to get the previous BD entry
> >
> > Bug: error to get the previous BD entry. When the current BD is the
> > first BD, the previous BD entry must be the last BD, not "bdp - 1" in
> current logic.
> >
> > V2:
> >   Add tx_ring_size and rx_ring_size to struct fec_enet_private.
> >   Replace api fec_enet_get_nextdesc() with next_bd().
> >   Replace api fec_enet_get_prevdesc() with pre_bd().
> >
> >   Move all ring size check logic to next_bd() and pre_bd, which
> >   simplifies the code redundancy.
> >
> > V1:
> >   Add BD ring size check to get the previous BD entry in correctly.
> >
> > Signed-off-by: Fugang Duan  <B38611@freescale.com>
> > ---
> >  drivers/net/ethernet/freescale/fec.h      |    3 +
> >  drivers/net/ethernet/freescale/fec_main.c |   94 +++++++++++++++-------
> -----
> > -
> >  2 files changed, 53 insertions(+), 44 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/fec.h
> > b/drivers/net/ethernet/freescale/fec.h
> > index ae23600..0120217 100644
> > --- a/drivers/net/ethernet/freescale/fec.h
> > +++ b/drivers/net/ethernet/freescale/fec.h
> > @@ -296,6 +296,9 @@ struct fec_enet_private {
> >  	/* The ring entries to be free()ed */
> >  	struct bufdesc	*dirty_tx;
> >
> > +	unsigned short tx_ring_size;
> > +	unsigned short rx_ring_size;
> > +
> >  	struct	platform_device *pdev;
> >
> >  	int	opened;
> > diff --git a/drivers/net/ethernet/freescale/fec_main.c
> > b/drivers/net/ethernet/freescale/fec_main.c
> > index 4ea1555..9894dd3 100644
> > --- a/drivers/net/ethernet/freescale/fec_main.c
> > +++ b/drivers/net/ethernet/freescale/fec_main.c
> > @@ -239,22 +239,35 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC
> > address");
> >
> >  static int mii_cnt;
> >
> > -static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int
> > is_ex)
> > +static inline
> > +struct bufdesc *next_bd(struct bufdesc *bdp, struct bufdesc *base,
> > +			int ring_size, int is_ex)
> 
> David suggest use fec_enet_ prefix for all function in fec driver when I
> upstream it.
> 
> 
> How about use
> 	Fec_enet_next_bd(struct bufdesc *bdp, *fep)
> 	The parameter will become little and easy to call.
> 
> >  {
> > -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> > +	struct bufdesc *new_bd = bdp + 1;
> > +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
> > +	struct bufdesc_ex *ex_base = (struct bufdesc_ex *)base;
> > +
> 
> If pass down fep,
> 	If( bdp > fep->rx_base) {
> 		Ex_base = fep->rx_base;
> 		Ring_size = fep->rx_ring_size;
> 	}
> 	Else {
> 		Ex_base = fep->tx_base.
> 		Ring_size = fep->tx_ring_size;
> 	}
> 
> Because RX always behind of TX.
> 

Good idea, I will send patch V3.  Thanks.

^ permalink raw reply

* Re: [PATCH net-next 0/5] bonding: locking simplifications and cleanup
From: Ding Tianhong @ 2013-09-03  1:48 UTC (permalink / raw)
  To: Nikolay Aleksandrov; +Cc: netdev, andy, fubar, davem
In-Reply-To: <1378122702-28943-1-git-send-email-nikolay@redhat.com>

On 2013/9/2 19:51, Nikolay Aleksandrov wrote:
> Hello,
> This small patchset aims to remove some use cases of bond->lock for mutual
> exclusion which will help in the RCUfication of the function users. It also
> does some small style cleanups and fixes.
> 
> Patch 01 - Drops the use of bond->lock as mutual exclusion for peer
> notification and relies on RTNL being held when send_peer_notif is modified
> Patch 02 - trivial outdated comment removal
> Patch 03 - Drops the use of bond->lock as mutual exclusion for lacp rate
> update and relies on RTNL, also fixes possible races with mode change
> Patch 04 - Drops read_lock in bond_fix_features because RTNL is held
> Patch 05 - Drops read_lock in bond_compute_features because RTNL is held
> whenever it's called
> 
> Best regards,
>  Nikolay Aleksandrov
> 
> Nikolay Aleksandrov (5):
>   bonding: simplify and fix peer notification
>   bonding: trivial: remove outdated comment and braces
>   bonding: simplify bond_3ad_update_lacp_rate and use RTNL for sync
>   bonding: drop read_lock in bond_fix_features
>   bonding: drop read_lock in bond_compute_features
> 
>  drivers/net/bonding/bond_3ad.c   |  8 +------
>  drivers/net/bonding/bond_main.c  | 48 ++++++++++++----------------------------
>  drivers/net/bonding/bond_sysfs.c |  7 +++++-
>  3 files changed, 21 insertions(+), 42 deletions(-)
> 

Reviewed-by: Ding Tianhong <dingtianhong@huawei.com>

^ permalink raw reply

* [PATCH] net: fec: fix the error to get the previous BD entry
From: Fugang Duan @ 2013-09-03  2:18 UTC (permalink / raw)
  To: b20596, davem; +Cc: netdev, bhutchings, stephen

Bug: error to get the previous BD entry. When the current BD
is the first BD, the previous BD entry must be the last BD,
not "bdp - 1" in current logic.

V3:
  * Restore the API name because David suggest to use fec_enet_
    prefix for all function in fec driver.
    So, change next_bd() -> fec_enet_get_nextdesc()
        change pre_bd()  -> fec_enet_get_prevdesc()
  * Reduce the two APIs parameters for easy to call.

V2:
  * Add tx_ring_size and rx_ring_size to struct fec_enet_private.
  * Replace api fec_enet_get_nextdesc() with next_bd().
    Replace api fec_enet_get_prevdesc() with pre_bd().

  * Move all ring size check logic to next_bd() and pre_bd(), which
    simplifies the code redundancy.

V1:
  * Add BD ring size check to get the previous BD entry in correctly.

Reviewed-by: Li Frank <B20596@freescale.com>
Signed-off-by: Fugang Duan  <B38611@freescale.com>
---
 drivers/net/ethernet/freescale/fec.h      |    3 +
 drivers/net/ethernet/freescale/fec_main.c |  120 ++++++++++++++++++-----------
 2 files changed, 77 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index ae23600..0120217 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -296,6 +296,9 @@ struct fec_enet_private {
 	/* The ring entries to be free()ed */
 	struct bufdesc	*dirty_tx;
 
+	unsigned short tx_ring_size;
+	unsigned short rx_ring_size;
+
 	struct	platform_device *pdev;
 
 	int	opened;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 4ea1555..d5d8984 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -239,22 +239,57 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 
 static int mii_cnt;
 
-static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
+static inline
+struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
 {
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex + 1);
+	struct bufdesc *new_bd = bdp + 1;
+	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
+	struct bufdesc_ex *ex_base;
+	struct bufdesc *base;
+	int ring_size;
+
+	if (bdp >= fep->tx_bd_base) {
+		base = fep->tx_bd_base;
+		ring_size = fep->tx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
+	} else {
+		base = fep->rx_bd_base;
+		ring_size = fep->rx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
+	}
+
+	if (fep->bufdesc_ex)
+		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
+			(ex_new_bd - ring_size) : ex_new_bd);
 	else
-		return bdp + 1;
+		return (new_bd >= (base + ring_size)) ?
+			(new_bd - ring_size) : new_bd;
 }
 
-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
+static inline
+struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
 {
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex - 1);
+	struct bufdesc *new_bd = bdp - 1;
+	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
+	struct bufdesc_ex *ex_base;
+	struct bufdesc *base;
+	int ring_size;
+
+	if (bdp >= fep->tx_bd_base) {
+		base = fep->tx_bd_base;
+		ring_size = fep->tx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
+	} else {
+		base = fep->rx_bd_base;
+		ring_size = fep->rx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
+	}
+
+	if (fep->bufdesc_ex)
+		return (struct bufdesc *)((ex_new_bd < ex_base) ?
+			(ex_new_bd + ring_size) : ex_new_bd);
 	else
-		return bdp - 1;
+		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
 }
 
 static void *swap_buffer(void *bufaddr, int len)
@@ -380,7 +415,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		}
 	}
 
-	bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
 	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
 	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
 		fep->delay_work.trig_tx = true;
@@ -389,10 +424,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	}
 
 	/* If this was the last BD in the ring, start at the beginning again. */
-	if (status & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_nextdesc(bdp, fep);
 
 	fep->cur_tx = bdp;
 
@@ -417,18 +449,18 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 
 		/* Initialize the BD for every fragment in the page. */
 		if (bdp->cbd_bufaddr)
 			bdp->cbd_sc = BD_ENET_RX_EMPTY;
 		else
 			bdp->cbd_sc = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	fep->cur_rx = fep->rx_bd_base;
@@ -436,7 +468,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 	/* ...and the same for transmit */
 	bdp = fep->tx_bd_base;
 	fep->cur_tx = bdp;
-	for (i = 0; i < TX_RING_SIZE; i++) {
+	for (i = 0; i < fep->tx_ring_size; i++) {
 
 		/* Initialize the BD for every fragment in the page. */
 		bdp->cbd_sc = 0;
@@ -445,11 +477,11 @@ static void fec_enet_bd_init(struct net_device *dev)
 			fep->tx_skbuff[i] = NULL;
 		}
 		bdp->cbd_bufaddr = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 	fep->dirty_tx = bdp;
 }
@@ -510,10 +542,10 @@ fec_restart(struct net_device *ndev, int duplex)
 	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
 	if (fep->bufdesc_ex)
 		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
-			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
+			* fep->rx_ring_size, fep->hwp + FEC_X_DES_START);
 	else
 		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
-			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
+			* fep->rx_ring_size,	fep->hwp + FEC_X_DES_START);
 
 
 	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
@@ -727,10 +759,7 @@ fec_enet_tx(struct net_device *ndev)
 	bdp = fep->dirty_tx;
 
 	/* get next bdp of dirty_tx */
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_nextdesc(bdp, fep);
 
 	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
 
@@ -800,10 +829,7 @@ fec_enet_tx(struct net_device *ndev)
 		fep->dirty_tx = bdp;
 
 		/* Update pointer to next buffer descriptor to be transmitted */
-		if (status & BD_ENET_TX_WRAP)
-			bdp = fep->tx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
@@ -994,10 +1020,8 @@ rx_processing_done:
 		}
 
 		/* Update BD pointer to next entry */
-		if (status & BD_ENET_RX_WRAP)
-			bdp = fep->rx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
+
 		/* Doing this here will keep the FEC running while we process
 		 * incoming frames.  On a heavily loaded network, we should be
 		 * able to keep up at the expense of system resources.
@@ -1663,7 +1687,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 	struct bufdesc	*bdp;
 
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 		skb = fep->rx_skbuff[i];
 
 		if (bdp->cbd_bufaddr)
@@ -1671,11 +1695,11 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		if (skb)
 			dev_kfree_skb(skb);
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++)
+	for (i = 0; i < fep->tx_ring_size; i++)
 		kfree(fep->tx_bounce[i]);
 }
 
@@ -1687,7 +1711,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 	struct bufdesc	*bdp;
 
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
 		if (!skb) {
 			fec_enet_free_buffers(ndev);
@@ -1704,15 +1728,15 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++) {
+	for (i = 0; i < fep->tx_ring_size; i++) {
 		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
 
 		bdp->cbd_sc = 0;
@@ -1723,11 +1747,11 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	return 0;
@@ -1967,13 +1991,17 @@ static int fec_enet_init(struct net_device *ndev)
 	/* Get the Ethernet address */
 	fec_get_mac(ndev);
 
+	/* init the tx & rx ring size */
+	fep->tx_ring_size = TX_RING_SIZE;
+	fep->rx_ring_size = RX_RING_SIZE;
+
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	if (fep->bufdesc_ex)
 		fep->tx_bd_base = (struct bufdesc *)
-			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
+			(((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size);
 	else
-		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+		fep->tx_bd_base = cbd_base + fep->rx_ring_size;
 
 	/* The FEC Ethernet specific entries in the device structure */
 	ndev->watchdog_timeo = TX_TIMEOUT;
-- 
1.7.1

^ permalink raw reply related

* RE: [PATCH] net: fec: fix the error to get the previous BD entry
From: Li Frank-B20596 @ 2013-09-03  2:33 UTC (permalink / raw)
  To: Duan Fugang-B38611, davem@davemloft.net
  Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
	stephen@networkplumber.org
In-Reply-To: <1378174690-20316-1-git-send-email-B38611@freescale.com>


> Bug: error to get the previous BD entry. When the current BD is the first BD,
> the previous BD entry must be the last BD, not "bdp - 1" in current logic.
> 
> V3:
>   * Restore the API name because David suggest to use fec_enet_
>     prefix for all function in fec driver.
>     So, change next_bd() -> fec_enet_get_nextdesc()
>         change pre_bd()  -> fec_enet_get_prevdesc()
>   * Reduce the two APIs parameters for easy to call.
> 
> V2:
>   * Add tx_ring_size and rx_ring_size to struct fec_enet_private.
>   * Replace api fec_enet_get_nextdesc() with next_bd().
>     Replace api fec_enet_get_prevdesc() with pre_bd().
> 
>   * Move all ring size check logic to next_bd() and pre_bd(), which
>     simplifies the code redundancy.
> 
> V1:
>   * Add BD ring size check to get the previous BD entry in correctly.
> 
> Reviewed-by: Li Frank <B20596@freescale.com>
> Signed-off-by: Fugang Duan  <B38611@freescale.com>
> ---
>  drivers/net/ethernet/freescale/fec.h      |    3 +
>  drivers/net/ethernet/freescale/fec_main.c |  120 ++++++++++++++++++---------
> --
>  2 files changed, 77 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/fec.h
> b/drivers/net/ethernet/freescale/fec.h
> index ae23600..0120217 100644
> --- a/drivers/net/ethernet/freescale/fec.h
> +++ b/drivers/net/ethernet/freescale/fec.h
> @@ -296,6 +296,9 @@ struct fec_enet_private {
>  	/* The ring entries to be free()ed */
>  	struct bufdesc	*dirty_tx;
> 
> +	unsigned short tx_ring_size;
> +	unsigned short rx_ring_size;
> +
>  	struct	platform_device *pdev;
> 
>  	int	opened;
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 4ea1555..d5d8984 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -239,22 +239,57 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
> 
>  static int mii_cnt;
> 
> -static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
> +static inline
> +struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct
> +fec_enet_private *fep)
>  {
> -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> -	if (is_ex)
> -		return (struct bufdesc *)(ex + 1);
> +	struct bufdesc *new_bd = bdp + 1;
> +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
> +	struct bufdesc_ex *ex_base;
> +	struct bufdesc *base;
> +	int ring_size;
> +
> +	if (bdp >= fep->tx_bd_base) {
> +		base = fep->tx_bd_base;
> +		ring_size = fep->tx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
> +	} else {
> +		base = fep->rx_bd_base;
> +		ring_size = fep->rx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
> +	}
> +
> +	if (fep->bufdesc_ex)
> +		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
> +			(ex_new_bd - ring_size) : ex_new_bd);

I think  "exbase:ex_new_bd" is better

>  	else
> -		return bdp + 1;
> +		return (new_bd >= (base + ring_size)) ?
> +			(new_bd - ring_size) : new_bd;

I think "base:new_bd" is better.

>  }
> 
> -static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
> +static inline
> +struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct
> +fec_enet_private *fep)
>  {
> -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> -	if (is_ex)
> -		return (struct bufdesc *)(ex - 1);
> +	struct bufdesc *new_bd = bdp - 1;
> +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
> +	struct bufdesc_ex *ex_base;
> +	struct bufdesc *base;
> +	int ring_size;
> +
> +	if (bdp >= fep->tx_bd_base) {
> +		base = fep->tx_bd_base;
> +		ring_size = fep->tx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
> +	} else {
> +		base = fep->rx_bd_base;
> +		ring_size = fep->rx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
> +	}
> +
> +	if (fep->bufdesc_ex)
> +		return (struct bufdesc *)((ex_new_bd < ex_base) ?
> +			(ex_new_bd + ring_size) : ex_new_bd);
>  	else
> -		return bdp - 1;
> +		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
>  }
> 
>  static void *swap_buffer(void *bufaddr, int len) @@ -380,7 +415,7 @@
> fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>  		}
>  	}
> 
> -	bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
>  	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
>  	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
>  		fep->delay_work.trig_tx = true;
> @@ -389,10 +424,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct
> net_device *ndev)
>  	}
> 
>  	/* If this was the last BD in the ring, start at the beginning again.
> */
> -	if (status & BD_ENET_TX_WRAP)
> -		bdp = fep->tx_bd_base;
> -	else
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  	fep->cur_tx = bdp;
> 
> @@ -417,18 +449,18 @@ static void fec_enet_bd_init(struct net_device *dev)
> 
>  	/* Initialize the receive buffer descriptors. */
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
> 
>  		/* Initialize the BD for every fragment in the page. */
>  		if (bdp->cbd_bufaddr)
>  			bdp->cbd_sc = BD_ENET_RX_EMPTY;
>  		else
>  			bdp->cbd_sc = 0;
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	fep->cur_rx = fep->rx_bd_base;
> @@ -436,7 +468,7 @@ static void fec_enet_bd_init(struct net_device *dev)
>  	/* ...and the same for transmit */
>  	bdp = fep->tx_bd_base;
>  	fep->cur_tx = bdp;
> -	for (i = 0; i < TX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->tx_ring_size; i++) {
> 
>  		/* Initialize the BD for every fragment in the page. */
>  		bdp->cbd_sc = 0;
> @@ -445,11 +477,11 @@ static void fec_enet_bd_init(struct net_device *dev)
>  			fep->tx_skbuff[i] = NULL;
>  		}
>  		bdp->cbd_bufaddr = 0;
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
>  	fep->dirty_tx = bdp;
>  }
> @@ -510,10 +542,10 @@ fec_restart(struct net_device *ndev, int duplex)
>  	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
>  	if (fep->bufdesc_ex)
>  		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
> -			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
> +			* fep->rx_ring_size, fep->hwp + FEC_X_DES_START);
>  	else
>  		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
> -			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
> +			* fep->rx_ring_size,	fep->hwp + FEC_X_DES_START);
> 
> 
>  	for (i = 0; i <= TX_RING_MOD_MASK; i++) { @@ -727,10 +759,7 @@
> fec_enet_tx(struct net_device *ndev)
>  	bdp = fep->dirty_tx;
> 
>  	/* get next bdp of dirty_tx */
> -	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
> -		bdp = fep->tx_bd_base;
> -	else
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
> 
> @@ -800,10 +829,7 @@ fec_enet_tx(struct net_device *ndev)
>  		fep->dirty_tx = bdp;
> 
>  		/* Update pointer to next buffer descriptor to be transmitted */
> -		if (status & BD_ENET_TX_WRAP)
> -			bdp = fep->tx_bd_base;
> -		else
> -			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  		/* Since we have freed up a buffer, the ring is no longer full
>  		 */
> @@ -994,10 +1020,8 @@ rx_processing_done:
>  		}
> 
>  		/* Update BD pointer to next entry */
> -		if (status & BD_ENET_RX_WRAP)
> -			bdp = fep->rx_bd_base;
> -		else
> -			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
> +
>  		/* Doing this here will keep the FEC running while we process
>  		 * incoming frames.  On a heavily loaded network, we should be
>  		 * able to keep up at the expense of system resources.
> @@ -1663,7 +1687,7 @@ static void fec_enet_free_buffers(struct net_device
> *ndev)
>  	struct bufdesc	*bdp;
> 
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
>  		skb = fep->rx_skbuff[i];
> 
>  		if (bdp->cbd_bufaddr)
> @@ -1671,11 +1695,11 @@ static void fec_enet_free_buffers(struct net_device
> *ndev)
>  					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
>  		if (skb)
>  			dev_kfree_skb(skb);
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	bdp = fep->tx_bd_base;
> -	for (i = 0; i < TX_RING_SIZE; i++)
> +	for (i = 0; i < fep->tx_ring_size; i++)
>  		kfree(fep->tx_bounce[i]);
>  }
> 
> @@ -1687,7 +1711,7 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  	struct bufdesc	*bdp;
> 
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
>  		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
>  		if (!skb) {
>  			fec_enet_free_buffers(ndev);
> @@ -1704,15 +1728,15 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  			ebdp->cbd_esc = BD_ENET_RX_INT;
>  		}
> 
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap. */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	bdp = fep->tx_bd_base;
> -	for (i = 0; i < TX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->tx_ring_size; i++) {
>  		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
> 
>  		bdp->cbd_sc = 0;
> @@ -1723,11 +1747,11 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  			ebdp->cbd_esc = BD_ENET_TX_INT;
>  		}
> 
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap. */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	return 0;
> @@ -1967,13 +1991,17 @@ static int fec_enet_init(struct net_device *ndev)
>  	/* Get the Ethernet address */
>  	fec_get_mac(ndev);
> 
> +	/* init the tx & rx ring size */
> +	fep->tx_ring_size = TX_RING_SIZE;
> +	fep->rx_ring_size = RX_RING_SIZE;
> +
>  	/* Set receive and transmit descriptor base. */
>  	fep->rx_bd_base = cbd_base;
>  	if (fep->bufdesc_ex)
>  		fep->tx_bd_base = (struct bufdesc *)
> -			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
> +			(((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size);
>  	else
> -		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
> +		fep->tx_bd_base = cbd_base + fep->rx_ring_size;
> 
>  	/* The FEC Ethernet specific entries in the device structure */
>  	ndev->watchdog_timeo = TX_TIMEOUT;
> --
> 1.7.1

^ permalink raw reply

* [PATCH] net: fec: fix the error to get the previous BD entry
From: Fugang Duan @ 2013-09-03  2:41 UTC (permalink / raw)
  To: b20596, davem; +Cc: netdev, bhutchings, stephen

Bug: error to get the previous BD entry. When the current BD
is the first BD, the previous BD entry must be the last BD,
not "bdp - 1" in current logic.

V4:
  * Optimize fec_enet_get_nextdesc() for code clean.
    Replace "ex_new_bd - ring_size" with "ex_base".
    Replace "new_bd - ring_size" with "base".

V3:
  * Restore the API name because David suggest to use fec_enet_
    prefix for all function in fec driver.
    So, change next_bd() -> fec_enet_get_nextdesc()
        change pre_bd()  -> fec_enet_get_prevdesc()
  * Reduce the two APIs parameters for easy to call.

V2:
  * Add tx_ring_size and rx_ring_size to struct fec_enet_private.
  * Replace api fec_enet_get_nextdesc() with next_bd().
    Replace api fec_enet_get_prevdesc() with pre_bd().

  * Move all ring size check logic to next_bd() and pre_bd(), which
    simplifies the code redundancy.

V1:
  * Add BD ring size check to get the previous BD entry in correctly.

Reviewed-by: Li Frank <B20596@freescale.com>
Signed-off-by: Fugang Duan  <B38611@freescale.com>
---
 drivers/net/ethernet/freescale/fec.h      |    3 +
 drivers/net/ethernet/freescale/fec_main.c |  120 ++++++++++++++++++-----------
 2 files changed, 77 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index ae23600..0120217 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -296,6 +296,9 @@ struct fec_enet_private {
 	/* The ring entries to be free()ed */
 	struct bufdesc	*dirty_tx;
 
+	unsigned short tx_ring_size;
+	unsigned short rx_ring_size;
+
 	struct	platform_device *pdev;
 
 	int	opened;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 4ea1555..1364a6f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -239,22 +239,57 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 
 static int mii_cnt;
 
-static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
+static inline
+struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
 {
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex + 1);
+	struct bufdesc *new_bd = bdp + 1;
+	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
+	struct bufdesc_ex *ex_base;
+	struct bufdesc *base;
+	int ring_size;
+
+	if (bdp >= fep->tx_bd_base) {
+		base = fep->tx_bd_base;
+		ring_size = fep->tx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
+	} else {
+		base = fep->rx_bd_base;
+		ring_size = fep->rx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
+	}
+
+	if (fep->bufdesc_ex)
+		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
+			ex_base : ex_new_bd);
 	else
-		return bdp + 1;
+		return (new_bd >= (base + ring_size)) ?
+			base : new_bd;
 }
 
-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
+static inline
+struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
 {
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex - 1);
+	struct bufdesc *new_bd = bdp - 1;
+	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
+	struct bufdesc_ex *ex_base;
+	struct bufdesc *base;
+	int ring_size;
+
+	if (bdp >= fep->tx_bd_base) {
+		base = fep->tx_bd_base;
+		ring_size = fep->tx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
+	} else {
+		base = fep->rx_bd_base;
+		ring_size = fep->rx_ring_size;
+		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
+	}
+
+	if (fep->bufdesc_ex)
+		return (struct bufdesc *)((ex_new_bd < ex_base) ?
+			(ex_new_bd + ring_size) : ex_new_bd);
 	else
-		return bdp - 1;
+		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
 }
 
 static void *swap_buffer(void *bufaddr, int len)
@@ -380,7 +415,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		}
 	}
 
-	bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
 	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
 	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
 		fep->delay_work.trig_tx = true;
@@ -389,10 +424,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	}
 
 	/* If this was the last BD in the ring, start at the beginning again. */
-	if (status & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_nextdesc(bdp, fep);
 
 	fep->cur_tx = bdp;
 
@@ -417,18 +449,18 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 
 		/* Initialize the BD for every fragment in the page. */
 		if (bdp->cbd_bufaddr)
 			bdp->cbd_sc = BD_ENET_RX_EMPTY;
 		else
 			bdp->cbd_sc = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	fep->cur_rx = fep->rx_bd_base;
@@ -436,7 +468,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 	/* ...and the same for transmit */
 	bdp = fep->tx_bd_base;
 	fep->cur_tx = bdp;
-	for (i = 0; i < TX_RING_SIZE; i++) {
+	for (i = 0; i < fep->tx_ring_size; i++) {
 
 		/* Initialize the BD for every fragment in the page. */
 		bdp->cbd_sc = 0;
@@ -445,11 +477,11 @@ static void fec_enet_bd_init(struct net_device *dev)
 			fep->tx_skbuff[i] = NULL;
 		}
 		bdp->cbd_bufaddr = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 	fep->dirty_tx = bdp;
 }
@@ -510,10 +542,10 @@ fec_restart(struct net_device *ndev, int duplex)
 	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
 	if (fep->bufdesc_ex)
 		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
-			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
+			* fep->rx_ring_size, fep->hwp + FEC_X_DES_START);
 	else
 		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
-			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
+			* fep->rx_ring_size,	fep->hwp + FEC_X_DES_START);
 
 
 	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
@@ -727,10 +759,7 @@ fec_enet_tx(struct net_device *ndev)
 	bdp = fep->dirty_tx;
 
 	/* get next bdp of dirty_tx */
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_nextdesc(bdp, fep);
 
 	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
 
@@ -800,10 +829,7 @@ fec_enet_tx(struct net_device *ndev)
 		fep->dirty_tx = bdp;
 
 		/* Update pointer to next buffer descriptor to be transmitted */
-		if (status & BD_ENET_TX_WRAP)
-			bdp = fep->tx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
@@ -994,10 +1020,8 @@ rx_processing_done:
 		}
 
 		/* Update BD pointer to next entry */
-		if (status & BD_ENET_RX_WRAP)
-			bdp = fep->rx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
+
 		/* Doing this here will keep the FEC running while we process
 		 * incoming frames.  On a heavily loaded network, we should be
 		 * able to keep up at the expense of system resources.
@@ -1663,7 +1687,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 	struct bufdesc	*bdp;
 
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 		skb = fep->rx_skbuff[i];
 
 		if (bdp->cbd_bufaddr)
@@ -1671,11 +1695,11 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		if (skb)
 			dev_kfree_skb(skb);
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++)
+	for (i = 0; i < fep->tx_ring_size; i++)
 		kfree(fep->tx_bounce[i]);
 }
 
@@ -1687,7 +1711,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 	struct bufdesc	*bdp;
 
 	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < fep->rx_ring_size; i++) {
 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
 		if (!skb) {
 			fec_enet_free_buffers(ndev);
@@ -1704,15 +1728,15 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++) {
+	for (i = 0; i < fep->tx_ring_size; i++) {
 		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
 
 		bdp->cbd_sc = 0;
@@ -1723,11 +1747,11 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp = fec_enet_get_prevdesc(bdp, fep);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	return 0;
@@ -1967,13 +1991,17 @@ static int fec_enet_init(struct net_device *ndev)
 	/* Get the Ethernet address */
 	fec_get_mac(ndev);
 
+	/* init the tx & rx ring size */
+	fep->tx_ring_size = TX_RING_SIZE;
+	fep->rx_ring_size = RX_RING_SIZE;
+
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	if (fep->bufdesc_ex)
 		fep->tx_bd_base = (struct bufdesc *)
-			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
+			(((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size);
 	else
-		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+		fep->tx_bd_base = cbd_base + fep->rx_ring_size;
 
 	/* The FEC Ethernet specific entries in the device structure */
 	ndev->watchdog_timeo = TX_TIMEOUT;
-- 
1.7.1

^ permalink raw reply related

* RE: [PATCH] net: fec: fix the error to get the previous BD entry
From: Duan Fugang-B38611 @ 2013-09-03  2:49 UTC (permalink / raw)
  To: Li Frank-B20596, davem@davemloft.net
  Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
	stephen@networkplumber.org
In-Reply-To: <1F990F8245A4214A8CC4BFFBD9F790F908B45EA4@039-SN1MPN1-001.039d.mgd.msft.net>

From: Li Frank-B20596
Data: Tuesday, September 03, 2013 10:34 AM

> To: Duan Fugang-B38611; davem@davemloft.net
> Cc: netdev@vger.kernel.org; bhutchings@solarflare.com;
> stephen@networkplumber.org
> Subject: RE: [PATCH] net: fec: fix the error to get the previous BD entry
> 
> 
> > Bug: error to get the previous BD entry. When the current BD is the
> > first BD, the previous BD entry must be the last BD, not "bdp - 1" in
> current logic.
> >
> > V3:
> >   * Restore the API name because David suggest to use fec_enet_
> >     prefix for all function in fec driver.
> >     So, change next_bd() -> fec_enet_get_nextdesc()
> >         change pre_bd()  -> fec_enet_get_prevdesc()
> >   * Reduce the two APIs parameters for easy to call.
> >
> > V2:
> >   * Add tx_ring_size and rx_ring_size to struct fec_enet_private.
> >   * Replace api fec_enet_get_nextdesc() with next_bd().
> >     Replace api fec_enet_get_prevdesc() with pre_bd().
> >
> >   * Move all ring size check logic to next_bd() and pre_bd(), which
> >     simplifies the code redundancy.
> >
> > V1:
> >   * Add BD ring size check to get the previous BD entry in correctly.
> >
> > Reviewed-by: Li Frank <B20596@freescale.com>
> > Signed-off-by: Fugang Duan  <B38611@freescale.com>
> > ---
> >  drivers/net/ethernet/freescale/fec.h      |    3 +
> >  drivers/net/ethernet/freescale/fec_main.c |  120
> > ++++++++++++++++++---------
> > --
> >  2 files changed, 77 insertions(+), 46 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/fec.h
> > b/drivers/net/ethernet/freescale/fec.h
> > index ae23600..0120217 100644
> > --- a/drivers/net/ethernet/freescale/fec.h
> > +++ b/drivers/net/ethernet/freescale/fec.h
> > @@ -296,6 +296,9 @@ struct fec_enet_private {
> >  	/* The ring entries to be free()ed */
> >  	struct bufdesc	*dirty_tx;
> >
> > +	unsigned short tx_ring_size;
> > +	unsigned short rx_ring_size;
> > +
> >  	struct	platform_device *pdev;
> >
> >  	int	opened;
> > diff --git a/drivers/net/ethernet/freescale/fec_main.c
> > b/drivers/net/ethernet/freescale/fec_main.c
> > index 4ea1555..d5d8984 100644
> > --- a/drivers/net/ethernet/freescale/fec_main.c
> > +++ b/drivers/net/ethernet/freescale/fec_main.c
> > @@ -239,22 +239,57 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC
> > address");
> >
> >  static int mii_cnt;
> >
> > -static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int
> > is_ex)
> > +static inline
> > +struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct
> > +fec_enet_private *fep)
> >  {
> > -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> > -	if (is_ex)
> > -		return (struct bufdesc *)(ex + 1);
> > +	struct bufdesc *new_bd = bdp + 1;
> > +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
> > +	struct bufdesc_ex *ex_base;
> > +	struct bufdesc *base;
> > +	int ring_size;
> > +
> > +	if (bdp >= fep->tx_bd_base) {
> > +		base = fep->tx_bd_base;
> > +		ring_size = fep->tx_ring_size;
> > +		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
> > +	} else {
> > +		base = fep->rx_bd_base;
> > +		ring_size = fep->rx_ring_size;
> > +		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
> > +	}
> > +
> > +	if (fep->bufdesc_ex)
> > +		return (struct bufdesc *)((ex_new_bd >= (ex_base +
> ring_size)) ?
> > +			(ex_new_bd - ring_size) : ex_new_bd);
> 
> I think  "exbase:ex_new_bd" is better
> 
> >  	else
> > -		return bdp + 1;
> > +		return (new_bd >= (base + ring_size)) ?
> > +			(new_bd - ring_size) : new_bd;
> 
> I think "base:new_bd" is better.
> 

Yes, it is more clean for code review. I have sent the V4 version.
Thanks.

^ permalink raw reply

* Re: [PATCH v2 0/8] Drop support for Renesas H8/300 architecture
From: Chen Gang F T @ 2013-09-03  2:53 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-kernel, linux-ide, netdev, linux-watchdog, Wim Van Sebroeck,
	David S. Miller, Yoshinori Sato, Geert Uytterhoeven, Al Viro,
	Eric Paris, Greg Kroah-Hartman, Jiang Liu, David Howells,
	Thomas Gleixner, Stephen Rothwell, Linus Torvalds, Andrew Morton,
	Rusty Russell, Linus Walleij
In-Reply-To: <1377906694-9578-1-git-send-email-linux@roeck-us.net>

Hello Guenter Roeck:


I don't care about whether I am in cc mailing list, but at least,
please help confirm 2 things:

  Is what I had done for h8300 just making wastes and noisy in kernel and related sub-system mailing list ?

  and is the disccusion about h8300 between us also wastes and noisy in kernel mailing list ?


And also I have to make an apologize to kernel and other related sub
system mailing list:

  some of patches about h8300 which I have sent in 2013-09-02 are really wastes (and I wasted my time resource for it, too).

  the excuse (not reason) is I do not know about Guenter Roeck has sent this patch (I am not in this cc list, so I find it one day delay).


BTW: I also add some another related members in cc mailing list to let
them know about some of suspending thread about h8300 (which waiting
for allmodconfig finish) can be canceled.


Thanks.

On 08/31/2013 07:51 AM, Guenter Roeck wrote:
> H8/300 has been dead for several years, the kernel for it has
> not compiled for ages, and recent versions of gcc for it are broken.
> It is time to drop support for it.
> 
> Yes, I understand it is not that simple to drop an architecture,
> and it may need some discussion, but someone has to put a stake
> into the ground. Keeping a virtually dead architecture on life support
> takes resources which are better spent elsewhere.
> 
> v2:
> - s/Renesys/Renesas/g
> - Found and removed more architecture specific code in fs/minix
>   and in smc9194 driver
> - Added explicit Cc: for h8300 maintainer
> - Added subsystem maintainer Acks
> 
> ----------------------------------------------------------------
> Guenter Roeck (8):
>       Drop support for Renesas H8/300 (h8300) architecture
>       ide: Drop H8/300 driver
>       net/ethernet: smsc9194: Drop conditional code for H8/300
>       net/ethernet: Drop H8/300 Ethernet driver
>       watchdog: Drop references to H8300 architecture
>       Drop MAINTAINERS entry for H8/300
>       Drop remaining references to H8/300 architecture
>       fs/minix: Drop dependency on H8300
> 
>  Documentation/scheduler/sched-arch.txt           |    5 -
>  MAINTAINERS                                      |    8 -
>  arch/h8300/Kconfig                               |  109 ----
>  arch/h8300/Kconfig.cpu                           |  171 ------
>  arch/h8300/Kconfig.debug                         |   68 ---
>  arch/h8300/Kconfig.ide                           |   44 --
>  arch/h8300/Makefile                              |   71 ---
>  arch/h8300/README                                |   38 --
>  arch/h8300/boot/Makefile                         |   22 -
>  arch/h8300/boot/compressed/Makefile              |   37 --
>  arch/h8300/boot/compressed/head.S                |   47 --
>  arch/h8300/boot/compressed/misc.c                |  180 ------
>  arch/h8300/boot/compressed/vmlinux.lds           |   32 -
>  arch/h8300/boot/compressed/vmlinux.scr           |    9 -
>  arch/h8300/defconfig                             |   42 --
>  arch/h8300/include/asm/Kbuild                    |    8 -
>  arch/h8300/include/asm/asm-offsets.h             |    1 -
>  arch/h8300/include/asm/atomic.h                  |  146 -----
>  arch/h8300/include/asm/barrier.h                 |   29 -
>  arch/h8300/include/asm/bitops.h                  |  211 -------
>  arch/h8300/include/asm/bootinfo.h                |    2 -
>  arch/h8300/include/asm/bug.h                     |   12 -
>  arch/h8300/include/asm/bugs.h                    |   16 -
>  arch/h8300/include/asm/cache.h                   |   13 -
>  arch/h8300/include/asm/cachectl.h                |   14 -
>  arch/h8300/include/asm/cacheflush.h              |   40 --
>  arch/h8300/include/asm/checksum.h                |  102 ----
>  arch/h8300/include/asm/cmpxchg.h                 |   60 --
>  arch/h8300/include/asm/cputime.h                 |    6 -
>  arch/h8300/include/asm/current.h                 |   25 -
>  arch/h8300/include/asm/dbg.h                     |    2 -
>  arch/h8300/include/asm/delay.h                   |   38 --
>  arch/h8300/include/asm/device.h                  |    7 -
>  arch/h8300/include/asm/div64.h                   |    1 -
>  arch/h8300/include/asm/dma.h                     |   15 -
>  arch/h8300/include/asm/elf.h                     |  101 ----
>  arch/h8300/include/asm/emergency-restart.h       |    6 -
>  arch/h8300/include/asm/fb.h                      |   12 -
>  arch/h8300/include/asm/flat.h                    |   26 -
>  arch/h8300/include/asm/fpu.h                     |    1 -
>  arch/h8300/include/asm/ftrace.h                  |    1 -
>  arch/h8300/include/asm/futex.h                   |    6 -
>  arch/h8300/include/asm/gpio-internal.h           |   52 --
>  arch/h8300/include/asm/hardirq.h                 |   19 -
>  arch/h8300/include/asm/hw_irq.h                  |    1 -
>  arch/h8300/include/asm/io.h                      |  358 -----------
>  arch/h8300/include/asm/irq.h                     |   49 --
>  arch/h8300/include/asm/irq_regs.h                |    1 -
>  arch/h8300/include/asm/irqflags.h                |   43 --
>  arch/h8300/include/asm/kdebug.h                  |    1 -
>  arch/h8300/include/asm/kmap_types.h              |    6 -
>  arch/h8300/include/asm/local.h                   |    6 -
>  arch/h8300/include/asm/local64.h                 |    1 -
>  arch/h8300/include/asm/mc146818rtc.h             |    9 -
>  arch/h8300/include/asm/mmu_context.h             |   32 -
>  arch/h8300/include/asm/mutex.h                   |    9 -
>  arch/h8300/include/asm/page.h                    |   78 ---
>  arch/h8300/include/asm/page_offset.h             |    3 -
>  arch/h8300/include/asm/param.h                   |    9 -
>  arch/h8300/include/asm/pci.h                     |   19 -
>  arch/h8300/include/asm/percpu.h                  |    6 -
>  arch/h8300/include/asm/pgalloc.h                 |    8 -
>  arch/h8300/include/asm/pgtable.h                 |   73 ---
>  arch/h8300/include/asm/processor.h               |  139 -----
>  arch/h8300/include/asm/ptrace.h                  |   33 --
>  arch/h8300/include/asm/regs267x.h                |  336 -----------
>  arch/h8300/include/asm/regs306x.h                |  212 -------
>  arch/h8300/include/asm/scatterlist.h             |    6 -
>  arch/h8300/include/asm/sections.h                |    6 -
>  arch/h8300/include/asm/segment.h                 |   49 --
>  arch/h8300/include/asm/sh_bios.h                 |   29 -
>  arch/h8300/include/asm/shm.h                     |   31 -
>  arch/h8300/include/asm/shmparam.h                |    6 -
>  arch/h8300/include/asm/signal.h                  |   24 -
>  arch/h8300/include/asm/smp.h                     |    1 -
>  arch/h8300/include/asm/spinlock.h                |    6 -
>  arch/h8300/include/asm/string.h                  |   44 --
>  arch/h8300/include/asm/switch_to.h               |   50 --
>  arch/h8300/include/asm/target_time.h             |    4 -
>  arch/h8300/include/asm/termios.h                 |   50 --
>  arch/h8300/include/asm/thread_info.h             |  103 ----
>  arch/h8300/include/asm/timer.h                   |   25 -
>  arch/h8300/include/asm/timex.h                   |   19 -
>  arch/h8300/include/asm/tlb.h                     |    8 -
>  arch/h8300/include/asm/tlbflush.h                |   55 --
>  arch/h8300/include/asm/topology.h                |    6 -
>  arch/h8300/include/asm/traps.h                   |   37 --
>  arch/h8300/include/asm/types.h                   |    9 -
>  arch/h8300/include/asm/uaccess.h                 |  163 ------
>  arch/h8300/include/asm/ucontext.h                |   12 -
>  arch/h8300/include/asm/unaligned.h               |   11 -
>  arch/h8300/include/asm/unistd.h                  |   36 --
>  arch/h8300/include/asm/user.h                    |   75 ---
>  arch/h8300/include/asm/virtconvert.h             |   20 -
>  arch/h8300/include/uapi/asm/Kbuild               |   34 --
>  arch/h8300/include/uapi/asm/auxvec.h             |    4 -
>  arch/h8300/include/uapi/asm/bitsperlong.h        |    1 -
>  arch/h8300/include/uapi/asm/byteorder.h          |    6 -
>  arch/h8300/include/uapi/asm/errno.h              |    6 -
>  arch/h8300/include/uapi/asm/fcntl.h              |   11 -
>  arch/h8300/include/uapi/asm/ioctl.h              |    1 -
>  arch/h8300/include/uapi/asm/ioctls.h             |    8 -
>  arch/h8300/include/uapi/asm/ipcbuf.h             |    1 -
>  arch/h8300/include/uapi/asm/kvm_para.h           |    1 -
>  arch/h8300/include/uapi/asm/mman.h               |    1 -
>  arch/h8300/include/uapi/asm/msgbuf.h             |   31 -
>  arch/h8300/include/uapi/asm/param.h              |   16 -
>  arch/h8300/include/uapi/asm/poll.h               |   11 -
>  arch/h8300/include/uapi/asm/posix_types.h        |   26 -
>  arch/h8300/include/uapi/asm/ptrace.h             |   44 --
>  arch/h8300/include/uapi/asm/resource.h           |    6 -
>  arch/h8300/include/uapi/asm/sembuf.h             |   25 -
>  arch/h8300/include/uapi/asm/setup.h              |    6 -
>  arch/h8300/include/uapi/asm/shmbuf.h             |   42 --
>  arch/h8300/include/uapi/asm/sigcontext.h         |   18 -
>  arch/h8300/include/uapi/asm/siginfo.h            |    6 -
>  arch/h8300/include/uapi/asm/signal.h             |  115 ----
>  arch/h8300/include/uapi/asm/socket.h             |   79 ---
>  arch/h8300/include/uapi/asm/sockios.h            |   13 -
>  arch/h8300/include/uapi/asm/stat.h               |   78 ---
>  arch/h8300/include/uapi/asm/statfs.h             |    6 -
>  arch/h8300/include/uapi/asm/swab.h               |   10 -
>  arch/h8300/include/uapi/asm/termbits.h           |  201 -------
>  arch/h8300/include/uapi/asm/termios.h            |   44 --
>  arch/h8300/include/uapi/asm/types.h              |    1 -
>  arch/h8300/include/uapi/asm/unistd.h             |  330 -----------
>  arch/h8300/kernel/Makefile                       |   12 -
>  arch/h8300/kernel/asm-offsets.c                  |   60 --
>  arch/h8300/kernel/entry.S                        |  402 -------------
>  arch/h8300/kernel/gpio.c                         |  178 ------
>  arch/h8300/kernel/h8300_ksyms.c                  |  100 ----
>  arch/h8300/kernel/irq.c                          |  165 ------
>  arch/h8300/kernel/module.c                       |   75 ---
>  arch/h8300/kernel/process.c                      |  154 -----
>  arch/h8300/kernel/ptrace.c                       |  168 ------
>  arch/h8300/kernel/setup.c                        |  242 --------
>  arch/h8300/kernel/signal.c                       |  444 --------------
>  arch/h8300/kernel/sys_h8300.c                    |   48 --
>  arch/h8300/kernel/syscalls.S                     |  338 -----------
>  arch/h8300/kernel/time.c                         |   66 ---
>  arch/h8300/kernel/timer/Makefile                 |    6 -
>  arch/h8300/kernel/timer/itu.c                    |   82 ---
>  arch/h8300/kernel/timer/timer16.c                |   77 ---
>  arch/h8300/kernel/timer/timer8.c                 |  102 ----
>  arch/h8300/kernel/timer/tpu.c                    |  100 ----
>  arch/h8300/kernel/traps.c                        |  166 ------
>  arch/h8300/kernel/vmlinux.lds.S                  |  157 -----
>  arch/h8300/lib/Makefile                          |    5 -
>  arch/h8300/lib/abs.S                             |   21 -
>  arch/h8300/lib/ashrdi3.c                         |   63 --
>  arch/h8300/lib/checksum.c                        |  164 ------
>  arch/h8300/lib/memcpy.S                          |   84 ---
>  arch/h8300/lib/memset.S                          |   61 --
>  arch/h8300/lib/romfs.S                           |   57 --
>  arch/h8300/mm/Makefile                           |    5 -
>  arch/h8300/mm/fault.c                            |   56 --
>  arch/h8300/mm/init.c                             |  155 -----
>  arch/h8300/mm/kmap.c                             |   58 --
>  arch/h8300/mm/memory.c                           |   54 --
>  arch/h8300/platform/h8300h/Makefile              |    7 -
>  arch/h8300/platform/h8300h/aki3068net/Makefile   |    5 -
>  arch/h8300/platform/h8300h/aki3068net/crt0_ram.S |  110 ----
>  arch/h8300/platform/h8300h/generic/Makefile      |    5 -
>  arch/h8300/platform/h8300h/generic/crt0_ram.S    |  107 ----
>  arch/h8300/platform/h8300h/generic/crt0_rom.S    |  122 ----
>  arch/h8300/platform/h8300h/h8max/Makefile        |    5 -
>  arch/h8300/platform/h8300h/h8max/crt0_ram.S      |  110 ----
>  arch/h8300/platform/h8300h/irq.c                 |   82 ---
>  arch/h8300/platform/h8300h/ptrace_h8300h.c       |  284 ---------
>  arch/h8300/platform/h8s/Makefile                 |    7 -
>  arch/h8300/platform/h8s/edosk2674/Makefile       |    5 -
>  arch/h8300/platform/h8s/edosk2674/crt0_ram.S     |  130 ----
>  arch/h8300/platform/h8s/edosk2674/crt0_rom.S     |  186 ------
>  arch/h8300/platform/h8s/generic/Makefile         |    5 -
>  arch/h8300/platform/h8s/generic/crt0_ram.S       |  127 ----
>  arch/h8300/platform/h8s/generic/crt0_rom.S       |  128 ----
>  arch/h8300/platform/h8s/irq.c                    |  104 ----
>  arch/h8300/platform/h8s/ptrace_h8s.c             |   84 ---
>  drivers/ide/Kconfig                              |    7 -
>  drivers/ide/Makefile                             |    2 -
>  drivers/ide/ide-h8300.c                          |  109 ----
>  drivers/net/Space.c                              |    3 +-
>  drivers/net/ethernet/8390/Kconfig                |    7 -
>  drivers/net/ethernet/8390/Makefile               |    1 -
>  drivers/net/ethernet/8390/ne-h8300.c             |  684 ----------------------
>  drivers/net/ethernet/smsc/smc9194.c              |   24 -
>  drivers/watchdog/Kconfig                         |    2 -
>  drivers/watchdog/Makefile                        |    2 -
>  fs/minix/Kconfig                                 |    2 +-
>  include/linux/serial_sci.h                       |    2 +-
>  include/uapi/linux/audit.h                       |    1 -
>  include/uapi/linux/elf-em.h                      |    1 -
>  tools/testing/ktest/examples/crosstests.conf     |    6 -
>  193 files changed, 3 insertions(+), 11742 deletions(-)
>  delete mode 100644 arch/h8300/Kconfig
>  delete mode 100644 arch/h8300/Kconfig.cpu
>  delete mode 100644 arch/h8300/Kconfig.debug
>  delete mode 100644 arch/h8300/Kconfig.ide
>  delete mode 100644 arch/h8300/Makefile
>  delete mode 100644 arch/h8300/README
>  delete mode 100644 arch/h8300/boot/Makefile
>  delete mode 100644 arch/h8300/boot/compressed/Makefile
>  delete mode 100644 arch/h8300/boot/compressed/head.S
>  delete mode 100644 arch/h8300/boot/compressed/misc.c
>  delete mode 100644 arch/h8300/boot/compressed/vmlinux.lds
>  delete mode 100644 arch/h8300/boot/compressed/vmlinux.scr
>  delete mode 100644 arch/h8300/defconfig
>  delete mode 100644 arch/h8300/include/asm/Kbuild
>  delete mode 100644 arch/h8300/include/asm/asm-offsets.h
>  delete mode 100644 arch/h8300/include/asm/atomic.h
>  delete mode 100644 arch/h8300/include/asm/barrier.h
>  delete mode 100644 arch/h8300/include/asm/bitops.h
>  delete mode 100644 arch/h8300/include/asm/bootinfo.h
>  delete mode 100644 arch/h8300/include/asm/bug.h
>  delete mode 100644 arch/h8300/include/asm/bugs.h
>  delete mode 100644 arch/h8300/include/asm/cache.h
>  delete mode 100644 arch/h8300/include/asm/cachectl.h
>  delete mode 100644 arch/h8300/include/asm/cacheflush.h
>  delete mode 100644 arch/h8300/include/asm/checksum.h
>  delete mode 100644 arch/h8300/include/asm/cmpxchg.h
>  delete mode 100644 arch/h8300/include/asm/cputime.h
>  delete mode 100644 arch/h8300/include/asm/current.h
>  delete mode 100644 arch/h8300/include/asm/dbg.h
>  delete mode 100644 arch/h8300/include/asm/delay.h
>  delete mode 100644 arch/h8300/include/asm/device.h
>  delete mode 100644 arch/h8300/include/asm/div64.h
>  delete mode 100644 arch/h8300/include/asm/dma.h
>  delete mode 100644 arch/h8300/include/asm/elf.h
>  delete mode 100644 arch/h8300/include/asm/emergency-restart.h
>  delete mode 100644 arch/h8300/include/asm/fb.h
>  delete mode 100644 arch/h8300/include/asm/flat.h
>  delete mode 100644 arch/h8300/include/asm/fpu.h
>  delete mode 100644 arch/h8300/include/asm/ftrace.h
>  delete mode 100644 arch/h8300/include/asm/futex.h
>  delete mode 100644 arch/h8300/include/asm/gpio-internal.h
>  delete mode 100644 arch/h8300/include/asm/hardirq.h
>  delete mode 100644 arch/h8300/include/asm/hw_irq.h
>  delete mode 100644 arch/h8300/include/asm/io.h
>  delete mode 100644 arch/h8300/include/asm/irq.h
>  delete mode 100644 arch/h8300/include/asm/irq_regs.h
>  delete mode 100644 arch/h8300/include/asm/irqflags.h
>  delete mode 100644 arch/h8300/include/asm/kdebug.h
>  delete mode 100644 arch/h8300/include/asm/kmap_types.h
>  delete mode 100644 arch/h8300/include/asm/local.h
>  delete mode 100644 arch/h8300/include/asm/local64.h
>  delete mode 100644 arch/h8300/include/asm/mc146818rtc.h
>  delete mode 100644 arch/h8300/include/asm/mmu_context.h
>  delete mode 100644 arch/h8300/include/asm/mutex.h
>  delete mode 100644 arch/h8300/include/asm/page.h
>  delete mode 100644 arch/h8300/include/asm/page_offset.h
>  delete mode 100644 arch/h8300/include/asm/param.h
>  delete mode 100644 arch/h8300/include/asm/pci.h
>  delete mode 100644 arch/h8300/include/asm/percpu.h
>  delete mode 100644 arch/h8300/include/asm/pgalloc.h
>  delete mode 100644 arch/h8300/include/asm/pgtable.h
>  delete mode 100644 arch/h8300/include/asm/processor.h
>  delete mode 100644 arch/h8300/include/asm/ptrace.h
>  delete mode 100644 arch/h8300/include/asm/regs267x.h
>  delete mode 100644 arch/h8300/include/asm/regs306x.h
>  delete mode 100644 arch/h8300/include/asm/scatterlist.h
>  delete mode 100644 arch/h8300/include/asm/sections.h
>  delete mode 100644 arch/h8300/include/asm/segment.h
>  delete mode 100644 arch/h8300/include/asm/sh_bios.h
>  delete mode 100644 arch/h8300/include/asm/shm.h
>  delete mode 100644 arch/h8300/include/asm/shmparam.h
>  delete mode 100644 arch/h8300/include/asm/signal.h
>  delete mode 100644 arch/h8300/include/asm/smp.h
>  delete mode 100644 arch/h8300/include/asm/spinlock.h
>  delete mode 100644 arch/h8300/include/asm/string.h
>  delete mode 100644 arch/h8300/include/asm/switch_to.h
>  delete mode 100644 arch/h8300/include/asm/target_time.h
>  delete mode 100644 arch/h8300/include/asm/termios.h
>  delete mode 100644 arch/h8300/include/asm/thread_info.h
>  delete mode 100644 arch/h8300/include/asm/timer.h
>  delete mode 100644 arch/h8300/include/asm/timex.h
>  delete mode 100644 arch/h8300/include/asm/tlb.h
>  delete mode 100644 arch/h8300/include/asm/tlbflush.h
>  delete mode 100644 arch/h8300/include/asm/topology.h
>  delete mode 100644 arch/h8300/include/asm/traps.h
>  delete mode 100644 arch/h8300/include/asm/types.h
>  delete mode 100644 arch/h8300/include/asm/uaccess.h
>  delete mode 100644 arch/h8300/include/asm/ucontext.h
>  delete mode 100644 arch/h8300/include/asm/unaligned.h
>  delete mode 100644 arch/h8300/include/asm/unistd.h
>  delete mode 100644 arch/h8300/include/asm/user.h
>  delete mode 100644 arch/h8300/include/asm/virtconvert.h
>  delete mode 100644 arch/h8300/include/uapi/asm/Kbuild
>  delete mode 100644 arch/h8300/include/uapi/asm/auxvec.h
>  delete mode 100644 arch/h8300/include/uapi/asm/bitsperlong.h
>  delete mode 100644 arch/h8300/include/uapi/asm/byteorder.h
>  delete mode 100644 arch/h8300/include/uapi/asm/errno.h
>  delete mode 100644 arch/h8300/include/uapi/asm/fcntl.h
>  delete mode 100644 arch/h8300/include/uapi/asm/ioctl.h
>  delete mode 100644 arch/h8300/include/uapi/asm/ioctls.h
>  delete mode 100644 arch/h8300/include/uapi/asm/ipcbuf.h
>  delete mode 100644 arch/h8300/include/uapi/asm/kvm_para.h
>  delete mode 100644 arch/h8300/include/uapi/asm/mman.h
>  delete mode 100644 arch/h8300/include/uapi/asm/msgbuf.h
>  delete mode 100644 arch/h8300/include/uapi/asm/param.h
>  delete mode 100644 arch/h8300/include/uapi/asm/poll.h
>  delete mode 100644 arch/h8300/include/uapi/asm/posix_types.h
>  delete mode 100644 arch/h8300/include/uapi/asm/ptrace.h
>  delete mode 100644 arch/h8300/include/uapi/asm/resource.h
>  delete mode 100644 arch/h8300/include/uapi/asm/sembuf.h
>  delete mode 100644 arch/h8300/include/uapi/asm/setup.h
>  delete mode 100644 arch/h8300/include/uapi/asm/shmbuf.h
>  delete mode 100644 arch/h8300/include/uapi/asm/sigcontext.h
>  delete mode 100644 arch/h8300/include/uapi/asm/siginfo.h
>  delete mode 100644 arch/h8300/include/uapi/asm/signal.h
>  delete mode 100644 arch/h8300/include/uapi/asm/socket.h
>  delete mode 100644 arch/h8300/include/uapi/asm/sockios.h
>  delete mode 100644 arch/h8300/include/uapi/asm/stat.h
>  delete mode 100644 arch/h8300/include/uapi/asm/statfs.h
>  delete mode 100644 arch/h8300/include/uapi/asm/swab.h
>  delete mode 100644 arch/h8300/include/uapi/asm/termbits.h
>  delete mode 100644 arch/h8300/include/uapi/asm/termios.h
>  delete mode 100644 arch/h8300/include/uapi/asm/types.h
>  delete mode 100644 arch/h8300/include/uapi/asm/unistd.h
>  delete mode 100644 arch/h8300/kernel/Makefile
>  delete mode 100644 arch/h8300/kernel/asm-offsets.c
>  delete mode 100644 arch/h8300/kernel/entry.S
>  delete mode 100644 arch/h8300/kernel/gpio.c
>  delete mode 100644 arch/h8300/kernel/h8300_ksyms.c
>  delete mode 100644 arch/h8300/kernel/irq.c
>  delete mode 100644 arch/h8300/kernel/module.c
>  delete mode 100644 arch/h8300/kernel/process.c
>  delete mode 100644 arch/h8300/kernel/ptrace.c
>  delete mode 100644 arch/h8300/kernel/setup.c
>  delete mode 100644 arch/h8300/kernel/signal.c
>  delete mode 100644 arch/h8300/kernel/sys_h8300.c
>  delete mode 100644 arch/h8300/kernel/syscalls.S
>  delete mode 100644 arch/h8300/kernel/time.c
>  delete mode 100644 arch/h8300/kernel/timer/Makefile
>  delete mode 100644 arch/h8300/kernel/timer/itu.c
>  delete mode 100644 arch/h8300/kernel/timer/timer16.c
>  delete mode 100644 arch/h8300/kernel/timer/timer8.c
>  delete mode 100644 arch/h8300/kernel/timer/tpu.c
>  delete mode 100644 arch/h8300/kernel/traps.c
>  delete mode 100644 arch/h8300/kernel/vmlinux.lds.S
>  delete mode 100644 arch/h8300/lib/Makefile
>  delete mode 100644 arch/h8300/lib/abs.S
>  delete mode 100644 arch/h8300/lib/ashrdi3.c
>  delete mode 100644 arch/h8300/lib/checksum.c
>  delete mode 100644 arch/h8300/lib/memcpy.S
>  delete mode 100644 arch/h8300/lib/memset.S
>  delete mode 100644 arch/h8300/lib/romfs.S
>  delete mode 100644 arch/h8300/mm/Makefile
>  delete mode 100644 arch/h8300/mm/fault.c
>  delete mode 100644 arch/h8300/mm/init.c
>  delete mode 100644 arch/h8300/mm/kmap.c
>  delete mode 100644 arch/h8300/mm/memory.c
>  delete mode 100644 arch/h8300/platform/h8300h/Makefile
>  delete mode 100644 arch/h8300/platform/h8300h/aki3068net/Makefile
>  delete mode 100644 arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
>  delete mode 100644 arch/h8300/platform/h8300h/generic/Makefile
>  delete mode 100644 arch/h8300/platform/h8300h/generic/crt0_ram.S
>  delete mode 100644 arch/h8300/platform/h8300h/generic/crt0_rom.S
>  delete mode 100644 arch/h8300/platform/h8300h/h8max/Makefile
>  delete mode 100644 arch/h8300/platform/h8300h/h8max/crt0_ram.S
>  delete mode 100644 arch/h8300/platform/h8300h/irq.c
>  delete mode 100644 arch/h8300/platform/h8300h/ptrace_h8300h.c
>  delete mode 100644 arch/h8300/platform/h8s/Makefile
>  delete mode 100644 arch/h8300/platform/h8s/edosk2674/Makefile
>  delete mode 100644 arch/h8300/platform/h8s/edosk2674/crt0_ram.S
>  delete mode 100644 arch/h8300/platform/h8s/edosk2674/crt0_rom.S
>  delete mode 100644 arch/h8300/platform/h8s/generic/Makefile
>  delete mode 100644 arch/h8300/platform/h8s/generic/crt0_ram.S
>  delete mode 100644 arch/h8300/platform/h8s/generic/crt0_rom.S
>  delete mode 100644 arch/h8300/platform/h8s/irq.c
>  delete mode 100644 arch/h8300/platform/h8s/ptrace_h8s.c
>  delete mode 100644 drivers/ide/ide-h8300.c
>  delete mode 100644 drivers/net/ethernet/8390/ne-h8300.c
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


-- 
Chen Gang

^ permalink raw reply

* RE: [PATCH] net: fec: fix the error to get the previous BD entry
From: Li Frank-B20596 @ 2013-09-03  3:00 UTC (permalink / raw)
  To: Duan Fugang-B38611, davem@davemloft.net
  Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
	stephen@networkplumber.org
In-Reply-To: <1378176078-10380-1-git-send-email-B38611@freescale.com>

> 
> Bug: error to get the previous BD entry. When the current BD is the first BD,
> the previous BD entry must be the last BD, not "bdp - 1" in current logic.
> 
> V4:
>   * Optimize fec_enet_get_nextdesc() for code clean.
>     Replace "ex_new_bd - ring_size" with "ex_base".
>     Replace "new_bd - ring_size" with "base".
> 
> V3:
>   * Restore the API name because David suggest to use fec_enet_
>     prefix for all function in fec driver.
>     So, change next_bd() -> fec_enet_get_nextdesc()
>         change pre_bd()  -> fec_enet_get_prevdesc()
>   * Reduce the two APIs parameters for easy to call.
> 
> V2:
>   * Add tx_ring_size and rx_ring_size to struct fec_enet_private.
>   * Replace api fec_enet_get_nextdesc() with next_bd().
>     Replace api fec_enet_get_prevdesc() with pre_bd().
> 
>   * Move all ring size check logic to next_bd() and pre_bd(), which
>     simplifies the code redundancy.
> 
> V1:
>   * Add BD ring size check to get the previous BD entry in correctly.
> 
> Reviewed-by: Li Frank <B20596@freescale.com>
> Signed-off-by: Fugang Duan  <B38611@freescale.com>

Acked

> ---
>  drivers/net/ethernet/freescale/fec.h      |    3 +
>  drivers/net/ethernet/freescale/fec_main.c |  120 ++++++++++++++++++---------
> --
>  2 files changed, 77 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/fec.h
> b/drivers/net/ethernet/freescale/fec.h
> index ae23600..0120217 100644
> --- a/drivers/net/ethernet/freescale/fec.h
> +++ b/drivers/net/ethernet/freescale/fec.h
> @@ -296,6 +296,9 @@ struct fec_enet_private {
>  	/* The ring entries to be free()ed */
>  	struct bufdesc	*dirty_tx;
> 
> +	unsigned short tx_ring_size;
> +	unsigned short rx_ring_size;
> +
>  	struct	platform_device *pdev;
> 
>  	int	opened;
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 4ea1555..1364a6f 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -239,22 +239,57 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
> 
>  static int mii_cnt;
> 
> -static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
> +static inline
> +struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct
> +fec_enet_private *fep)
>  {
> -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> -	if (is_ex)
> -		return (struct bufdesc *)(ex + 1);
> +	struct bufdesc *new_bd = bdp + 1;
> +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
> +	struct bufdesc_ex *ex_base;
> +	struct bufdesc *base;
> +	int ring_size;
> +
> +	if (bdp >= fep->tx_bd_base) {
> +		base = fep->tx_bd_base;
> +		ring_size = fep->tx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
> +	} else {
> +		base = fep->rx_bd_base;
> +		ring_size = fep->rx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
> +	}
> +
> +	if (fep->bufdesc_ex)
> +		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
> +			ex_base : ex_new_bd);
>  	else
> -		return bdp + 1;
> +		return (new_bd >= (base + ring_size)) ?
> +			base : new_bd;
>  }
> 
> -static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
> +static inline
> +struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct
> +fec_enet_private *fep)
>  {
> -	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
> -	if (is_ex)
> -		return (struct bufdesc *)(ex - 1);
> +	struct bufdesc *new_bd = bdp - 1;
> +	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
> +	struct bufdesc_ex *ex_base;
> +	struct bufdesc *base;
> +	int ring_size;
> +
> +	if (bdp >= fep->tx_bd_base) {
> +		base = fep->tx_bd_base;
> +		ring_size = fep->tx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
> +	} else {
> +		base = fep->rx_bd_base;
> +		ring_size = fep->rx_ring_size;
> +		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
> +	}
> +
> +	if (fep->bufdesc_ex)
> +		return (struct bufdesc *)((ex_new_bd < ex_base) ?
> +			(ex_new_bd + ring_size) : ex_new_bd);
>  	else
> -		return bdp - 1;
> +		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
>  }
> 
>  static void *swap_buffer(void *bufaddr, int len) @@ -380,7 +415,7 @@
> fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>  		}
>  	}
> 
> -	bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
>  	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
>  	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
>  		fep->delay_work.trig_tx = true;
> @@ -389,10 +424,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct
> net_device *ndev)
>  	}
> 
>  	/* If this was the last BD in the ring, start at the beginning again.
> */
> -	if (status & BD_ENET_TX_WRAP)
> -		bdp = fep->tx_bd_base;
> -	else
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  	fep->cur_tx = bdp;
> 
> @@ -417,18 +449,18 @@ static void fec_enet_bd_init(struct net_device *dev)
> 
>  	/* Initialize the receive buffer descriptors. */
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
> 
>  		/* Initialize the BD for every fragment in the page. */
>  		if (bdp->cbd_bufaddr)
>  			bdp->cbd_sc = BD_ENET_RX_EMPTY;
>  		else
>  			bdp->cbd_sc = 0;
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	fep->cur_rx = fep->rx_bd_base;
> @@ -436,7 +468,7 @@ static void fec_enet_bd_init(struct net_device *dev)
>  	/* ...and the same for transmit */
>  	bdp = fep->tx_bd_base;
>  	fep->cur_tx = bdp;
> -	for (i = 0; i < TX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->tx_ring_size; i++) {
> 
>  		/* Initialize the BD for every fragment in the page. */
>  		bdp->cbd_sc = 0;
> @@ -445,11 +477,11 @@ static void fec_enet_bd_init(struct net_device *dev)
>  			fep->tx_skbuff[i] = NULL;
>  		}
>  		bdp->cbd_bufaddr = 0;
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
>  	fep->dirty_tx = bdp;
>  }
> @@ -510,10 +542,10 @@ fec_restart(struct net_device *ndev, int duplex)
>  	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
>  	if (fep->bufdesc_ex)
>  		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
> -			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
> +			* fep->rx_ring_size, fep->hwp + FEC_X_DES_START);
>  	else
>  		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
> -			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
> +			* fep->rx_ring_size,	fep->hwp + FEC_X_DES_START);
> 
> 
>  	for (i = 0; i <= TX_RING_MOD_MASK; i++) { @@ -727,10 +759,7 @@
> fec_enet_tx(struct net_device *ndev)
>  	bdp = fep->dirty_tx;
> 
>  	/* get next bdp of dirty_tx */
> -	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
> -		bdp = fep->tx_bd_base;
> -	else
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
> 
> @@ -800,10 +829,7 @@ fec_enet_tx(struct net_device *ndev)
>  		fep->dirty_tx = bdp;
> 
>  		/* Update pointer to next buffer descriptor to be transmitted */
> -		if (status & BD_ENET_TX_WRAP)
> -			bdp = fep->tx_bd_base;
> -		else
> -			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
> 
>  		/* Since we have freed up a buffer, the ring is no longer full
>  		 */
> @@ -994,10 +1020,8 @@ rx_processing_done:
>  		}
> 
>  		/* Update BD pointer to next entry */
> -		if (status & BD_ENET_RX_WRAP)
> -			bdp = fep->rx_bd_base;
> -		else
> -			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
> +
>  		/* Doing this here will keep the FEC running while we process
>  		 * incoming frames.  On a heavily loaded network, we should be
>  		 * able to keep up at the expense of system resources.
> @@ -1663,7 +1687,7 @@ static void fec_enet_free_buffers(struct net_device
> *ndev)
>  	struct bufdesc	*bdp;
> 
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
>  		skb = fep->rx_skbuff[i];
> 
>  		if (bdp->cbd_bufaddr)
> @@ -1671,11 +1695,11 @@ static void fec_enet_free_buffers(struct net_device
> *ndev)
>  					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
>  		if (skb)
>  			dev_kfree_skb(skb);
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	bdp = fep->tx_bd_base;
> -	for (i = 0; i < TX_RING_SIZE; i++)
> +	for (i = 0; i < fep->tx_ring_size; i++)
>  		kfree(fep->tx_bounce[i]);
>  }
> 
> @@ -1687,7 +1711,7 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  	struct bufdesc	*bdp;
> 
>  	bdp = fep->rx_bd_base;
> -	for (i = 0; i < RX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->rx_ring_size; i++) {
>  		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
>  		if (!skb) {
>  			fec_enet_free_buffers(ndev);
> @@ -1704,15 +1728,15 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  			ebdp->cbd_esc = BD_ENET_RX_INT;
>  		}
> 
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap. */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	bdp = fep->tx_bd_base;
> -	for (i = 0; i < TX_RING_SIZE; i++) {
> +	for (i = 0; i < fep->tx_ring_size; i++) {
>  		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
> 
>  		bdp->cbd_sc = 0;
> @@ -1723,11 +1747,11 @@ static int fec_enet_alloc_buffers(struct net_device
> *ndev)
>  			ebdp->cbd_esc = BD_ENET_TX_INT;
>  		}
> 
> -		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
> +		bdp = fec_enet_get_nextdesc(bdp, fep);
>  	}
> 
>  	/* Set the last buffer to wrap. */
> -	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
> +	bdp = fec_enet_get_prevdesc(bdp, fep);
>  	bdp->cbd_sc |= BD_SC_WRAP;
> 
>  	return 0;
> @@ -1967,13 +1991,17 @@ static int fec_enet_init(struct net_device *ndev)
>  	/* Get the Ethernet address */
>  	fec_get_mac(ndev);
> 
> +	/* init the tx & rx ring size */
> +	fep->tx_ring_size = TX_RING_SIZE;
> +	fep->rx_ring_size = RX_RING_SIZE;
> +
>  	/* Set receive and transmit descriptor base. */
>  	fep->rx_bd_base = cbd_base;
>  	if (fep->bufdesc_ex)
>  		fep->tx_bd_base = (struct bufdesc *)
> -			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
> +			(((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size);
>  	else
> -		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
> +		fep->tx_bd_base = cbd_base + fep->rx_ring_size;
> 
>  	/* The FEC Ethernet specific entries in the device structure */
>  	ndev->watchdog_timeo = TX_TIMEOUT;
> --
> 1.7.1

^ permalink raw reply

* Re: [PATCH v2 0/8] Drop support for Renesas H8/300 architecture
From: Guenter Roeck @ 2013-09-03  3:26 UTC (permalink / raw)
  To: Chen Gang F T
  Cc: linux-kernel, linux-ide, netdev, linux-watchdog, Wim Van Sebroeck,
	David S. Miller, Yoshinori Sato, Geert Uytterhoeven, Al Viro,
	Eric Paris, Greg Kroah-Hartman, Jiang Liu, David Howells,
	Thomas Gleixner, Stephen Rothwell, Linus Torvalds, Andrew Morton,
	Rusty Russell, Linus Walleij
In-Reply-To: <52254F11.8070601@gmail.com>

On 09/02/2013 07:53 PM, Chen Gang F T wrote:
> Hello Guenter Roeck:
> 
> 
> I don't care about whether I am in cc mailing list, but at least,
> please help confirm 2 things:
> 
>    Is what I had done for h8300 just making wastes and noisy in kernel and related sub-system mailing list ?
> 
>    and is the disccusion about h8300 between us also wastes and noisy in kernel mailing list ?
> 

It raised my awareness of the status of h8300 maintenance,
so I would not see it as noise or waste. I might have suggested
a different target for your efforts, but that is your choice to make,
not mine.

On the code review side, I had suggested that you should not add new
ifdefs into code, much less unnecessary ones. Your counter-argument
was that you wanted to follow the existing coding style in the file
in question. To me, that argument is along the line of "the coding
style in this file is bad, let's do more of it".
That doesn't make much sense to me, so I did not bother to respond.
Setting that aside, it is not up to me to approve or reject your patches.
Whoever does that would be the one you have to convince.

Guenter

^ permalink raw reply

* Re: [guv v2 04/31] net: Replace __get_cpu_var uses
From: David Miller @ 2013-09-03  3:33 UTC (permalink / raw)
  To: dhowells; +Cc: cl, tj, akpm, netdev, linux-arch, srostedt, linux-kernel
In-Reply-To: <7435.1378157706@warthog.procyon.org.uk>

From: David Howells <dhowells@redhat.com>
Date: Mon, 02 Sep 2013 22:35:06 +0100

> Would it be possible to use __thread annotations for per-CPU
> variables, I wonder?

Paul Mackerras tried it on powerpc and you can't do it.

The problem is that there is no way to tell the compiler that sched()
and similar (potentially) change the thread pointer base.

It really will cache pre-computed __thread pointer calculations across
sched().

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox