Commit 4d7b6b5d247aa71ea27709b9eac1ba6e752fbe87
Committed by
David S. Miller
1 parent
36eac2130c
Exists in
master
and in
39 other branches
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>
Showing 3 changed files with 6 additions and 8 deletions Side-by-side Diff
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_main.c
... | ... | @@ -4629,6 +4629,7 @@ |
4629 | 4629 | INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); |
4630 | 4630 | INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log); |
4631 | 4631 | init_completion(&qdev->ide_completion); |
4632 | + mutex_init(&qdev->mpi_mutex); | |
4632 | 4633 | |
4633 | 4634 | if (!cards_found) { |
4634 | 4635 | dev_info(&pdev->dev, "%s\n", DRV_STRING); |
drivers/net/qlge/qlge_mpi.c
... | ... | @@ -534,6 +534,7 @@ |
534 | 534 | int status; |
535 | 535 | unsigned long count; |
536 | 536 | |
537 | + mutex_lock(&qdev->mpi_mutex); | |
537 | 538 | |
538 | 539 | /* Begin polled mode for MPI */ |
539 | 540 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); |
... | ... | @@ -603,6 +604,7 @@ |
603 | 604 | end: |
604 | 605 | /* End polled mode for MPI */ |
605 | 606 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); |
607 | + mutex_unlock(&qdev->mpi_mutex); | |
606 | 608 | return status; |
607 | 609 | } |
608 | 610 | |
609 | 611 | |
... | ... | @@ -1099,9 +1101,7 @@ |
1099 | 1101 | static int ql_set_port_cfg(struct ql_adapter *qdev) |
1100 | 1102 | { |
1101 | 1103 | int status; |
1102 | - rtnl_lock(); | |
1103 | 1104 | status = ql_mb_set_port_cfg(qdev); |
1104 | - rtnl_unlock(); | |
1105 | 1105 | if (status) |
1106 | 1106 | return status; |
1107 | 1107 | status = ql_idc_wait(qdev); |
1108 | 1108 | |
... | ... | @@ -1122,9 +1122,7 @@ |
1122 | 1122 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); |
1123 | 1123 | int status; |
1124 | 1124 | |
1125 | - rtnl_lock(); | |
1126 | 1125 | status = ql_mb_get_port_cfg(qdev); |
1127 | - rtnl_unlock(); | |
1128 | 1126 | if (status) { |
1129 | 1127 | netif_err(qdev, drv, qdev->ndev, |
1130 | 1128 | "Bug: Failed to get port config data.\n"); |
... | ... | @@ -1167,7 +1165,6 @@ |
1167 | 1165 | u32 aen; |
1168 | 1166 | int timeout; |
1169 | 1167 | |
1170 | - rtnl_lock(); | |
1171 | 1168 | aen = mbcp->mbox_out[1] >> 16; |
1172 | 1169 | timeout = (mbcp->mbox_out[1] >> 8) & 0xf; |
1173 | 1170 | |
... | ... | @@ -1231,7 +1228,6 @@ |
1231 | 1228 | } |
1232 | 1229 | break; |
1233 | 1230 | } |
1234 | - rtnl_unlock(); | |
1235 | 1231 | } |
1236 | 1232 | |
1237 | 1233 | void ql_mpi_work(struct work_struct *work) |
... | ... | @@ -1242,7 +1238,7 @@ |
1242 | 1238 | struct mbox_params *mbcp = &mbc; |
1243 | 1239 | int err = 0; |
1244 | 1240 | |
1245 | - rtnl_lock(); | |
1241 | + mutex_lock(&qdev->mpi_mutex); | |
1246 | 1242 | /* Begin polled mode for MPI */ |
1247 | 1243 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); |
1248 | 1244 | |
... | ... | @@ -1259,7 +1255,7 @@ |
1259 | 1255 | |
1260 | 1256 | /* End polled mode for MPI */ |
1261 | 1257 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); |
1262 | - rtnl_unlock(); | |
1258 | + mutex_unlock(&qdev->mpi_mutex); | |
1263 | 1259 | ql_enable_completion_interrupt(qdev, 0); |
1264 | 1260 | } |
1265 | 1261 |