From patchwork Fri Jun 30 17:18:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 9820171 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F40AB602B1 for ; Fri, 30 Jun 2017 17:19:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA66728669 for ; Fri, 30 Jun 2017 17:19:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CED22286BE; Fri, 30 Jun 2017 17:19:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F7C628669 for ; Fri, 30 Jun 2017 17:19:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752011AbdF3RTo (ORCPT ); Fri, 30 Jun 2017 13:19:44 -0400 Received: from mx2.suse.de ([195.135.220.15]:59922 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751792AbdF3RTi (ORCPT ); Fri, 30 Jun 2017 13:19:38 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id ACCA3AC69; Fri, 30 Jun 2017 17:18:38 +0000 (UTC) From: Hannes Reinecke To: "Martin K. Petersen" Cc: Christoph Hellwig , James Bottomley , linux-scsi@vger.kernel.org, Raghava Aditya Renukunta , Hannes Reinecke , Hannes Reinecke Subject: [PATCH 4/7] aacraid: use aac_tmf_callback for reset fib Date: Fri, 30 Jun 2017 19:18:09 +0200 Message-Id: <1498843092-76285-5-git-send-email-hare@suse.de> X-Mailer: git-send-email 1.8.5.6 In-Reply-To: <1498843092-76285-1-git-send-email-hare@suse.de> References: <1498843092-76285-1-git-send-email-hare@suse.de> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When sending a reset fib we shouldn't rely on the scsi command, but rather set the TMF status in the map_info->reset_state variable. That allows us to send a TMF independent on a scsi command. Signed-off-by: Hannes Reinecke Reviewed-by: Raghava Aditya Renukunta --- drivers/scsi/aacraid/linit.c | 99 +++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 57b2077..e5d2d91 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -814,8 +814,8 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) return ret; } -static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, - int bus, int cid, u64 tmf_lun) +static u8 aac_eh_tmf_lun_reset_fib(struct aac_hba_map_info *info, + struct fib *fib, u64 tmf_lun) { struct aac_hba_tm_req *tmf; u64 address; @@ -824,7 +824,7 @@ static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, tmf = (struct aac_hba_tm_req *)fib->hw_fib_va; memset(tmf, 0, sizeof(*tmf)); tmf->tmf = HBA_TMF_LUN_RESET; - tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus; + tmf->it_nexus = info->rmw_nexus; int_to_scsilun(tmf_lun, (struct scsi_lun *)tmf->lun); address = (u64)fib->hw_error_pa; @@ -838,8 +838,8 @@ static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, return HBA_IU_TYPE_SCSI_TM_REQ; } -static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, - int bus, int cid) +static u8 aac_eh_tmf_hard_reset_fib(struct aac_hba_map_info *info, + struct fib *fib) { struct aac_hba_reset_req *rst; u64 address; @@ -847,8 +847,7 @@ static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, /* already tried, start a hard reset now */ rst = (struct aac_hba_reset_req *)fib->hw_fib_va; memset(rst, 0, sizeof(*rst)); - /* reset_type is already zero... */ - rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus; + rst->it_nexus = info->rmw_nexus; address = (u64)fib->hw_error_pa; rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); @@ -860,6 +859,33 @@ static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, return HBA_IU_TYPE_SATA_REQ; } +void aac_tmf_callback(void *context, struct fib *fibptr) +{ + struct aac_hba_resp *err = + &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err; + struct aac_hba_map_info *info = context; + int res; + + switch (err->service_response) { + case HBA_RESP_SVCRES_TMF_REJECTED: + res = -1; + break; + case HBA_RESP_SVCRES_TMF_LUN_INVALID: + res = 0; + break; + case HBA_RESP_SVCRES_TMF_COMPLETE: + case HBA_RESP_SVCRES_TMF_SUCCEEDED: + res = 0; + break; + default: + res = -2; + break; + } + aac_fib_complete(fibptr); + + info->reset_state = res; +} + /* * aac_eh_dev_reset - Device reset command handling * @scsi_cmd: SCSI command block causing the reset @@ -870,6 +896,7 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) struct scsi_device * dev = cmd->device; struct Scsi_Host * host = dev->host; struct aac_dev * aac = (struct aac_dev *)host->hostdata; + struct aac_hba_map_info *info; int count; u32 bus, cid; struct fib *fib; @@ -879,8 +906,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) bus = aac_logical_to_phys(scmd_channel(cmd)); cid = scmd_id(cmd); + info = &aac->hba_map[bus][cid]; if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || - aac->hba_map[bus][cid].devtype != AAC_DEVTYPE_NATIVE_RAW) + info->devtype != AAC_DEVTYPE_NATIVE_RAW) + return FAILED; + + if (info->reset_state > 0) return FAILED; pr_err("%s: Host adapter reset request. SCSI hang ?\n", @@ -890,21 +921,19 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) if (!fib) return ret; - /* start a HBA_TMF_LUN_RESET TMF request */ - command = aac_eh_tmf_lun_reset_fib(aac, fib, bus, cid, - cmd->device->lun); + command = aac_eh_tmf_lun_reset_fib(info, fib, dev->lun); - cmd->SCp.sent_command = 0; + info->reset_state = 1; status = aac_hba_send(command, fib, - (fib_callback) aac_hba_callback, - (void *) cmd); + (fib_callback) aac_tmf_callback, + (void *) info); /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { - if (cmd->SCp.sent_command) { - ret = SUCCESS; + if (info->reset_state == 0) { + ret = info->reset_state == 0 ? SUCCESS : FAILED; break; } msleep(1000); @@ -923,6 +952,7 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) struct scsi_device * dev = cmd->device; struct Scsi_Host * host = dev->host; struct aac_dev * aac = (struct aac_dev *)host->hostdata; + struct aac_hba_map_info *info; int count; u32 bus, cid; int ret = FAILED; @@ -932,8 +962,12 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) bus = aac_logical_to_phys(scmd_channel(cmd)); cid = scmd_id(cmd); + info = &aac->hba_map[bus][cid]; if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || - aac->hba_map[bus][cid].devtype != AAC_DEVTYPE_NATIVE_RAW) + info->devtype != AAC_DEVTYPE_NATIVE_RAW) + return FAILED; + + if (info->reset_state > 0) return FAILED; pr_err("%s: Host adapter reset request. SCSI hang ?\n", @@ -945,18 +979,18 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) /* already tried, start a hard reset now */ - command = aac_eh_tmf_hard_reset_fib(aac, fib, bus, cid); + command = aac_eh_tmf_hard_reset_fib(info, fib); - cmd->SCp.sent_command = 0; + info->reset_state = 2; status = aac_hba_send(command, fib, - (fib_callback) aac_hba_callback, - (void *) cmd); + (fib_callback) aac_tmf_callback, + (void *) info); /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { - if (cmd->SCp.sent_command) { - ret = SUCCESS; + if (info->reset_state <= 0) { + ret = info->reset_state == 0 ? SUCCESS : FAILED; break; } msleep(1000); @@ -1044,8 +1078,23 @@ int aac_eh_host_reset(struct scsi_cmnd *cmd) && aac_check_reset && (aac_check_reset != -1 || !is_ignore_reset)) { /* Bypass wait for command quiesce */ - aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET); - ret = SUCCESS; + if (aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET) == 0) + ret = SUCCESS; + } + /* + * Reset EH state + */ + if (ret == SUCCESS) { + int bus, cid; + struct aac_hba_map_info *info; + + for (bus = 0; bus < AAC_MAX_BUSES; bus++) { + for (cid = 0; cid < AAC_MAX_TARGETS; cid++) { + info = &aac->hba_map[bus][cid]; + if (info->devtype == AAC_DEVTYPE_NATIVE_RAW) + info->reset_state = 0; + } + } } return ret; }