Commit 2e41f644 authored by Jon Mason's avatar Jon Mason Committed by David S. Miller

vxge: transmit timeout deadlock

Use a workqueue to handle the device reset during a transmit timeout, as
there can be a deadlock during bringup.  Also, set the netif carrier off
before the watchdog reset is started to prevent the timeout from
reoccurring while still processing the first.
Signed-off-by: default avatarJon Mason <jon.mason@exar.com>
Signed-off-by: default avatarRam Vepa <ram.vepa@exar.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dc66daa9
...@@ -1606,12 +1606,16 @@ static int do_vxge_reset(struct vxgedev *vdev, int event) ...@@ -1606,12 +1606,16 @@ static int do_vxge_reset(struct vxgedev *vdev, int event)
} }
if (event == VXGE_LL_FULL_RESET) { if (event == VXGE_LL_FULL_RESET) {
netif_carrier_off(vdev->ndev);
/* wait for all the vpath reset to complete */ /* wait for all the vpath reset to complete */
for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) { for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
while (test_bit(vp_id, &vdev->vp_reset)) while (test_bit(vp_id, &vdev->vp_reset))
msleep(50); msleep(50);
} }
netif_carrier_on(vdev->ndev);
/* if execution mode is set to debug, don't reset the adapter */ /* if execution mode is set to debug, don't reset the adapter */
if (unlikely(vdev->exec_mode)) { if (unlikely(vdev->exec_mode)) {
vxge_debug_init(VXGE_ERR, vxge_debug_init(VXGE_ERR,
...@@ -1765,9 +1769,14 @@ static int do_vxge_reset(struct vxgedev *vdev, int event) ...@@ -1765,9 +1769,14 @@ static int do_vxge_reset(struct vxgedev *vdev, int event)
* *
* driver may reset the chip on events of serr, eccerr, etc * driver may reset the chip on events of serr, eccerr, etc
*/ */
static int vxge_reset(struct vxgedev *vdev) static void vxge_reset(struct work_struct *work)
{ {
return do_vxge_reset(vdev, VXGE_LL_FULL_RESET); struct vxgedev *vdev = container_of(work, struct vxgedev, reset_task);
if (!netif_running(vdev->ndev))
return;
do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
} }
/** /**
...@@ -3111,8 +3120,7 @@ static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -3111,8 +3120,7 @@ static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* This function is triggered if the Tx Queue is stopped * This function is triggered if the Tx Queue is stopped
* for a pre-defined amount of time when the Interface is still up. * for a pre-defined amount of time when the Interface is still up.
*/ */
static void static void vxge_tx_watchdog(struct net_device *dev)
vxge_tx_watchdog(struct net_device *dev)
{ {
struct vxgedev *vdev; struct vxgedev *vdev;
...@@ -3122,7 +3130,7 @@ vxge_tx_watchdog(struct net_device *dev) ...@@ -3122,7 +3130,7 @@ vxge_tx_watchdog(struct net_device *dev)
vdev->cric_err_event = VXGE_HW_EVENT_RESET_START; vdev->cric_err_event = VXGE_HW_EVENT_RESET_START;
vxge_reset(vdev); schedule_work(&vdev->reset_task);
vxge_debug_entryexit(VXGE_TRACE, vxge_debug_entryexit(VXGE_TRACE,
"%s:%d Exiting...", __func__, __LINE__); "%s:%d Exiting...", __func__, __LINE__);
} }
...@@ -3324,6 +3332,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ...@@ -3324,6 +3332,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
ndev->netdev_ops = &vxge_netdev_ops; ndev->netdev_ops = &vxge_netdev_ops;
ndev->watchdog_timeo = VXGE_LL_WATCH_DOG_TIMEOUT; ndev->watchdog_timeo = VXGE_LL_WATCH_DOG_TIMEOUT;
INIT_WORK(&vdev->reset_task, vxge_reset);
vxge_initialize_ethtool_ops(ndev); vxge_initialize_ethtool_ops(ndev);
......
...@@ -395,6 +395,7 @@ struct vxgedev { ...@@ -395,6 +395,7 @@ struct vxgedev {
u32 level_err; u32 level_err;
u32 level_trace; u32 level_trace;
char fw_version[VXGE_HW_FW_STRLEN]; char fw_version[VXGE_HW_FW_STRLEN];
struct work_struct reset_task;
}; };
struct vxge_rx_priv { struct vxge_rx_priv {
......
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