All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] ucc_geth: Some more fixes
@ 2009-12-24 15:30 Anton Vorontsov
  2009-12-24 15:31   ` Anton Vorontsov
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:30 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, netdev, Lennart Sorensen

Hi all,

Here are some more fixes and one small enhancement for the ucc_geth
driver.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/3] ucc_geth: Fix empty TX queue processing
  2009-12-24 15:30 [PATCH 0/3] ucc_geth: Some more fixes Anton Vorontsov
@ 2009-12-24 15:31   ` Anton Vorontsov
  2009-12-24 15:31   ` Anton Vorontsov
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, netdev, Lennart Sorensen

Following oops was seen with the ucc_geth driver:

 Unable to handle kernel paging request for data at address 0x00000058
 Faulting instruction address: 0xc024f2fc
 Oops: Kernel access of bad area, sig: 11 [#1]
 [...]
 NIP [c024f2fc] skb_recycle_check+0x14/0x100
 LR [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 Call Trace:
 [df857d50] [c000b03c] __ipipe_grab_irq+0x3c/0xa4 (unreliable)
 [df857d60] [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 [df857dd0] [c0258cf8] net_rx_action+0xf8/0x1b8
 [df857e10] [c0032a38] __do_softirq+0xb8/0x13c
 [df857e60] [c00065cc] do_softirq+0xa0/0xac
 [...]

This is because ucc_geth_tx() tries to process an empty queue when
queues are logically stopped. Stopping the queues doesn't disable
polling, and since nowadays ucc_geth_tx() is actually called from
the polling routine, the oops above might pop up.

Fix this by removing 'netif_queue_stopped() == 0' check.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index afaf088..0f8c99e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3273,7 +3273,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+		if (bd == ugeth->txBd[txQ]) /* queue empty? */
 			break;
 
 		dev->stats.tx_packets++;
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 1/3] ucc_geth: Fix empty TX queue processing
@ 2009-12-24 15:31   ` Anton Vorontsov
  0 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: Lennart Sorensen, Li Yang, netdev, linuxppc-dev

Following oops was seen with the ucc_geth driver:

 Unable to handle kernel paging request for data at address 0x00000058
 Faulting instruction address: 0xc024f2fc
 Oops: Kernel access of bad area, sig: 11 [#1]
 [...]
 NIP [c024f2fc] skb_recycle_check+0x14/0x100
 LR [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 Call Trace:
 [df857d50] [c000b03c] __ipipe_grab_irq+0x3c/0xa4 (unreliable)
 [df857d60] [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 [df857dd0] [c0258cf8] net_rx_action+0xf8/0x1b8
 [df857e10] [c0032a38] __do_softirq+0xb8/0x13c
 [df857e60] [c00065cc] do_softirq+0xa0/0xac
 [...]

This is because ucc_geth_tx() tries to process an empty queue when
queues are logically stopped. Stopping the queues doesn't disable
polling, and since nowadays ucc_geth_tx() is actually called from
the polling routine, the oops above might pop up.

Fix this by removing 'netif_queue_stopped() == 0' check.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index afaf088..0f8c99e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3273,7 +3273,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+		if (bd == ugeth->txBd[txQ]) /* queue empty? */
 			break;
 
 		dev->stats.tx_packets++;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/3] ucc_geth: Fix netdev watchdog triggering on link changes
  2009-12-24 15:30 [PATCH 0/3] ucc_geth: Some more fixes Anton Vorontsov
@ 2009-12-24 15:31   ` Anton Vorontsov
  2009-12-24 15:31   ` Anton Vorontsov
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, netdev, Lennart Sorensen

Since commit 864fdf884e82bacbe8ca5e93bd43393a61d2e2b4 ("ucc_geth:
Fix hangs after switching from full to half duplex") ucc_geth driver
disables the controller during MAC configuration changes. Though,
disabling the controller might take quite awhile, and so the netdev
watchdog might get upset:

 NETDEV WATCHDOG: eth2 (ucc_geth): transmit queue 0 timed out
 ------------[ cut here ]------------
 Badness at c02729a8 [verbose debug info unavailable]
 NIP: c02729a8 LR: c02729a8 CTR: c01b6088
 REGS: c0451c40 TRAP: 0700   Not tainted  (2.6.32-trunk-8360e)
 [...]
 NIP [c02729a8] dev_watchdog+0x280/0x290
 LR [c02729a8] dev_watchdog+0x280/0x290
 Call Trace:
 [c0451cf0] [c02729a8] dev_watchdog+0x280/0x290 (unreliable)
 [c0451d50] [c00377c4] run_timer_softirq+0x164/0x224
 [c0451da0] [c0032a38] __do_softirq+0xb8/0x13c
 [c0451df0] [c00065cc] do_softirq+0xa0/0xac
 [c0451e00] [c003280c] irq_exit+0x7c/0x9c
 [c0451e10] [c00640c4] __ipipe_sync_stage+0x248/0x24c
 [...]

This patch fixes the issue by detaching the netdev during the
time we change the configuration.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 0f8c99e..7fff4c5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1563,7 +1563,10 @@ static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
 
 static void ugeth_quiesce(struct ucc_geth_private *ugeth)
 {
-	/* Wait for and prevent any further xmits. */
+	/* Prevent any further xmits, plus detach the device. */
+	netif_device_detach(ugeth->ndev);
+
+	/* Wait for any current xmits to finish. */
 	netif_tx_disable(ugeth->ndev);
 
 	/* Disable the interrupt to avoid NAPI rescheduling. */
@@ -1577,7 +1580,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
 {
 	napi_enable(&ugeth->napi);
 	enable_irq(ugeth->ug_info->uf_info.irq);
-	netif_tx_wake_all_queues(ugeth->ndev);
+	netif_device_attach(ugeth->ndev);
 }
 
 /* Called every time the controller might need to be made
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/3] ucc_geth: Fix netdev watchdog triggering on link changes
@ 2009-12-24 15:31   ` Anton Vorontsov
  0 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: Lennart Sorensen, Li Yang, netdev, linuxppc-dev

Since commit 864fdf884e82bacbe8ca5e93bd43393a61d2e2b4 ("ucc_geth:
Fix hangs after switching from full to half duplex") ucc_geth driver
disables the controller during MAC configuration changes. Though,
disabling the controller might take quite awhile, and so the netdev
watchdog might get upset:

 NETDEV WATCHDOG: eth2 (ucc_geth): transmit queue 0 timed out
 ------------[ cut here ]------------
 Badness at c02729a8 [verbose debug info unavailable]
 NIP: c02729a8 LR: c02729a8 CTR: c01b6088
 REGS: c0451c40 TRAP: 0700   Not tainted  (2.6.32-trunk-8360e)
 [...]
 NIP [c02729a8] dev_watchdog+0x280/0x290
 LR [c02729a8] dev_watchdog+0x280/0x290
 Call Trace:
 [c0451cf0] [c02729a8] dev_watchdog+0x280/0x290 (unreliable)
 [c0451d50] [c00377c4] run_timer_softirq+0x164/0x224
 [c0451da0] [c0032a38] __do_softirq+0xb8/0x13c
 [c0451df0] [c00065cc] do_softirq+0xa0/0xac
 [c0451e00] [c003280c] irq_exit+0x7c/0x9c
 [c0451e10] [c00640c4] __ipipe_sync_stage+0x248/0x24c
 [...]

This patch fixes the issue by detaching the netdev during the
time we change the configuration.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 0f8c99e..7fff4c5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1563,7 +1563,10 @@ static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
 
 static void ugeth_quiesce(struct ucc_geth_private *ugeth)
 {
-	/* Wait for and prevent any further xmits. */
+	/* Prevent any further xmits, plus detach the device. */
+	netif_device_detach(ugeth->ndev);
+
+	/* Wait for any current xmits to finish. */
 	netif_tx_disable(ugeth->ndev);
 
 	/* Disable the interrupt to avoid NAPI rescheduling. */
@@ -1577,7 +1580,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
 {
 	napi_enable(&ugeth->napi);
 	enable_irq(ugeth->ug_info->uf_info.irq);
-	netif_tx_wake_all_queues(ugeth->ndev);
+	netif_device_attach(ugeth->ndev);
 }
 
 /* Called every time the controller might need to be made
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/3] ucc_geth: Don't needlessly change MAC settings in adjust_link()
  2009-12-24 15:30 [PATCH 0/3] ucc_geth: Some more fixes Anton Vorontsov
@ 2009-12-24 15:31   ` Anton Vorontsov
  2009-12-24 15:31   ` Anton Vorontsov
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, netdev, Lennart Sorensen

If PHY doesn't have an IRQ, phylib would poll for link changes, and
would call adjust_link() every second. In that case we disable and
enable the controller every second.

Let's better check if there is actually anything changed, and, if so,
change the MAC settings.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/net/ucc_geth.c |   33 ++++++++++++++++++---------------
 1 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 7fff4c5..41ad2f3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1651,25 +1651,28 @@ static void adjust_link(struct net_device *dev)
 			ugeth->oldspeed = phydev->speed;
 		}
 
-		/*
-		 * To change the MAC configuration we need to disable the
-		 * controller. To do so, we have to either grab ugeth->lock,
-		 * which is a bad idea since 'graceful stop' commands might
-		 * take quite a while, or we can quiesce driver's activity.
-		 */
-		ugeth_quiesce(ugeth);
-		ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
-
-		out_be32(&ug_regs->maccfg2, tempval);
-		out_be32(&uf_regs->upsmr, upsmr);
-
-		ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
-		ugeth_activate(ugeth);
-
 		if (!ugeth->oldlink) {
 			new_state = 1;
 			ugeth->oldlink = 1;
 		}
+
+		if (new_state) {
+			/*
+			 * To change the MAC configuration we need to disable
+			 * the controller. To do so, we have to either grab
+			 * ugeth->lock, which is a bad idea since 'graceful
+			 * stop' commands might take quite a while, or we can
+			 * quiesce driver's activity.
+			 */
+			ugeth_quiesce(ugeth);
+			ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+			out_be32(&ug_regs->maccfg2, tempval);
+			out_be32(&uf_regs->upsmr, upsmr);
+
+			ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+			ugeth_activate(ugeth);
+		}
 	} else if (ugeth->oldlink) {
 			new_state = 1;
 			ugeth->oldlink = 0;
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/3] ucc_geth: Don't needlessly change MAC settings in adjust_link()
@ 2009-12-24 15:31   ` Anton Vorontsov
  0 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2009-12-24 15:31 UTC (permalink / raw)
  To: David Miller; +Cc: Lennart Sorensen, Li Yang, netdev, linuxppc-dev

If PHY doesn't have an IRQ, phylib would poll for link changes, and
would call adjust_link() every second. In that case we disable and
enable the controller every second.

Let's better check if there is actually anything changed, and, if so,
change the MAC settings.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/net/ucc_geth.c |   33 ++++++++++++++++++---------------
 1 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 7fff4c5..41ad2f3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1651,25 +1651,28 @@ static void adjust_link(struct net_device *dev)
 			ugeth->oldspeed = phydev->speed;
 		}
 
-		/*
-		 * To change the MAC configuration we need to disable the
-		 * controller. To do so, we have to either grab ugeth->lock,
-		 * which is a bad idea since 'graceful stop' commands might
-		 * take quite a while, or we can quiesce driver's activity.
-		 */
-		ugeth_quiesce(ugeth);
-		ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
-
-		out_be32(&ug_regs->maccfg2, tempval);
-		out_be32(&uf_regs->upsmr, upsmr);
-
-		ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
-		ugeth_activate(ugeth);
-
 		if (!ugeth->oldlink) {
 			new_state = 1;
 			ugeth->oldlink = 1;
 		}
+
+		if (new_state) {
+			/*
+			 * To change the MAC configuration we need to disable
+			 * the controller. To do so, we have to either grab
+			 * ugeth->lock, which is a bad idea since 'graceful
+			 * stop' commands might take quite a while, or we can
+			 * quiesce driver's activity.
+			 */
+			ugeth_quiesce(ugeth);
+			ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+			out_be32(&ug_regs->maccfg2, tempval);
+			out_be32(&uf_regs->upsmr, upsmr);
+
+			ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+			ugeth_activate(ugeth);
+		}
 	} else if (ugeth->oldlink) {
 			new_state = 1;
 			ugeth->oldlink = 0;
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/3] ucc_geth: Some more fixes
  2009-12-24 15:30 [PATCH 0/3] ucc_geth: Some more fixes Anton Vorontsov
@ 2009-12-27  4:25   ` David Miller
  2009-12-24 15:31   ` Anton Vorontsov
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2009-12-27  4:25 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, netdev, lsorense

From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Thu, 24 Dec 2009 18:30:34 +0300

> Here are some more fixes and one small enhancement for the ucc_geth
> driver.

All 3 patches applied, thanks a lot!

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/3] ucc_geth: Some more fixes
@ 2009-12-27  4:25   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2009-12-27  4:25 UTC (permalink / raw)
  To: avorontsov; +Cc: lsorense, leoli, netdev, linuxppc-dev

From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Thu, 24 Dec 2009 18:30:34 +0300

> Here are some more fixes and one small enhancement for the ucc_geth
> driver.

All 3 patches applied, thanks a lot!

^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
       [not found] <0A1FE637C2C7E148B9573BB60CC630E56C3E90@zch01exm26.fsl.freescale.net>
@ 2010-01-11  3:47   ` Wu Jiajun-B06378
  0 siblings, 0 replies; 16+ messages in thread
From: Wu Jiajun-B06378 @ 2010-01-11  3:47 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, lsorense, davem, netdev

=20
'bd =3D=3D ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
2)empty queue.
Removing 'netif_queue_stopped() =3D=3D 0' will make transmitting =
stopping
when the queue is full.=20

I made a new patch for this oops.

>From 726765194352d01dc8ea672d97612589b67cec3f Mon Sep 17 00:00:00 2001
From: Jiajun Wu <b06378@freescale.com>
Date: Mon, 11 Jan 2010 10:57:22 +0800
Subject: [PATCH] ucc_geth: Fix empty TX queue processing

Signed-off-by: Jiajun Wu <b06378@freescale.com>
---
 drivers/net/ucc_geth.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index f982220..34345f0 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3576,17 +3576,17 @@ static int ucc_geth_tx(struct net_device *dev,
u8 txQ)
 	while ((bd_status & T_R) =3D=3D 0) {
 		struct sk_buff *skb;
=20
+		skb =3D ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+
 		/* BD contains already transmitted buffer.   */
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
=20
-		if ((bd =3D=3D ugeth->txBd[txQ]) &&
(netif_queue_stopped(dev) =3D=3D 0))
+		if ((bd =3D=3D ugeth->txBd[txQ]) && (skb =3D=3D NULL))
 			break;
=20
 		dev->stats.tx_packets++;
=20
-		skb =3D ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN
&&
 			     skb_recycle_check(skb,
=20
ugeth->ug_info->uf_info.max_rx_buf_length +
--=20
1.5.6.3
-----Original Message-----
From: linuxppc-dev-bounces+b13201=3Dfreescale.com@lists.ozlabs.org
[mailto:linuxppc-dev-bounces+b13201=3Dfreescale.com@lists.ozlabs.org] On
Behalf Of Anton Vorontsov
Sent: Thursday, December 24, 2009 11:31 PM
To: David Miller
Cc: linuxppc-dev@ozlabs.org; netdev@vger.kernel.org; Lennart Sorensen
Subject: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
-----------

Following oops was seen with the ucc_geth driver:

 Unable to handle kernel paging request for data at address 0x00000058
Faulting instruction address: 0xc024f2fc
 Oops: Kernel access of bad area, sig: 11 [#1]  [...]  NIP [c024f2fc]
skb_recycle_check+0x14/0x100  LR [e30aa0a4] ucc_geth_poll+0xd8/0x4e0
[ucc_geth_driver]  Call Trace:
 [df857d50] [c000b03c] __ipipe_grab_irq+0x3c/0xa4 (unreliable)
[df857d60] [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
[df857dd0] [c0258cf8] net_rx_action+0xf8/0x1b8  [df857e10] [c0032a38]
__do_softirq+0xb8/0x13c  [df857e60] [c00065cc] do_softirq+0xa0/0xac
[...]

This is because ucc_geth_tx() tries to process an empty queue when
queues are logically stopped. Stopping the queues doesn't disable
polling, and since nowadays ucc_geth_tx() is actually called from the
polling routine, the oops above might pop up.

Fix this by removing 'netif_queue_stopped() =3D=3D 0' check.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index
afaf088..0f8c99e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3273,7 +3273,7 @@ static int ucc_geth_tx(struct net_device *dev, u8
txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
=20
-		if ((bd =3D=3D ugeth->txBd[txQ]) &&
(netif_queue_stopped(dev) =3D=3D 0))
+		if (bd =3D=3D ugeth->txBd[txQ]) /* queue empty? */
 			break;
=20
 		dev->stats.tx_packets++;
--
1.6.3.3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* RE: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
@ 2010-01-11  3:47   ` Wu Jiajun-B06378
  0 siblings, 0 replies; 16+ messages in thread
From: Wu Jiajun-B06378 @ 2010-01-11  3:47 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, netdev, lsorense, davem

 
'bd == ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
2)empty queue.
Removing 'netif_queue_stopped() == 0' will make transmitting stopping
when the queue is full. 

I made a new patch for this oops.

>From 726765194352d01dc8ea672d97612589b67cec3f Mon Sep 17 00:00:00 2001
From: Jiajun Wu <b06378@freescale.com>
Date: Mon, 11 Jan 2010 10:57:22 +0800
Subject: [PATCH] ucc_geth: Fix empty TX queue processing

Signed-off-by: Jiajun Wu <b06378@freescale.com>
---
 drivers/net/ucc_geth.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index f982220..34345f0 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3576,17 +3576,17 @@ static int ucc_geth_tx(struct net_device *dev,
u8 txQ)
 	while ((bd_status & T_R) == 0) {
 		struct sk_buff *skb;
 
+		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+
 		/* BD contains already transmitted buffer.   */
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) &&
(netif_queue_stopped(dev) == 0))
+		if ((bd == ugeth->txBd[txQ]) && (skb == NULL))
 			break;
 
 		dev->stats.tx_packets++;
 
-		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN
&&
 			     skb_recycle_check(skb,
 
ugeth->ug_info->uf_info.max_rx_buf_length +
-- 
1.5.6.3
-----Original Message-----
From: linuxppc-dev-bounces+b13201=freescale.com@lists.ozlabs.org
[mailto:linuxppc-dev-bounces+b13201=freescale.com@lists.ozlabs.org] On
Behalf Of Anton Vorontsov
Sent: Thursday, December 24, 2009 11:31 PM
To: David Miller
Cc: linuxppc-dev@ozlabs.org; netdev@vger.kernel.org; Lennart Sorensen
Subject: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
-----------

Following oops was seen with the ucc_geth driver:

 Unable to handle kernel paging request for data at address 0x00000058
Faulting instruction address: 0xc024f2fc
 Oops: Kernel access of bad area, sig: 11 [#1]  [...]  NIP [c024f2fc]
skb_recycle_check+0x14/0x100  LR [e30aa0a4] ucc_geth_poll+0xd8/0x4e0
[ucc_geth_driver]  Call Trace:
 [df857d50] [c000b03c] __ipipe_grab_irq+0x3c/0xa4 (unreliable)
[df857d60] [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
[df857dd0] [c0258cf8] net_rx_action+0xf8/0x1b8  [df857e10] [c0032a38]
__do_softirq+0xb8/0x13c  [df857e60] [c00065cc] do_softirq+0xa0/0xac
[...]

This is because ucc_geth_tx() tries to process an empty queue when
queues are logically stopped. Stopping the queues doesn't disable
polling, and since nowadays ucc_geth_tx() is actually called from the
polling routine, the oops above might pop up.

Fix this by removing 'netif_queue_stopped() == 0' check.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
---
 drivers/net/ucc_geth.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index
afaf088..0f8c99e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3273,7 +3273,7 @@ static int ucc_geth_tx(struct net_device *dev, u8
txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) &&
(netif_queue_stopped(dev) == 0))
+		if (bd == ugeth->txBd[txQ]) /* queue empty? */
 			break;
 
 		dev->stats.tx_packets++;
--
1.6.3.3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
  2010-01-11  3:47   ` Wu Jiajun-B06378
@ 2010-01-11 10:52     ` Anton Vorontsov
  -1 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2010-01-11 10:52 UTC (permalink / raw)
  To: Wu Jiajun-B06378; +Cc: linuxppc-dev, lsorense, davem, netdev

On Mon, Jan 11, 2010 at 11:47:37AM +0800, Wu Jiajun-B06378 wrote:
>  
> 'bd == ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
> 2)empty queue.
> Removing 'netif_queue_stopped() == 0' will make transmitting stopping
> when the queue is full. 
> 
> I made a new patch for this oops.
[...]
> +		if ((bd == ugeth->txBd[txQ]) && (skb == NULL))
>  			break;

Hm. I wonder why do we need the 'bd == ugeth->txBd[txQ]' check
at all? The null skb will cause a kernel oops anyway.

I think the patch below should be sufficient for the fix.
Can you try it? Or if you tell me how to reproduce the issue
you observe, I can try it myself.

Thanks a lot!

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 41ad2f3..a1a6d06 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if (bd == ugeth->txBd[txQ]) /* queue empty? */
+		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+		if (!skb)
 			break;
 
 		dev->stats.tx_packets++;
 
-		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
 			     skb_recycle_check(skb,
 				    ugeth->ug_info->uf_info.max_rx_buf_length +

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
@ 2010-01-11 10:52     ` Anton Vorontsov
  0 siblings, 0 replies; 16+ messages in thread
From: Anton Vorontsov @ 2010-01-11 10:52 UTC (permalink / raw)
  To: Wu Jiajun-B06378; +Cc: linuxppc-dev, netdev, lsorense, davem

On Mon, Jan 11, 2010 at 11:47:37AM +0800, Wu Jiajun-B06378 wrote:
>  
> 'bd == ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
> 2)empty queue.
> Removing 'netif_queue_stopped() == 0' will make transmitting stopping
> when the queue is full. 
> 
> I made a new patch for this oops.
[...]
> +		if ((bd == ugeth->txBd[txQ]) && (skb == NULL))
>  			break;

Hm. I wonder why do we need the 'bd == ugeth->txBd[txQ]' check
at all? The null skb will cause a kernel oops anyway.

I think the patch below should be sufficient for the fix.
Can you try it? Or if you tell me how to reproduce the issue
you observe, I can try it myself.

Thanks a lot!

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 41ad2f3..a1a6d06 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if (bd == ugeth->txBd[txQ]) /* queue empty? */
+		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+		if (!skb)
 			break;
 
 		dev->stats.tx_packets++;
 
-		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
 			     skb_recycle_check(skb,
 				    ugeth->ug_info->uf_info.max_rx_buf_length +

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* RE: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
  2010-01-11 10:52     ` Anton Vorontsov
@ 2010-01-11 11:52       ` Wu Jiajun-B06378
  -1 siblings, 0 replies; 16+ messages in thread
From: Wu Jiajun-B06378 @ 2010-01-11 11:52 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, lsorense, davem, netdev


Yes,'if (!skb)' is enough.
You can reproduce transmitting stopping if you use 'if ((bd =3D=3D =
ugeth->txBd[txQ])' and run ipforwarding with MTU=3D64 1Gbps =
100%linerate.


-----Original Message-----
From: Anton Vorontsov [mailto:avorontsov@ru.mvista.com]=20
Sent: 2010=C4=EA1=D4=C211=C8=D5 18:53
To: Wu Jiajun-B06378
Cc: linuxppc-dev@ozlabs.org; netdev@vger.kernel.org; =
lsorense@csclub.uwaterloo.ca; davem@davemloft.net
Subject: Re: [PATCH 1/3] ucc_geth: Fix empty TX queue processing

On Mon, Jan 11, 2010 at 11:47:37AM +0800, Wu Jiajun-B06378 wrote:
> =20
> 'bd =3D=3D ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
> 2)empty queue.
> Removing 'netif_queue_stopped() =3D=3D 0' will make transmitting =
stopping=20
> when the queue is full.
>=20
> I made a new patch for this oops.
[...]
> +		if ((bd =3D=3D ugeth->txBd[txQ]) && (skb =3D=3D NULL))
>  			break;

Hm. I wonder why do we need the 'bd =3D=3D ugeth->txBd[txQ]' check at =
all? The null skb will cause a kernel oops anyway.

I think the patch below should be sufficient for the fix.
Can you try it? Or if you tell me how to reproduce the issue you =
observe, I can try it myself.

Thanks a lot!

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index =
41ad2f3..a1a6d06 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, =
u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
=20
-		if (bd =3D=3D ugeth->txBd[txQ]) /* queue empty? */
+		skb =3D ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+		if (!skb)
 			break;
=20
 		dev->stats.tx_packets++;
=20
-		skb =3D ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
 			     skb_recycle_check(skb,
 				    ugeth->ug_info->uf_info.max_rx_buf_length +

^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: [PATCH 1/3] ucc_geth: Fix empty TX queue processing
@ 2010-01-11 11:52       ` Wu Jiajun-B06378
  0 siblings, 0 replies; 16+ messages in thread
From: Wu Jiajun-B06378 @ 2010-01-11 11:52 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, netdev, lsorense, davem


Yes,'if (!skb)' is enough.
You can reproduce transmitting stopping if you use 'if ((bd == ugeth->txBd[txQ])' and run ipforwarding with MTU=64 1Gbps 100%linerate.


-----Original Message-----
From: Anton Vorontsov [mailto:avorontsov@ru.mvista.com] 
Sent: 2010年1月11日 18:53
To: Wu Jiajun-B06378
Cc: linuxppc-dev@ozlabs.org; netdev@vger.kernel.org; lsorense@csclub.uwaterloo.ca; davem@davemloft.net
Subject: Re: [PATCH 1/3] ucc_geth: Fix empty TX queue processing

On Mon, Jan 11, 2010 at 11:47:37AM +0800, Wu Jiajun-B06378 wrote:
>  
> 'bd == ugeth->txBd[txQ]' has two possible statuses: 1)full queue.
> 2)empty queue.
> Removing 'netif_queue_stopped() == 0' will make transmitting stopping 
> when the queue is full.
> 
> I made a new patch for this oops.
[...]
> +		if ((bd == ugeth->txBd[txQ]) && (skb == NULL))
>  			break;

Hm. I wonder why do we need the 'bd == ugeth->txBd[txQ]' check at all? The null skb will cause a kernel oops anyway.

I think the patch below should be sufficient for the fix.
Can you try it? Or if you tell me how to reproduce the issue you observe, I can try it myself.

Thanks a lot!

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 41ad2f3..a1a6d06 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if (bd == ugeth->txBd[txQ]) /* queue empty? */
+		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+		if (!skb)
 			break;
 
 		dev->stats.tx_packets++;
 
-		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
 			     skb_recycle_check(skb,
 				    ugeth->ug_info->uf_info.max_rx_buf_length +


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/3] ucc_geth: Fix empty TX queue processing
  2010-06-22 13:02 [stable] Please apply ucc_geth driver fixes to 2.6.32-stable Petri Lehtinen
@ 2010-06-22 13:02 ` Petri Lehtinen
  0 siblings, 0 replies; 16+ messages in thread
From: Petri Lehtinen @ 2010-06-22 13:02 UTC (permalink / raw)
  To: linux-kernel
  Cc: stable, netdev, Anton Vorontsov, Stable, "[2.6.32]",
	David S. Miller

From: Anton Vorontsov <avorontsov@ru.mvista.com>

Following oops was seen with the ucc_geth driver:

 Unable to handle kernel paging request for data at address 0x00000058
 Faulting instruction address: 0xc024f2fc
 Oops: Kernel access of bad area, sig: 11 [#1]
 [...]
 NIP [c024f2fc] skb_recycle_check+0x14/0x100
 LR [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 Call Trace:
 [df857d50] [c000b03c] __ipipe_grab_irq+0x3c/0xa4 (unreliable)
 [df857d60] [e30aa0a4] ucc_geth_poll+0xd8/0x4e0 [ucc_geth_driver]
 [df857dd0] [c0258cf8] net_rx_action+0xf8/0x1b8
 [df857e10] [c0032a38] __do_softirq+0xb8/0x13c
 [df857e60] [c00065cc] do_softirq+0xa0/0xac
 [...]

This is because ucc_geth_tx() tries to process an empty queue when
queues are logically stopped. Stopping the queues doesn't disable
polling, and since nowadays ucc_geth_tx() is actually called from
the polling routine, the oops above might pop up.

Fix this by removing 'netif_queue_stopped() == 0' check.

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Tested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: Stable <stable@vger.kernel.org> [2.6.32]
Signed-off-by: David S. Miller <davem@davemloft.net>

(cherry picked from commit 7583605b6d29f1f7f6fc505b883328089f3485ad)
---
 drivers/net/ucc_geth.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4469f24..20aa5b5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3273,7 +3273,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+		if (bd == ugeth->txBd[txQ]) /* queue empty? */
 			break;
 
 		dev->stats.tx_packets++;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-06-22 13:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-24 15:30 [PATCH 0/3] ucc_geth: Some more fixes Anton Vorontsov
2009-12-24 15:31 ` [PATCH 1/3] ucc_geth: Fix empty TX queue processing Anton Vorontsov
2009-12-24 15:31   ` Anton Vorontsov
2009-12-24 15:31 ` [PATCH 2/3] ucc_geth: Fix netdev watchdog triggering on link changes Anton Vorontsov
2009-12-24 15:31   ` Anton Vorontsov
2009-12-24 15:31 ` [PATCH 3/3] ucc_geth: Don't needlessly change MAC settings in adjust_link() Anton Vorontsov
2009-12-24 15:31   ` Anton Vorontsov
2009-12-27  4:25 ` [PATCH 0/3] ucc_geth: Some more fixes David Miller
2009-12-27  4:25   ` David Miller
     [not found] <0A1FE637C2C7E148B9573BB60CC630E56C3E90@zch01exm26.fsl.freescale.net>
2010-01-11  3:47 ` [PATCH 1/3] ucc_geth: Fix empty TX queue processing Wu Jiajun-B06378
2010-01-11  3:47   ` Wu Jiajun-B06378
2010-01-11 10:52   ` Anton Vorontsov
2010-01-11 10:52     ` Anton Vorontsov
2010-01-11 11:52     ` Wu Jiajun-B06378
2010-01-11 11:52       ` Wu Jiajun-B06378
  -- strict thread matches above, loose matches on Subject: below --
2010-06-22 13:02 [stable] Please apply ucc_geth driver fixes to 2.6.32-stable Petri Lehtinen
2010-06-22 13:02 ` [PATCH 1/3] ucc_geth: Fix empty TX queue processing Petri Lehtinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.