--- 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");