aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJoerg Ahrens <joerg@hydrops.han.de>2006-08-20 16:51:57 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-24 00:38:32 -0400
commit9a469abe9c6bab3ce237ee433541931bbd827faf (patch)
treeb1f3634a602b612fbbf62254f80c7c2c72a4540f /drivers/net
parentcb958186ed543d1a4f074ceb1c783fe8b0908437 (diff)
[PATCH] xirc2ps_cs: Cannot reset card in atomic context
I am using a Xircom CEM33 pcmcia NIC which has occasional hardware problems. If the netdev watchdog detects a transmit timeout, do_reset is called which msleeps - this is illegal in atomic context. This patch schedules the timeout handling as a workqueue item. Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 9bae77ce1314..4122bb46f5ff 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -345,6 +345,7 @@ typedef struct local_info_t {
345 void __iomem *dingo_ccr; /* only used for CEM56 cards */ 345 void __iomem *dingo_ccr; /* only used for CEM56 cards */
346 unsigned last_ptr_value; /* last packets transmitted value */ 346 unsigned last_ptr_value; /* last packets transmitted value */
347 const char *manf_str; 347 const char *manf_str;
348 struct work_struct tx_timeout_task;
348} local_info_t; 349} local_info_t;
349 350
350/**************** 351/****************
@@ -352,6 +353,7 @@ typedef struct local_info_t {
352 */ 353 */
353static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); 354static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
354static void do_tx_timeout(struct net_device *dev); 355static void do_tx_timeout(struct net_device *dev);
356static void xirc2ps_tx_timeout_task(void *data);
355static struct net_device_stats *do_get_stats(struct net_device *dev); 357static struct net_device_stats *do_get_stats(struct net_device *dev);
356static void set_addresses(struct net_device *dev); 358static void set_addresses(struct net_device *dev);
357static void set_multicast_list(struct net_device *dev); 359static void set_multicast_list(struct net_device *dev);
@@ -589,6 +591,7 @@ xirc2ps_probe(struct pcmcia_device *link)
589#ifdef HAVE_TX_TIMEOUT 591#ifdef HAVE_TX_TIMEOUT
590 dev->tx_timeout = do_tx_timeout; 592 dev->tx_timeout = do_tx_timeout;
591 dev->watchdog_timeo = TX_TIMEOUT; 593 dev->watchdog_timeo = TX_TIMEOUT;
594 INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
592#endif 595#endif
593 596
594 return xirc2ps_config(link); 597 return xirc2ps_config(link);
@@ -1341,17 +1344,24 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1341/*====================================================================*/ 1344/*====================================================================*/
1342 1345
1343static void 1346static void
1344do_tx_timeout(struct net_device *dev) 1347xirc2ps_tx_timeout_task(void *data)
1345{ 1348{
1346 local_info_t *lp = netdev_priv(dev); 1349 struct net_device *dev = data;
1347 printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
1348 lp->stats.tx_errors++;
1349 /* reset the card */ 1350 /* reset the card */
1350 do_reset(dev,1); 1351 do_reset(dev,1);
1351 dev->trans_start = jiffies; 1352 dev->trans_start = jiffies;
1352 netif_wake_queue(dev); 1353 netif_wake_queue(dev);
1353} 1354}
1354 1355
1356static void
1357do_tx_timeout(struct net_device *dev)
1358{
1359 local_info_t *lp = netdev_priv(dev);
1360 lp->stats.tx_errors++;
1361 printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
1362 schedule_work(&lp->tx_timeout_task);
1363}
1364
1355static int 1365static int
1356do_start_xmit(struct sk_buff *skb, struct net_device *dev) 1366do_start_xmit(struct sk_buff *skb, struct net_device *dev)
1357{ 1367{