Commit 79a58c06 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: fix double use of queue-lock

Deadlock seen in an instance where the hwstamp configuration
is changed while the driver is running:

[ 3988.736671]  schedule_preempt_disabled+0xe/0x10
[ 3988.736676]  __mutex_lock.isra.5+0x276/0x4e0
[ 3988.736683]  __mutex_lock_slowpath+0x13/0x20
[ 3988.736687]  ? __mutex_lock_slowpath+0x13/0x20
[ 3988.736692]  mutex_lock+0x2f/0x40
[ 3988.736711]  ionic_stop_queues_reconfig+0x16/0x40 [ionic]
[ 3988.736726]  ionic_reconfigure_queues+0x43e/0xc90 [ionic]
[ 3988.736738]  ionic_lif_config_hwstamp_rxq_all+0x85/0x90 [ionic]
[ 3988.736751]  ionic_lif_hwstamp_set_ts_config+0x29c/0x360 [ionic]
[ 3988.736763]  ionic_lif_hwstamp_set+0x76/0xf0 [ionic]
[ 3988.736776]  ionic_eth_ioctl+0x33/0x40 [ionic]
[ 3988.736781]  dev_ifsioc+0x12c/0x420
[ 3988.736785]  dev_ioctl+0x316/0x720

This can be demonstrated with "ptp4l -m -i <intf>"

To fix this, we pull the use of the queue_lock further up above the
callers of ionic_reconfigure_queues() and ionic_stop_queues_reconfig().

Fixes: 7ee99fc5 ("ionic: pull hwstamp queue_lock up a level")
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d12e1c46
...@@ -582,7 +582,10 @@ static int ionic_set_ringparam(struct net_device *netdev, ...@@ -582,7 +582,10 @@ static int ionic_set_ringparam(struct net_device *netdev,
qparam.ntxq_descs = ring->tx_pending; qparam.ntxq_descs = ring->tx_pending;
qparam.nrxq_descs = ring->rx_pending; qparam.nrxq_descs = ring->rx_pending;
mutex_lock(&lif->queue_lock);
err = ionic_reconfigure_queues(lif, &qparam); err = ionic_reconfigure_queues(lif, &qparam);
mutex_unlock(&lif->queue_lock);
if (err) if (err)
netdev_info(netdev, "Ring reconfiguration failed, changes canceled: %d\n", err); netdev_info(netdev, "Ring reconfiguration failed, changes canceled: %d\n", err);
...@@ -679,7 +682,9 @@ static int ionic_set_channels(struct net_device *netdev, ...@@ -679,7 +682,9 @@ static int ionic_set_channels(struct net_device *netdev,
return 0; return 0;
} }
mutex_lock(&lif->queue_lock);
err = ionic_reconfigure_queues(lif, &qparam); err = ionic_reconfigure_queues(lif, &qparam);
mutex_unlock(&lif->queue_lock);
if (err) if (err)
netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err); netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err);
......
...@@ -1715,7 +1715,6 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) ...@@ -1715,7 +1715,6 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
static void ionic_stop_queues_reconfig(struct ionic_lif *lif) static void ionic_stop_queues_reconfig(struct ionic_lif *lif)
{ {
/* Stop and clean the queues before reconfiguration */ /* Stop and clean the queues before reconfiguration */
mutex_lock(&lif->queue_lock);
netif_device_detach(lif->netdev); netif_device_detach(lif->netdev);
ionic_stop_queues(lif); ionic_stop_queues(lif);
ionic_txrx_deinit(lif); ionic_txrx_deinit(lif);
...@@ -1734,8 +1733,7 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif) ...@@ -1734,8 +1733,7 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif)
* DOWN and UP to try to reset and clear the issue. * DOWN and UP to try to reset and clear the issue.
*/ */
err = ionic_txrx_init(lif); err = ionic_txrx_init(lif);
mutex_unlock(&lif->queue_lock); ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
ionic_link_status_check_request(lif, CAN_SLEEP);
netif_device_attach(lif->netdev); netif_device_attach(lif->netdev);
return err; return err;
...@@ -1765,9 +1763,13 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -1765,9 +1763,13 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
return 0; return 0;
} }
mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif); ionic_stop_queues_reconfig(lif);
netdev->mtu = new_mtu; netdev->mtu = new_mtu;
return ionic_start_queues_reconfig(lif); err = ionic_start_queues_reconfig(lif);
mutex_unlock(&lif->queue_lock);
return err;
} }
static void ionic_tx_timeout_work(struct work_struct *ws) static void ionic_tx_timeout_work(struct work_struct *ws)
...@@ -1783,8 +1785,10 @@ static void ionic_tx_timeout_work(struct work_struct *ws) ...@@ -1783,8 +1785,10 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
if (!netif_running(lif->netdev)) if (!netif_running(lif->netdev))
return; return;
mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif); ionic_stop_queues_reconfig(lif);
ionic_start_queues_reconfig(lif); ionic_start_queues_reconfig(lif);
mutex_unlock(&lif->queue_lock);
} }
static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue) static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment