[linux-yocto] [PATCH 2/2] net: femac: Possible deadlock during nfs mount fixed.
Cristian Bercaru
cristian.bercaru at windriver.com
Mon Oct 26 09:53:53 PDT 2015
From: Sreedevi Joshi <sreedevi.joshi at intel.com>
This is to fix mount.nfs over TCP generating the following circular
dependency and possible DEADLOCK message. FEMAC driver has been
converted to LLTX to avoid this issue. Tx lock is introduced in the
FEMAC driver.
CPU0 CPU1
---- ----
lock(clock-AF_INET);
lock(_xmit_ETHER#2);
lock(clock-AF_INET);
lock(_xmit_ETHER#2);
*** DEADLOCK ***
Signed-off-by: Sreedevi Joshi <sreedevi.joshi at intel.com>
---
drivers/net/ethernet/lsi/lsi_acp_net.c | 12 ++++++++++++
drivers/net/ethernet/lsi/lsi_acp_net.h | 1 +
2 files changed, 13 insertions(+)
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.c b/drivers/net/ethernet/lsi/lsi_acp_net.c
index 1973e04..8ea1ca1 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.c
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
@@ -895,6 +895,7 @@ static irqreturn_t appnic_isr(int irq, void *device_id)
struct appnic_device *pdata = netdev_priv(dev);
unsigned long dma_interrupt_status;
unsigned long flags;
+ unsigned long flags1;
/* Acquire the lock. */
spin_lock_irqsave(&pdata->dev_lock, flags);
@@ -910,7 +911,9 @@ static irqreturn_t appnic_isr(int irq, void *device_id)
if (TX_INTERRUPT(dma_interrupt_status)) {
/* transmition complete */
pdata->transmit_interrupts++;
+ spin_lock_irqsave(&pdata->tx_lock, flags1);
handle_transmit_interrupt(dev);
+ spin_unlock_irqrestore(&pdata->tx_lock, flags1);
}
if (RX_INTERRUPT(dma_interrupt_status)) {
@@ -1046,6 +1049,10 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
int length;
int buf_per_desc;
union appnic_queue_pointer queue;
+ unsigned long flags;
+
+ if (!spin_trylock_irqsave(&pdata->tx_lock, flags))
+ return NETDEV_TX_LOCKED;
length = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
@@ -1124,9 +1131,11 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
pdata->out_of_tx_descriptors++;
pr_err("%s: No transmit descriptors available!\n",
LSI_DRV_NAME);
+ spin_unlock_irqrestore(&pdata->tx_lock, flags);
return NETDEV_TX_BUSY;
}
+ spin_unlock_irqrestore(&pdata->tx_lock, flags);
/* Free the socket buffer. */
dev_kfree_skb(skb);
@@ -1525,6 +1534,7 @@ int appnic_init(struct net_device *dev)
/* Initialize the spinlocks. */
spin_lock_init(&pdata->dev_lock);
+ spin_lock_init(&pdata->tx_lock);
/* Take MAC out of reset. */
@@ -1650,6 +1660,8 @@ int appnic_init(struct net_device *dev)
dev->netdev_ops = &appnic_netdev_ops;
dev->ethtool_ops = &appnic_ethtool_ops;
+ dev->features |= NETIF_F_LLTX;
+
memset((void *) &pdata->napi, 0, sizeof(struct napi_struct));
netif_napi_add(dev, &pdata->napi,
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.h b/drivers/net/ethernet/lsi/lsi_acp_net.h
index ac891cf..b2622b4 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.h
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.h
@@ -190,6 +190,7 @@ struct appnic_device {
/* Spin Lock */
spinlock_t dev_lock;
+ spinlock_t tx_lock;
/* PHY */
struct mii_bus *mii_bus;
--
1.7.9.5
More information about the linux-yocto
mailing list