From: "Luis R. Rodriguez" 2004-03-18 Aurelien Alleaume - islpci_eth.[c,h] islpci_dev.[c,h] : reset card on tx_timeout. Patch submited by Denis Vlasenko Signed-off-by: Andrew Morton --- 25-akpm/drivers/net/wireless/prism54/islpci_dev.c | 6 ++-- 25-akpm/drivers/net/wireless/prism54/islpci_dev.h | 5 ++- 25-akpm/drivers/net/wireless/prism54/islpci_eth.c | 33 ++++++++++------------ 25-akpm/drivers/net/wireless/prism54/islpci_eth.h | 3 +- 4 files changed, 26 insertions(+), 21 deletions(-) diff -puN drivers/net/wireless/prism54/islpci_dev.c~prism54-reset-card-on-tx_timeout drivers/net/wireless/prism54/islpci_dev.c --- 25/drivers/net/wireless/prism54/islpci_dev.c~prism54-reset-card-on-tx_timeout Wed May 26 16:16:55 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_dev.c Wed May 26 16:16:55 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.68 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.71 2004/03/18 11:44:17 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel @@ -743,9 +743,11 @@ islpci_setup(struct pci_dev *pdev) /* initialize workqueue's */ INIT_WORK(&priv->stats_work, (void (*)(void *)) prism54_update_stats, priv); - priv->stats_timestamp = 0; + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + priv->reset_task_pending = 0; + /* allocate various memory areas */ if (islpci_alloc_memory(priv)) goto do_free_netdev; diff -puN drivers/net/wireless/prism54/islpci_dev.h~prism54-reset-card-on-tx_timeout drivers/net/wireless/prism54/islpci_dev.h --- 25/drivers/net/wireless/prism54/islpci_dev.h~prism54-reset-card-on-tx_timeout Wed May 26 16:16:55 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_dev.h Wed May 26 16:16:55 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.55 2004/03/18 11:16:23 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.56 2004/03/18 11:44:17 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel @@ -188,6 +188,9 @@ typedef struct { struct list_head bss_wpa_list; int num_bss_wpa; struct semaphore wpa_sem; + + struct work_struct reset_task; + int reset_task_pending; } islpci_private; static inline islpci_state_t diff -puN drivers/net/wireless/prism54/islpci_eth.c~prism54-reset-card-on-tx_timeout drivers/net/wireless/prism54/islpci_eth.c --- 25/drivers/net/wireless/prism54/islpci_eth.c~prism54-reset-card-on-tx_timeout Wed May 26 16:16:55 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_eth.c Wed May 26 16:16:55 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.27 2004/01/30 16:24:00 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.30 2004/03/18 11:44:17 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * @@ -319,17 +319,9 @@ islpci_eth_receive(islpci_private *priv) /* The card reports full 802.11 packets but with a 20 bytes * header and without the FCS. But there a is a bit that * indicates if the packet is corrupted :-) */ - /* int i; */ - if (skb->data[8] & 0x01){ + if (skb->data[8] & 0x01) /* This one is bad. Drop it !*/ discard = 1; - /* printk("BAD\n");*/ - } - /* - for(i=0;i<50;i++) - printk("%2.2X:",skb->data[i]); - printk("\n"); - */ skb_pull(skb, 20); skb->protocol = htons(ETH_P_802_2); skb->mac.raw = skb->data; @@ -414,6 +406,15 @@ islpci_eth_receive(islpci_private *priv) } void +islpci_do_reset_and_wake(void *data) +{ + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; +} + +void islpci_eth_tx_timeout(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); @@ -422,13 +423,11 @@ islpci_eth_tx_timeout(struct net_device /* increment the transmit error counter */ statistics->tx_errors++; -#if 0 - /* don't do this here! we are not allowed to sleep since we are in interrupt context */ - if (islpci_reset(priv)) - printk(KERN_ERR "%s: error on TX timeout card reset!\n", - ndev->name); -#endif + if(!priv->reset_task_pending) { + priv->reset_task_pending = 1; + netif_stop_queue(ndev); + schedule_work(&priv->reset_task); + } - /* netif_wake_queue(ndev); */ return; } diff -puN drivers/net/wireless/prism54/islpci_eth.h~prism54-reset-card-on-tx_timeout drivers/net/wireless/prism54/islpci_eth.h --- 25/drivers/net/wireless/prism54/islpci_eth.h~prism54-reset-card-on-tx_timeout Wed May 26 16:16:55 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_eth.h Wed May 26 16:16:55 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.5 2004/01/12 22:16:32 jmaurer Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.6 2004/03/18 11:44:17 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * @@ -27,5 +27,6 @@ void islpci_eth_cleanup_transmit(islpci_ int islpci_eth_transmit(struct sk_buff *, struct net_device *); int islpci_eth_receive(islpci_private *); void islpci_eth_tx_timeout(struct net_device *); +void islpci_do_reset_and_wake(void *data); #endif /* _ISL_GEN_H */ _