Hello!
The following backtrace was captured on the wild. :)
NETDEV WATCHDOG: eth2: transmit timed out
Debug: sleeping function called from invalid context at mm/slab.c:2088
in_atomic():1, irqs_disabled():0
[<c011bd22>] __might_sleep+0x92/0xa0
[<c0152081>] __kmalloc+0x81/0x90
[<c01b4c76>] proc_create+0x86/0x100
[<c01b4d8d>] proc_mkdir_mode+0x1d/0x60
[<c01474bc>] register_handler_proc+0x6c/0x80
[<c0146972>] setup_irq+0x122/0x200
[<d4872a30>] e100_intr+0x0/0x240 [e100]
[<c0146c8e>] request_irq+0x6e/0x90
[<d48740cb>] e100_up+0x13b/0x3b0 [e100]
[<c02fae80>] dev_watchdog+0x0/0x1b0
The attached patch tries to fix the problem deffering _up/_down.
Please apply.
Thank you.
Signed-off-by: Catalin BOIE <catab at umbrella.ro>
---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/
--- e100_sleep_in_atomic/drivers/net/e100.c 2005-03-02 09:38:33.000000000
+0200
+++ linux-2.6/drivers/net/e100.c 2005-07-08 13:34:15.000000000 +0300
@@ -564,8 +564,15 @@ struct nic {
u16 leds;
u16 eeprom_wc;
u16 eeprom[256];
+
+ struct work_struct tx_timeout_task;
};
+
+/* Local functions prototypes */
+static void e100_tx_timeout_task(struct net_device *netdev);
+
+
static inline void e100_write_flush(struct nic *nic)
{
/* Flush previous PCI writes through intermediate bridges
@@ -1718,6 +1725,14 @@ static void e100_tx_timeout(struct net_d
DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
readb(&nic->csr->scb.status));
+
+ schedule_work(&nic->tx_timeout_task);
+}
+
+/* This is runned in process context (from keventd) */
+/* Else request_irq in e100_up will trigger "sleep in invalid context */
+static void e100_tx_timeout_task(struct net_device *netdev)
+{
e100_down(netdev_priv(netdev));
e100_up(netdev_priv(netdev));
}
@@ -2265,6 +2280,9 @@ static int __devinit e100_probe(struct p
pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ INIT_WORK(&nic->tx_timeout_task,
+ (void (*)(void *))e100_tx_timeout_task, netdev);
+
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");