aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ks8842.c
diff options
context:
space:
mode:
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;