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

Commit 1073daa4 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix deadlock between ATIO and HW lock



Move ATIO queue processing out of hardware_lock to prevent deadlock.

Fixes: 3bb67df5 ("qla2xxx: Check for online flag instead of active reset when transmitting responses")
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b6faaaf7
Loading
Loading
Loading
Loading
+4 −13
Original line number Diff line number Diff line
@@ -4859,19 +4859,10 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
			 */
			if (qla_tgt_mode_enabled(vha) ||
			    qla_dual_mode_enabled(vha)) {
				if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
					spin_lock_irqsave(&ha->tgt.atio_lock,
					    flags);
				spin_lock_irqsave(&ha->tgt.atio_lock, flags);
				qlt_24xx_process_atio_queue(vha, 0);
					spin_unlock_irqrestore(
					    &ha->tgt.atio_lock, flags);
				} else {
					spin_lock_irqsave(&ha->hardware_lock,
				spin_unlock_irqrestore(&ha->tgt.atio_lock,
				    flags);
					qlt_24xx_process_atio_queue(vha, 1);
					spin_unlock_irqrestore(
					    &ha->hardware_lock, flags);
				}
			}
		}
	}
+22 −26
Original line number Diff line number Diff line
@@ -3121,6 +3121,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
	uint16_t	mb[8];
	struct rsp_que *rsp;
	unsigned long	flags;
	bool process_atio = false;

	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
@@ -3181,22 +3182,13 @@ qla24xx_intr_handler(int irq, void *dev_id)
			qla24xx_process_response_queue(vha, rsp);
			break;
		case INTR_ATIO_QUE_UPDATE_27XX:
		case INTR_ATIO_QUE_UPDATE:{
			unsigned long flags2;
			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
			qlt_24xx_process_atio_queue(vha, 1);
			spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
		case INTR_ATIO_QUE_UPDATE:
			process_atio = true;
			break;
		}
		case INTR_ATIO_RSP_QUE_UPDATE: {
			unsigned long flags2;
			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
			qlt_24xx_process_atio_queue(vha, 1);
			spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);

		case INTR_ATIO_RSP_QUE_UPDATE:
			process_atio = true;
			qla24xx_process_response_queue(vha, rsp);
			break;
		}
		default:
			ql_dbg(ql_dbg_async, vha, 0x504f,
			    "Unrecognized interrupt type (%d).\n", stat * 0xff);
@@ -3210,6 +3202,12 @@ qla24xx_intr_handler(int irq, void *dev_id)
	qla2x00_handle_mbx_completion(ha, status);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	if (process_atio) {
		spin_lock_irqsave(&ha->tgt.atio_lock, flags);
		qlt_24xx_process_atio_queue(vha, 0);
		spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
	}

	return IRQ_HANDLED;
}

@@ -3256,6 +3254,7 @@ qla24xx_msix_default(int irq, void *dev_id)
	uint32_t	hccr;
	uint16_t	mb[8];
	unsigned long flags;
	bool process_atio = false;

	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
@@ -3312,22 +3311,13 @@ qla24xx_msix_default(int irq, void *dev_id)
			qla24xx_process_response_queue(vha, rsp);
			break;
		case INTR_ATIO_QUE_UPDATE_27XX:
		case INTR_ATIO_QUE_UPDATE:{
			unsigned long flags2;
			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
			qlt_24xx_process_atio_queue(vha, 1);
			spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
		case INTR_ATIO_QUE_UPDATE:
			process_atio = true;
			break;
		}
		case INTR_ATIO_RSP_QUE_UPDATE: {
			unsigned long flags2;
			spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
			qlt_24xx_process_atio_queue(vha, 1);
			spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);

		case INTR_ATIO_RSP_QUE_UPDATE:
			process_atio = true;
			qla24xx_process_response_queue(vha, rsp);
			break;
		}
		default:
			ql_dbg(ql_dbg_async, vha, 0x5051,
			    "Unrecognized interrupt type (%d).\n", stat & 0xff);
@@ -3338,6 +3328,12 @@ qla24xx_msix_default(int irq, void *dev_id)
	qla2x00_handle_mbx_completion(ha, status);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	if (process_atio) {
		spin_lock_irqsave(&ha->tgt.atio_lock, flags);
		qlt_24xx_process_atio_queue(vha, 0);
		spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
	}

	return IRQ_HANDLED;
}