Commit c8dd61ef authored by Sumit.Saxena@avagotech.com's avatar Sumit.Saxena@avagotech.com Committed by Christoph Hellwig
Browse files

megaraid_sas: complete outstanding IOCTLs before killing adapter



Driver calls megasas_complete_cmd() to call wake_up() for each MFI frame
that was issued through the ioctl() interface prior to the kill adapter.
This ensures userspace ioctl() system calls issued just before a kill
adapter don't get stuck in wait state and IOCTLs are returned to
the application.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarSumit Saxena <sumit.saxena@avagotech.com>
Signed-off-by: default avatarChaitra Basappa <chaitra.basappa@avagotech.com>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent c2ced171
Loading
Loading
Loading
Loading
+54 −11
Original line number Diff line number Diff line
@@ -1692,22 +1692,66 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
	return 0;
}

/*
* megasas_complete_outstanding_ioctls - Complete outstanding ioctls after a
*                                       kill adapter
* @instance:				Adapter soft state
*
*/
void megasas_complete_outstanding_ioctls(struct megasas_instance *instance)
{
	int i;
	struct megasas_cmd *cmd_mfi;
	struct megasas_cmd_fusion *cmd_fusion;
	struct fusion_context *fusion = instance->ctrl_context;

	/* Find all outstanding ioctls */
	if (fusion) {
		for (i = 0; i < instance->max_fw_cmds; i++) {
			cmd_fusion = fusion->cmd_list[i];
			if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
				cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
				if (cmd_mfi->sync_cmd &&
					cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)
					megasas_complete_cmd(instance,
							     cmd_mfi, DID_OK);
			}
		}
	} else {
		for (i = 0; i < instance->max_fw_cmds; i++) {
			cmd_mfi = instance->cmd_list[i];
			if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd !=
				MFI_CMD_ABORT)
				megasas_complete_cmd(instance, cmd_mfi, DID_OK);
		}
	}
}


void megaraid_sas_kill_hba(struct megasas_instance *instance)
{
	/* Set critical error to block I/O & ioctls in case caller didn't */
	instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
	/* Wait 1 second to ensure IO or ioctls in build have posted */
	msleep(1000);
	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
		(instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
		(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
		(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
		(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
		writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
		writel(MFI_STOP_ADP,
			&instance->reg_set->doorbell);
		/* Flush */
		readl(&instance->reg_set->doorbell);
		if (instance->mpio && instance->requestorId)
			memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
	} else {
		writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
		writel(MFI_STOP_ADP,
			&instance->reg_set->inbound_doorbell);
	}
	/* Complete outstanding ioctls when adapter is killed */
	megasas_complete_outstanding_ioctls(instance);
}

 /**
@@ -3031,10 +3075,9 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
					"was tried multiple times during reset."
					"Shutting down the HBA\n",
					cmd, cmd->scmd, cmd->sync_cmd);
				instance->instancet->disable_intr(instance);
				atomic_set(&instance->fw_reset_no_pci_access, 1);
				megaraid_sas_kill_hba(instance);

				instance->adprecovery =
						MEGASAS_HW_CRITICAL_ERROR;
				return;
			}
		}
@@ -3168,8 +3211,8 @@ process_fw_state_change_wq(struct work_struct *work)
		if (megasas_transition_to_ready(instance, 1)) {
			printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");

			atomic_set(&instance->fw_reset_no_pci_access, 1);
			megaraid_sas_kill_hba(instance);
			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
			return ;
		}

+0 −4
Original line number Diff line number Diff line
@@ -2631,7 +2631,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
				instance->host->host_no);
			megaraid_sas_kill_hba(instance);
			instance->skip_heartbeat_timer_del = 1;
			instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
			retval = FAILED;
			goto out;
		}
@@ -2827,8 +2826,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
				dev_info(&instance->pdev->dev,
					"Failed from %s %d\n",
					__func__, __LINE__);
				instance->adprecovery =
					MEGASAS_HW_CRITICAL_ERROR;
				megaraid_sas_kill_hba(instance);
				retval = FAILED;
			}
@@ -2877,7 +2874,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
		       "adapter scsi%d.\n", instance->host->host_no);
		megaraid_sas_kill_hba(instance);
		instance->skip_heartbeat_timer_del = 1;
		instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
		retval = FAILED;
	} else {
		/* For VF: Restart HB timer if we didn't OCR */