Skip to content

Commit

Permalink
ks8842: Do the TX timeout work in workqueue context.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Richard Röjfors authored and David S. Miller committed Jul 9, 2010
1 parent 301e9d9 commit cc88e45
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions drivers/net/ks8842.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ struct ks8842_adapter {
int irq;
struct tasklet_struct tasklet;
spinlock_t lock; /* spinlock to be interrupt safe */
struct work_struct timeout_work;
struct net_device *netdev;
};

static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
Expand Down Expand Up @@ -553,6 +555,8 @@ static int ks8842_close(struct net_device *netdev)

netdev_dbg(netdev, "%s - entry\n", __func__);

cancel_work_sync(&adapter->timeout_work);

/* free the irq */
free_irq(adapter->irq, netdev);

Expand Down Expand Up @@ -595,9 +599,11 @@ static int ks8842_set_mac(struct net_device *netdev, void *p)
return 0;
}

static void ks8842_tx_timeout(struct net_device *netdev)
static void ks8842_tx_timeout_work(struct work_struct *work)
{
struct ks8842_adapter *adapter = netdev_priv(netdev);
struct ks8842_adapter *adapter =
container_of(work, struct ks8842_adapter, timeout_work);
struct net_device *netdev = adapter->netdev;
unsigned long flags;

netdev_dbg(netdev, "%s: entry\n", __func__);
Expand All @@ -606,6 +612,9 @@ static void ks8842_tx_timeout(struct net_device *netdev)
/* disable interrupts */
ks8842_write16(adapter, 18, 0, REG_IER);
ks8842_write16(adapter, 18, 0xFFFF, REG_ISR);

netif_stop_queue(netdev);

spin_unlock_irqrestore(&adapter->lock, flags);

ks8842_reset_hw(adapter);
Expand All @@ -615,6 +624,15 @@ static void ks8842_tx_timeout(struct net_device *netdev)
ks8842_update_link_status(netdev, adapter);
}

static void ks8842_tx_timeout(struct net_device *netdev)
{
struct ks8842_adapter *adapter = netdev_priv(netdev);

netdev_dbg(netdev, "%s: entry\n", __func__);

schedule_work(&adapter->timeout_work);
}

static const struct net_device_ops ks8842_netdev_ops = {
.ndo_open = ks8842_open,
.ndo_stop = ks8842_close,
Expand Down Expand Up @@ -649,6 +667,8 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
SET_NETDEV_DEV(netdev, &pdev->dev);

adapter = netdev_priv(netdev);
adapter->netdev = netdev;
INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
if (!adapter->hw_addr)
goto err_ioremap;
Expand Down

0 comments on commit cc88e45

Please sign in to comment.