Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2083,6 +2083,7 @@ struct ql_adapter {
	u32 mailbox_in;
	u32 mailbox_out;
	struct mbox_params idc_mbc;
	struct mutex	mpi_mutex;

	int tx_ring_size;
	int rx_ring_size;
+1 −0
Original line number Diff line number Diff line
@@ -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_core_to_log, ql_mpi_core_to_log);
	init_completion(&qdev->ide_completion);
	mutex_init(&qdev->mpi_mutex);

	if (!cards_found) {
		dev_info(&pdev->dev, "%s\n", DRV_STRING);
+4 −8
Original line number Diff line number Diff line
@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
	int status;
	unsigned long count;

	mutex_lock(&qdev->mpi_mutex);

	/* Begin polled mode for MPI */
	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)
end:
	/* End polled mode for MPI */
	ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
	mutex_unlock(&qdev->mpi_mutex);
	return status;
}

@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev)
static int ql_set_port_cfg(struct ql_adapter *qdev)
{
	int status;
	rtnl_lock();
	status = ql_mb_set_port_cfg(qdev);
	rtnl_unlock();
	if (status)
		return status;
	status = ql_idc_wait(qdev);
@@ -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);
	int status;

	rtnl_lock();
	status = ql_mb_get_port_cfg(qdev);
	rtnl_unlock();
	if (status) {
		netif_err(qdev, drv, qdev->ndev,
			  "Bug: Failed to get port config data.\n");
@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work)
	u32 aen;
	int timeout;

	rtnl_lock();
	aen = mbcp->mbox_out[1] >> 16;
	timeout = (mbcp->mbox_out[1] >> 8) & 0xf;

@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work)
		}
		break;
	}
	rtnl_unlock();
}

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;
	int err = 0;

	rtnl_lock();
	mutex_lock(&qdev->mpi_mutex);
	/* Begin polled mode for MPI */
	ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));

@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work)

	/* End polled mode for MPI */
	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);
}