diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2010-12-11 06:06:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-12 18:02:57 -0500 |
commit | 4d7b6b5d247aa71ea27709b9eac1ba6e752fbe87 (patch) | |
tree | 0af7a055a47899bd8a6475e182628b5fb1daa5b2 /drivers | |
parent | 36eac2130cdbac08606bb2c05775e52ab79b163c (diff) |
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: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/qlge/qlge.h | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 12 |
3 files changed, 6 insertions, 8 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 22821398fc63..9787dff90d3f 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -2083,6 +2083,7 @@ struct ql_adapter { | |||
2083 | u32 mailbox_in; | 2083 | u32 mailbox_in; |
2084 | u32 mailbox_out; | 2084 | u32 mailbox_out; |
2085 | struct mbox_params idc_mbc; | 2085 | struct mbox_params idc_mbc; |
2086 | struct mutex mpi_mutex; | ||
2086 | 2087 | ||
2087 | int tx_ring_size; | 2088 | int tx_ring_size; |
2088 | int rx_ring_size; | 2089 | int rx_ring_size; |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 528eaef5308f..2555b1d34f34 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
4629 | INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); | 4629 | INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); |
4630 | INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log); | 4630 | INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log); |
4631 | init_completion(&qdev->ide_completion); | 4631 | init_completion(&qdev->ide_completion); |
4632 | mutex_init(&qdev->mpi_mutex); | ||
4632 | 4633 | ||
4633 | if (!cards_found) { | 4634 | if (!cards_found) { |
4634 | dev_info(&pdev->dev, "%s\n", DRV_STRING); | 4635 | dev_info(&pdev->dev, "%s\n", DRV_STRING); |
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 0e7c7c7ee164..a2e919bcb3c6 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
534 | int status; | 534 | int status; |
535 | unsigned long count; | 535 | unsigned long count; |
536 | 536 | ||
537 | mutex_lock(&qdev->mpi_mutex); | ||
537 | 538 | ||
538 | /* Begin polled mode for MPI */ | 539 | /* Begin polled mode for MPI */ |
539 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | 540 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); |
@@ -603,6 +604,7 @@ done: | |||
603 | end: | 604 | end: |
604 | /* End polled mode for MPI */ | 605 | /* End polled mode for MPI */ |
605 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | 606 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); |
607 | mutex_unlock(&qdev->mpi_mutex); | ||
606 | return status; | 608 | return status; |
607 | } | 609 | } |
608 | 610 | ||
@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev) | |||
1099 | static int ql_set_port_cfg(struct ql_adapter *qdev) | 1101 | static int ql_set_port_cfg(struct ql_adapter *qdev) |
1100 | { | 1102 | { |
1101 | int status; | 1103 | int status; |
1102 | rtnl_lock(); | ||
1103 | status = ql_mb_set_port_cfg(qdev); | 1104 | status = ql_mb_set_port_cfg(qdev); |
1104 | rtnl_unlock(); | ||
1105 | if (status) | 1105 | if (status) |
1106 | return status; | 1106 | return status; |
1107 | status = ql_idc_wait(qdev); | 1107 | status = ql_idc_wait(qdev); |
@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work) | |||
1122 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); | 1122 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); |
1123 | int status; | 1123 | int status; |
1124 | 1124 | ||
1125 | rtnl_lock(); | ||
1126 | status = ql_mb_get_port_cfg(qdev); | 1125 | status = ql_mb_get_port_cfg(qdev); |
1127 | rtnl_unlock(); | ||
1128 | if (status) { | 1126 | if (status) { |
1129 | netif_err(qdev, drv, qdev->ndev, | 1127 | netif_err(qdev, drv, qdev->ndev, |
1130 | "Bug: Failed to get port config data.\n"); | 1128 | "Bug: Failed to get port config data.\n"); |
@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work) | |||
1167 | u32 aen; | 1165 | u32 aen; |
1168 | int timeout; | 1166 | int timeout; |
1169 | 1167 | ||
1170 | rtnl_lock(); | ||
1171 | aen = mbcp->mbox_out[1] >> 16; | 1168 | aen = mbcp->mbox_out[1] >> 16; |
1172 | timeout = (mbcp->mbox_out[1] >> 8) & 0xf; | 1169 | timeout = (mbcp->mbox_out[1] >> 8) & 0xf; |
1173 | 1170 | ||
@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work) | |||
1231 | } | 1228 | } |
1232 | break; | 1229 | break; |
1233 | } | 1230 | } |
1234 | rtnl_unlock(); | ||
1235 | } | 1231 | } |
1236 | 1232 | ||
1237 | void ql_mpi_work(struct work_struct *work) | 1233 | void ql_mpi_work(struct work_struct *work) |
@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work) | |||
1242 | struct mbox_params *mbcp = &mbc; | 1238 | struct mbox_params *mbcp = &mbc; |
1243 | int err = 0; | 1239 | int err = 0; |
1244 | 1240 | ||
1245 | rtnl_lock(); | 1241 | mutex_lock(&qdev->mpi_mutex); |
1246 | /* Begin polled mode for MPI */ | 1242 | /* Begin polled mode for MPI */ |
1247 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | 1243 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); |
1248 | 1244 | ||
@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work) | |||
1259 | 1255 | ||
1260 | /* End polled mode for MPI */ | 1256 | /* End polled mode for MPI */ |
1261 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | 1257 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); |
1262 | rtnl_unlock(); | 1258 | mutex_unlock(&qdev->mpi_mutex); |
1263 | ql_enable_completion_interrupt(qdev, 0); | 1259 | ql_enable_completion_interrupt(qdev, 0); |
1264 | } | 1260 | } |
1265 | 1261 | ||