Commit e2fac6c4 authored by Suganath Prabu S's avatar Suganath Prabu S Committed by Martin K. Petersen
Browse files

scsi: mpt3sas: Fix deadlock while cancelling the running firmware event

Do not cancel current running firmware event work if the event type is
different from MPT3SAS_REMOVE_UNRESPONDING_DEVICES.  Otherwise a deadlock
can be observed while cancelling the current firmware event work if a hard
reset operation is called as part of processing the current event.

Link: https://lore.kernel.org/r/20210518051625.1596742-2-suganath-prabu.subramani@broadcom.com


Signed-off-by: default avatarSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ea2f0f77
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -3697,6 +3697,28 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
	ioc->fw_events_cleanup = 1;
	while ((fw_event = dequeue_next_fw_event(ioc)) ||
	     (fw_event = ioc->current_event)) {

		/*
		 * Don't call cancel_work_sync() for current_event
		 * other than MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
		 * otherwise we may observe deadlock if current
		 * hard reset issued as part of processing the current_event.
		 *
		 * Orginal logic of cleaning the current_event is added
		 * for handling the back to back host reset issued by the user.
		 * i.e. during back to back host reset, driver use to process
		 * the two instances of MPT3SAS_REMOVE_UNRESPONDING_DEVICES
		 * event back to back and this made the drives to unregister
		 * the devices from SML.
		 */

		if (fw_event == ioc->current_event &&
		    ioc->current_event->event !=
		    MPT3SAS_REMOVE_UNRESPONDING_DEVICES) {
			ioc->current_event = NULL;
			continue;
		}

		/*
		 * Wait on the fw_event to complete. If this returns 1, then
		 * the event was never executed, and we need a put for the