Commit 4d7b6b5d authored by Ron Mercer's avatar Ron Mercer Committed by David S. Miller

qlge: Fix deadlock when cancelling worker.

Removing usage of rtnl_lock() to protect firmware interface registers.
These registers are accessed in some worker threads and can create a
deadlock if rtnl_lock is taken by upper layers while the worker is still
pending.
We remove rtnl_lock and use a driver mutex just while mailboxes are
accessed.
Signed-off-by: default avatarRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 36eac213
...@@ -2083,6 +2083,7 @@ struct ql_adapter { ...@@ -2083,6 +2083,7 @@ struct ql_adapter {
u32 mailbox_in; u32 mailbox_in;
u32 mailbox_out; u32 mailbox_out;
struct mbox_params idc_mbc; struct mbox_params idc_mbc;
struct mutex mpi_mutex;
int tx_ring_size; int tx_ring_size;
int rx_ring_size; int rx_ring_size;
......
...@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, ...@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log); INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log);
init_completion(&qdev->ide_completion); init_completion(&qdev->ide_completion);
mutex_init(&qdev->mpi_mutex);
if (!cards_found) { if (!cards_found) {
dev_info(&pdev->dev, "%s\n", DRV_STRING); dev_info(&pdev->dev, "%s\n", DRV_STRING);
......
...@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) ...@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
int status; int status;
unsigned long count; unsigned long count;
mutex_lock(&qdev->mpi_mutex);
/* Begin polled mode for MPI */ /* Begin polled mode for MPI */
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
...@@ -603,6 +604,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) ...@@ -603,6 +604,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
end: end:
/* End polled mode for MPI */ /* End polled mode for MPI */
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
mutex_unlock(&qdev->mpi_mutex);
return status; return status;
} }
...@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev) ...@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev)
static int ql_set_port_cfg(struct ql_adapter *qdev) static int ql_set_port_cfg(struct ql_adapter *qdev)
{ {
int status; int status;
rtnl_lock();
status = ql_mb_set_port_cfg(qdev); status = ql_mb_set_port_cfg(qdev);
rtnl_unlock();
if (status) if (status)
return status; return status;
status = ql_idc_wait(qdev); status = ql_idc_wait(qdev);
...@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work) ...@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work)
container_of(work, struct ql_adapter, mpi_port_cfg_work.work); container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
int status; int status;
rtnl_lock();
status = ql_mb_get_port_cfg(qdev); status = ql_mb_get_port_cfg(qdev);
rtnl_unlock();
if (status) { if (status) {
netif_err(qdev, drv, qdev->ndev, netif_err(qdev, drv, qdev->ndev,
"Bug: Failed to get port config data.\n"); "Bug: Failed to get port config data.\n");
...@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work) ...@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work)
u32 aen; u32 aen;
int timeout; int timeout;
rtnl_lock();
aen = mbcp->mbox_out[1] >> 16; aen = mbcp->mbox_out[1] >> 16;
timeout = (mbcp->mbox_out[1] >> 8) & 0xf; timeout = (mbcp->mbox_out[1] >> 8) & 0xf;
...@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work) ...@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work)
} }
break; break;
} }
rtnl_unlock();
} }
void ql_mpi_work(struct work_struct *work) void ql_mpi_work(struct work_struct *work)
...@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work) ...@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work)
struct mbox_params *mbcp = &mbc; struct mbox_params *mbcp = &mbc;
int err = 0; int err = 0;
rtnl_lock(); mutex_lock(&qdev->mpi_mutex);
/* Begin polled mode for MPI */ /* Begin polled mode for MPI */
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
...@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work) ...@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work)
/* End polled mode for MPI */ /* End polled mode for MPI */
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
rtnl_unlock(); mutex_unlock(&qdev->mpi_mutex);
ql_enable_completion_interrupt(qdev, 0); ql_enable_completion_interrupt(qdev, 0);
} }
......
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