(I already sent these patches a few weeks ago and got no reply. I also
sent them to some of the recipients a few minutes ago and failed to
use git-send-email properly. So sorry for the noise.)
Please include the following three patches to 2.6.32-stable. They fix
serious flaws in the ucc_geth ethernet driver, making it unusable (at
least on my system).
They have been included in 2.6.33 and apply cleanly on top of
2.6.32-stable.
From: Jiajun Wu <[email protected]>
commit 7583605b6d29f1f7f6fc505b883328089f3485ad ("ucc_geth: Fix empty
TX queue processing") fixed empty TX queue mishandling, but didn't
account another corner case: when TX queue becomes full.
Without this patch the driver will stop transmiting when TX queue
becomes full since 'bd == ugeth->txBd[txQ]' actually checks for
two things: queue empty or full.
Let's better check for NULL skb, which unambiguously signals an empty
queue.
Signed-off-by: Jiajun Wu <[email protected]>
Signed-off-by: Anton Vorontsov <[email protected]>
Cc: Stable <[email protected]> [2.6.32]
Signed-off-by: David S. Miller <[email protected]>
(cherry picked from commit 34692421bc7d6145ef383b014860f4fde10b7505)
---
drivers/net/ucc_geth.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 5077fd9..b4b25ff 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3276,13 +3276,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 +
--
1.7.1
From: Anton Vorontsov <[email protected]>
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 <[email protected]>
Signed-off-by: Anton Vorontsov <[email protected]>
Tested-by: Lennart Sorensen <[email protected]>
Cc: Stable <[email protected]> [2.6.32]
Signed-off-by: David S. Miller <[email protected]>
(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
From: Anton Vorontsov <[email protected]>
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 <[email protected]>
Signed-off-by: Anton Vorontsov <[email protected]>
Tested-by: Lennart Sorensen <[email protected]>
Cc: Stable <[email protected]> [2.6.32]
Signed-off-by: David S. Miller <[email protected]>
(cherry picked from commit 08b5e1c91ce95793c59a59529a362a1bcc81faae)
---
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 20aa5b5..5077fd9 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.7.1