aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ks8842.c
diff options
context:
space:
mode:
authorRichard Röjfors <richard.rojfors@pelagicore.com>2010-07-09 02:36:30 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-09 02:40:19 -0400
commitcc88e450ad14a79fd2d083f0827607499cf1ef51 (patch)
tree3a54a5d635af1550d3fcc41661f25f29c08bda20 /drivers/net/ks8842.c
parent301e9d96bf65292f916a3936d63c504ac7792ee6 (diff)
ks8842: Do the TX timeout work in workqueue context.
Currently all code that needs to be run at TX timeout is done in the calling context, where bottom halves are disabled. Some of the code blocks, so it needs to be done in a different context. This patch adds in a work struct which is scheduled at TX timeout. Then the timeout code is executed within work queue context. Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ks8842.c')
-rw-r--r--drivers/net/ks8842.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index d47bba9202e1..5191af2c1fa0 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -119,6 +119,8 @@ struct ks8842_adapter {
119 int irq; 119 int irq;
120 struct tasklet_struct tasklet; 120 struct tasklet_struct tasklet;
121 spinlock_t lock; /* spinlock to be interrupt safe */ 121 spinlock_t lock; /* spinlock to be interrupt safe */
122 struct work_struct timeout_work;
123 struct net_device *netdev;
122}; 124};
123 125
124static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank) 126static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
@@ -553,6 +555,8 @@ static int ks8842_close(struct net_device *netdev)
553 555
554 netdev_dbg(netdev, "%s - entry\n", __func__); 556 netdev_dbg(netdev, "%s - entry\n", __func__);
555 557
558 cancel_work_sync(&adapter->timeout_work);
559
556 /* free the irq */ 560 /* free the irq */
557 free_irq(adapter->irq, netdev); 561 free_irq(adapter->irq, netdev);
558 562
@@ -595,9 +599,11 @@ static int ks8842_set_mac(struct net_device *netdev, void *p)
595 return 0; 599 return 0;
596} 600}
597 601
598static void ks8842_tx_timeout(struct net_device *netdev) 602static void ks8842_tx_timeout_work(struct work_struct *work)
599{ 603{
600 struct ks8842_adapter *adapter = netdev_priv(netdev); 604 struct ks8842_adapter *adapter =
605 container_of(work, struct ks8842_adapter, timeout_work);
606 struct net_device *netdev = adapter->netdev;
601 unsigned long flags; 607 unsigned long flags;
602 608
603 netdev_dbg(netdev, "%s: entry\n", __func__); 609 netdev_dbg(netdev, "%s: entry\n", __func__);
@@ -606,6 +612,9 @@ static void ks8842_tx_timeout(struct net_device *netdev)
606 /* disable interrupts */ 612 /* disable interrupts */
607 ks8842_write16(adapter, 18, 0, REG_IER); 613 ks8842_write16(adapter, 18, 0, REG_IER);
608 ks8842_write16(adapter, 18, 0xFFFF, REG_ISR); 614 ks8842_write16(adapter, 18, 0xFFFF, REG_ISR);
615
616 netif_stop_queue(netdev);
617
609 spin_unlock_irqrestore(&adapter->lock, flags); 618 spin_unlock_irqrestore(&adapter->lock, flags);
610 619
611 ks8842_reset_hw(adapter); 620 ks8842_reset_hw(adapter);
@@ -615,6 +624,15 @@ static void ks8842_tx_timeout(struct net_device *netdev)
615 ks8842_update_link_status(netdev, adapter); 624 ks8842_update_link_status(netdev, adapter);
616} 625}
617 626
627static void ks8842_tx_timeout(struct net_device *netdev)
628{
629 struct ks8842_adapter *adapter = netdev_priv(netdev);
630
631 netdev_dbg(netdev, "%s: entry\n", __func__);
632
633 schedule_work(&adapter->timeout_work);
634}
635
618static const struct net_device_ops ks8842_netdev_ops = { 636static const struct net_device_ops ks8842_netdev_ops = {
619 .ndo_open = ks8842_open, 637 .ndo_open = ks8842_open,
620 .ndo_stop = ks8842_close, 638 .ndo_stop = ks8842_close,
@@ -649,6 +667,8 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
649 SET_NETDEV_DEV(netdev, &pdev->dev); 667 SET_NETDEV_DEV(netdev, &pdev->dev);
650 668
651 adapter = netdev_priv(netdev); 669 adapter = netdev_priv(netdev);
670 adapter->netdev = netdev;
671 INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
652 adapter->hw_addr = ioremap(iomem->start, resource_size(iomem)); 672 adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
653 if (!adapter->hw_addr) 673 if (!adapter->hw_addr)
654 goto err_ioremap; 674 goto err_ioremap;