Commit 4d7b6b5d247aa71ea27709b9eac1ba6e752fbe87

Authored by Ron Mercer
Committed by David S. Miller
1 parent 36eac2130c

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
... ... @@ -2083,6 +2083,7 @@
2083 2083 u32 mailbox_in;
2084 2084 u32 mailbox_out;
2085 2085 struct mbox_params idc_mbc;
  2086 + struct mutex mpi_mutex;
2086 2087  
2087 2088 int tx_ring_size;
2088 2089 int rx_ring_size;
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