aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-10-08 00:38:14 -0400
committerJeff Garzik <jeff@garzik.org>2006-12-02 00:11:57 -0500
commitd18e0c4a5434f02586b5fdcbcc72f1fe61ab49e6 (patch)
tree813592f56a6f090c7732aa7da675276b722da6ab /drivers/net/wireless
parent5c877fe58c5df19646204b144b978b99c2ef074f (diff)
[PATCH] prism54: fix potential race in reset scheduling
NET: prism54 - fix potential race in reset scheduling There appears to be a race in reset scheduling logic - thread responsible for reseting the interface should clear "reset pending" flag before restarting the queue, otherwise timeout handler might not schedule another reset even if it is needed. This race is mostly theoretical as far as I can see but a race nonetheless. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index a8261d8454dd..bfbafe99b94a 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -253,6 +253,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
253 * header and without the FCS. But there a is a bit that 253 * header and without the FCS. But there a is a bit that
254 * indicates if the packet is corrupted :-) */ 254 * indicates if the packet is corrupted :-) */
255 struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data; 255 struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data;
256
256 if (hdr->flags & 0x01) 257 if (hdr->flags & 0x01)
257 /* This one is bad. Drop it ! */ 258 /* This one is bad. Drop it ! */
258 return -1; 259 return -1;
@@ -464,10 +465,8 @@ islpci_eth_receive(islpci_private *priv)
464 break; 465 break;
465 } 466 }
466 /* update the fragment address */ 467 /* update the fragment address */
467 control_block->rx_data_low[index].address = cpu_to_le32((u32) 468 control_block->rx_data_low[index].address =
468 priv-> 469 cpu_to_le32((u32)priv->pci_map_rx_address[index]);
469 pci_map_rx_address
470 [index]);
471 wmb(); 470 wmb();
472 471
473 /* increment the driver read pointer */ 472 /* increment the driver read pointer */
@@ -484,10 +483,12 @@ islpci_eth_receive(islpci_private *priv)
484void 483void
485islpci_do_reset_and_wake(void *data) 484islpci_do_reset_and_wake(void *data)
486{ 485{
487 islpci_private *priv = (islpci_private *) data; 486 islpci_private *priv = data;
487
488 islpci_reset(priv, 1); 488 islpci_reset(priv, 1);
489 netif_wake_queue(priv->ndev);
490 priv->reset_task_pending = 0; 489 priv->reset_task_pending = 0;
490 smp_wmb();
491 netif_wake_queue(priv->ndev);
491} 492}
492 493
493void 494void
@@ -499,12 +500,14 @@ islpci_eth_tx_timeout(struct net_device *ndev)
499 /* increment the transmit error counter */ 500 /* increment the transmit error counter */
500 statistics->tx_errors++; 501 statistics->tx_errors++;
501 502
502 printk(KERN_WARNING "%s: tx_timeout", ndev->name);
503 if (!priv->reset_task_pending) { 503 if (!priv->reset_task_pending) {
504 priv->reset_task_pending = 1; 504 printk(KERN_WARNING
505 printk(", scheduling a reset"); 505 "%s: tx_timeout, scheduling reset", ndev->name);
506 netif_stop_queue(ndev); 506 netif_stop_queue(ndev);
507 priv->reset_task_pending = 1;
507 schedule_work(&priv->reset_task); 508 schedule_work(&priv->reset_task);
509 } else {
510 printk(KERN_WARNING
511 "%s: tx_timeout, waiting for reset", ndev->name);
508 } 512 }
509 printk("\n");
510} 513}