diff options
author | Alex Shi <alex.shi@linaro.org> | 2016-09-20 15:18:54 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2016-09-20 15:18:54 +0800 |
commit | 5f87c475f82a75e10bc6e249b7471349f1ef1636 (patch) | |
tree | df697b570c923c722b5ba24f502c6abdbb5e05f1 /drivers/scsi | |
parent | d3a1d035ef89cfb89cf6e2128d44b95771f2c7b4 (diff) | |
parent | d2d693d1ba7d93ec7c5db8aca2da29a4c91f6782 (diff) |
Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
Conflicts:
in fs/proc/task_mmu.c:
looks like vma_get_anon_name() want have a name for anonymous
vma when there is no name used in vma. commit: 586278d78bf
The name show is after any other names, so it maybe covered.
but anyway, it just a show here.
Diffstat (limited to 'drivers/scsi')
24 files changed, 551 insertions, 511 deletions
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 54195a117f72..f78cc943d230 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) struct fib *fibptr; struct hw_fib * hw_fib = (struct hw_fib *)0; dma_addr_t hw_fib_pa = (dma_addr_t)0LL; - unsigned size; + unsigned int size, osize; int retval; if (dev->in_reset) { @@ -87,7 +87,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) * will not overrun the buffer when we copy the memory. Return * an error if we would. */ - size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr); + osize = size = le16_to_cpu(kfib->header.Size) + + sizeof(struct aac_fibhdr); if (size < le16_to_cpu(kfib->header.SenderSize)) size = le16_to_cpu(kfib->header.SenderSize); if (size > dev->max_fib_size) { @@ -118,6 +119,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) goto cleanup; } + /* Sanity check the second copy */ + if ((osize != le16_to_cpu(kfib->header.Size) + + sizeof(struct aac_fibhdr)) + || (size < le16_to_cpu(kfib->header.SenderSize))) { + retval = -EINVAL; + goto cleanup; + } + if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) { aac_adapter_interrupt(dev); /* diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 333db5953607..41f9a00e4f74 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2664,7 +2664,7 @@ static bool arcmsr_hbaB_get_config(struct AdapterControlBlock *acb) if (!arcmsr_hbaB_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); - return false; + goto err_free_dma; } count = 8; while (count){ @@ -2694,19 +2694,23 @@ static bool arcmsr_hbaB_get_config(struct AdapterControlBlock *acb) acb->firm_model, acb->firm_version); - acb->signature = readl(®->message_rwbuffer[1]); + acb->signature = readl(®->message_rwbuffer[0]); /*firm_signature,1,00-03*/ - acb->firm_request_len = readl(®->message_rwbuffer[2]); + acb->firm_request_len = readl(®->message_rwbuffer[1]); /*firm_request_len,1,04-07*/ - acb->firm_numbers_queue = readl(®->message_rwbuffer[3]); + acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); /*firm_numbers_queue,2,08-11*/ - acb->firm_sdram_size = readl(®->message_rwbuffer[4]); + acb->firm_sdram_size = readl(®->message_rwbuffer[3]); /*firm_sdram_size,3,12-15*/ - acb->firm_hd_channels = readl(®->message_rwbuffer[5]); + acb->firm_hd_channels = readl(®->message_rwbuffer[4]); /*firm_ide_channels,4,16-19*/ acb->firm_cfg_version = readl(®->message_rwbuffer[25]); /*firm_cfg_version,25,100-103*/ /*firm_ide_channels,4,16-19*/ return true; +err_free_dma: + dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, + acb->dma_coherent2, acb->dma_coherent_handle2); + return false; } static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB) @@ -2880,15 +2884,15 @@ static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb) iop_device_map++; count--; } - acb->signature = readl(®->msgcode_rwbuffer[1]); + acb->signature = readl(®->msgcode_rwbuffer[0]); /*firm_signature,1,00-03*/ - acb->firm_request_len = readl(®->msgcode_rwbuffer[2]); + acb->firm_request_len = readl(®->msgcode_rwbuffer[1]); /*firm_request_len,1,04-07*/ - acb->firm_numbers_queue = readl(®->msgcode_rwbuffer[3]); + acb->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]); /*firm_numbers_queue,2,08-11*/ - acb->firm_sdram_size = readl(®->msgcode_rwbuffer[4]); + acb->firm_sdram_size = readl(®->msgcode_rwbuffer[3]); /*firm_sdram_size,3,12-15*/ - acb->firm_hd_channels = readl(®->msgcode_rwbuffer[5]); + acb->firm_hd_channels = readl(®->msgcode_rwbuffer[4]); /*firm_hd_channels,4,16-19*/ acb->firm_cfg_version = readl(®->msgcode_rwbuffer[25]); pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index fa09d4be2b53..2b456ca69d5c 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1181,8 +1181,9 @@ static const char * const snstext[] = { /* Get sense key string or NULL if not available */ const char * -scsi_sense_key_string(unsigned char key) { - if (key <= 0xE) +scsi_sense_key_string(unsigned char key) +{ + if (key < ARRAY_SIZE(snstext)) return snstext[key]; return NULL; } diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index c11cd193f896..5ada9268a450 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -165,6 +165,8 @@ struct afu { struct sisl_host_map __iomem *host_map; /* MC host map */ struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */ + struct kref mapcount; + ctx_hndl_t ctx_hndl; /* master's context handle */ u64 *hrrq_start; u64 *hrrq_end; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 1e5bf0ca81da..c86847c68448 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -289,7 +289,7 @@ static void context_reset(struct afu_cmd *cmd) atomic64_set(&afu->room, room); if (room) goto write_rrin; - udelay(nretry); + udelay(1 << nretry); } while (nretry++ < MC_ROOM_RETRY_CNT); pr_err("%s: no cmd_room to send reset\n", __func__); @@ -303,7 +303,7 @@ write_rrin: if (rrin != 0x1) break; /* Double delay each time */ - udelay(2 << nretry); + udelay(1 << nretry); } while (nretry++ < MC_ROOM_RETRY_CNT); } @@ -338,7 +338,7 @@ retry: atomic64_set(&afu->room, room); if (room) goto write_ioarrin; - udelay(nretry); + udelay(1 << nretry); } while (nretry++ < MC_ROOM_RETRY_CNT); dev_err(dev, "%s: no cmd_room to send 0x%X\n", @@ -352,7 +352,7 @@ retry: * afu->room. */ if (nretry++ < MC_ROOM_RETRY_CNT) { - udelay(nretry); + udelay(1 << nretry); goto retry; } @@ -368,6 +368,7 @@ out: no_room: afu->read_room = true; + kref_get(&cfg->afu->mapcount); schedule_work(&cfg->work_q); rc = SCSI_MLQUEUE_HOST_BUSY; goto out; @@ -473,6 +474,16 @@ out: return rc; } +static void afu_unmap(struct kref *ref) +{ + struct afu *afu = container_of(ref, struct afu, mapcount); + + if (likely(afu->afu_map)) { + cxl_psa_unmap((void __iomem *)afu->afu_map); + afu->afu_map = NULL; + } +} + /** * cxlflash_driver_info() - information handler for this host driver * @host: SCSI host associated with device. @@ -503,6 +514,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) ulong lock_flags; short lflag = 0; int rc = 0; + int kref_got = 0; dev_dbg_ratelimited(dev, "%s: (scp=%p) %d/%d/%d/%llu " "cdb=(%08X-%08X-%08X-%08X)\n", @@ -547,6 +559,9 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) goto out; } + kref_get(&cfg->afu->mapcount); + kref_got = 1; + cmd->rcb.ctx_id = afu->ctx_hndl; cmd->rcb.port_sel = port_sel; cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); @@ -587,6 +602,8 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) } out: + if (kref_got) + kref_put(&afu->mapcount, afu_unmap); pr_devel("%s: returning rc=%d\n", __func__, rc); return rc; } @@ -632,20 +649,36 @@ static void free_mem(struct cxlflash_cfg *cfg) * @cfg: Internal structure associated with the host. * * Safe to call with AFU in a partially allocated/initialized state. + * + * Cleans up all state associated with the command queue, and unmaps + * the MMIO space. + * + * - complete() will take care of commands we initiated (they'll be checked + * in as part of the cleanup that occurs after the completion) + * + * - cmd_checkin() will take care of entries that we did not initiate and that + * have not (and will not) complete because they are sitting on a [now stale] + * hardware queue */ static void stop_afu(struct cxlflash_cfg *cfg) { int i; struct afu *afu = cfg->afu; + struct afu_cmd *cmd; if (likely(afu)) { - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) - complete(&afu->cmd[i].cevent); + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { + cmd = &afu->cmd[i]; + complete(&cmd->cevent); + if (!atomic_read(&cmd->free)) + cmd_checkin(cmd); + } if (likely(afu->afu_map)) { cxl_psa_unmap((void __iomem *)afu->afu_map); afu->afu_map = NULL; } + kref_put(&afu->mapcount, afu_unmap); } } @@ -731,8 +764,8 @@ static void cxlflash_remove(struct pci_dev *pdev) scsi_remove_host(cfg->host); /* fall through */ case INIT_STATE_AFU: - term_afu(cfg); cancel_work_sync(&cfg->work_q); + term_afu(cfg); case INIT_STATE_PCI: pci_release_regions(cfg->dev); pci_disable_device(pdev); @@ -1108,7 +1141,7 @@ static const struct asyc_intr_info ainfo[] = { {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET}, - {SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, 0}, + {SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, LINK_RESET}, {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST}, {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0}, @@ -1316,6 +1349,7 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) __func__, port); cfg->lr_state = LINK_RESET_REQUIRED; cfg->lr_port = port; + kref_get(&cfg->afu->mapcount); schedule_work(&cfg->work_q); } @@ -1336,6 +1370,7 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) if (info->action & SCAN_HOST) { atomic_inc(&cfg->scan_host_needed); + kref_get(&cfg->afu->mapcount); schedule_work(&cfg->work_q); } } @@ -1731,6 +1766,7 @@ static int init_afu(struct cxlflash_cfg *cfg) rc = -ENOMEM; goto err1; } + kref_init(&afu->mapcount); /* No byte reverse on reading afu_version or string will be backwards */ reg = readq(&afu->afu_map->global.regs.afu_version); @@ -1765,8 +1801,7 @@ out: return rc; err2: - cxl_psa_unmap((void __iomem *)afu->afu_map); - afu->afu_map = NULL; + kref_put(&afu->mapcount, afu_unmap); err1: term_mc(cfg, UNDO_START); goto out; @@ -2114,6 +2149,16 @@ static ssize_t lun_mode_store(struct device *dev, rc = kstrtouint(buf, 10, &lun_mode); if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) { afu->internal_lun = lun_mode; + + /* + * When configured for internal LUN, there is only one channel, + * channel number 0, else there will be 2 (default). + */ + if (afu->internal_lun) + shost->max_channel = 0; + else + shost->max_channel = NUM_FC_PORTS - 1; + afu_reset(cfg); scsi_scan_host(cfg->host); } @@ -2274,6 +2319,7 @@ static struct scsi_host_template driver_template = { * Device dependent values */ static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS }; +static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS }; /* * PCI device binding table @@ -2281,6 +2327,8 @@ static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS }; static struct pci_device_id cxlflash_pci_table[] = { {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals}, + {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_FLASH_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_flash_gt_vals}, {} }; @@ -2339,6 +2387,7 @@ static void cxlflash_worker_thread(struct work_struct *work) if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0) scsi_scan_host(cfg->host); + kref_put(&afu->mapcount, afu_unmap); } /** diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h index 60324566c14f..3d2d606fafb3 100644 --- a/drivers/scsi/cxlflash/main.h +++ b/drivers/scsi/cxlflash/main.h @@ -24,8 +24,8 @@ #define CXLFLASH_ADAPTER_NAME "IBM POWER CXL Flash Adapter" #define CXLFLASH_DRIVER_DATE "(August 13, 2015)" -#define PCI_DEVICE_ID_IBM_CORSA 0x04F0 -#define CXLFLASH_SUBS_DEV_ID 0x04F0 +#define PCI_DEVICE_ID_IBM_CORSA 0x04F0 +#define PCI_DEVICE_ID_IBM_FLASH_GT 0x0600 /* Since there is only one target, make it 0 */ #define CXLFLASH_TARGET 0 diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index cac2e6a50efd..babe7ccc1777 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c @@ -1380,7 +1380,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, } ctxid = cxl_process_element(ctx); - if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) { + if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); rc = -EPERM; goto err2; @@ -1508,7 +1508,7 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) } ctxid = cxl_process_element(ctx); - if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) { + if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); rc = -EPERM; goto err1; @@ -1590,6 +1590,13 @@ err1: * place at the same time and the failure was due to CXL services being * unable to keep up. * + * As this routine is called on ioctl context, it holds the ioctl r/w + * semaphore that is used to drain ioctls in recovery scenarios. The + * implementation to achieve the pacing described above (a local mutex) + * requires that the ioctl r/w semaphore be dropped and reacquired to + * avoid a 3-way deadlock when multiple process recoveries operate in + * parallel. + * * Because a user can detect an error condition before the kernel, it is * quite possible for this routine to act as the kernel's EEH detection * source (MMIO read of mbox_r). Because of this, there is a window of @@ -1617,9 +1624,17 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, int rc = 0; atomic_inc(&cfg->recovery_threads); + up_read(&cfg->ioctl_rwsem); rc = mutex_lock_interruptible(mutex); + down_read(&cfg->ioctl_rwsem); if (rc) goto out; + rc = check_state(cfg); + if (rc) { + dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc); + rc = -ENODEV; + goto out; + } dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", __func__, recover->reason, rctxid); diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c index a53f583e2d7b..50f8e9300770 100644 --- a/drivers/scsi/cxlflash/vlun.c +++ b/drivers/scsi/cxlflash/vlun.c @@ -1008,6 +1008,8 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) virt->last_lba = last_lba; virt->rsrc_handle = rsrc_handle; + if (lli->port_sel == BOTH_PORTS) + virt->hdr.return_flags |= DK_CXLFLASH_ALL_PORTS_ACTIVE; out: if (likely(ctxi)) put_context(ctxi); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b0e6fe46448d..80d3c740a8a8 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -72,6 +72,7 @@ void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *); void lpfc_retry_pport_discovery(struct lpfc_hba *); void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t); +void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b6fa257ea3e0..59ced8864b2f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -455,9 +455,9 @@ int lpfc_issue_reg_vfi(struct lpfc_vport *vport) { struct lpfc_hba *phba = vport->phba; - LPFC_MBOXQ_t *mboxq; + LPFC_MBOXQ_t *mboxq = NULL; struct lpfc_nodelist *ndlp; - struct lpfc_dmabuf *dmabuf; + struct lpfc_dmabuf *dmabuf = NULL; int rc = 0; /* move forward in case of SLI4 FC port loopback test and pt2pt mode */ @@ -471,25 +471,33 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) } } - dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); - if (!dmabuf) { + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { rc = -ENOMEM; goto fail; } - dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys); - if (!dmabuf->virt) { - rc = -ENOMEM; - goto fail_free_dmabuf; - } - mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mboxq) { - rc = -ENOMEM; - goto fail_free_coherent; + /* Supply CSP's only if we are fabric connect or pt-to-pt connect */ + if ((vport->fc_flag & FC_FABRIC) || (vport->fc_flag & FC_PT2PT)) { + dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); + if (!dmabuf) { + rc = -ENOMEM; + goto fail; + } + dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys); + if (!dmabuf->virt) { + rc = -ENOMEM; + goto fail; + } + memcpy(dmabuf->virt, &phba->fc_fabparam, + sizeof(struct serv_parm)); } + vport->port_state = LPFC_FABRIC_CFG_LINK; - memcpy(dmabuf->virt, &phba->fc_fabparam, sizeof(vport->fc_sparam)); - lpfc_reg_vfi(mboxq, vport, dmabuf->phys); + if (dmabuf) + lpfc_reg_vfi(mboxq, vport, dmabuf->phys); + else + lpfc_reg_vfi(mboxq, vport, 0); mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi; mboxq->vport = vport; @@ -497,17 +505,19 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { rc = -ENXIO; - goto fail_free_mbox; + goto fail; } return 0; -fail_free_mbox: - mempool_free(mboxq, phba->mbox_mem_pool); -fail_free_coherent: - lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); -fail_free_dmabuf: - kfree(dmabuf); fail: + if (mboxq) + mempool_free(mboxq, phba->mbox_mem_pool); + if (dmabuf) { + if (dmabuf->virt) + lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); + kfree(dmabuf); + } + lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, "0289 Issue Register VFI failed: Err %d\n", rc); @@ -711,9 +721,10 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * For FC we need to do some special processing because of the SLI * Port's default settings of the Common Service Parameters. */ - if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) { + if ((phba->sli_rev == LPFC_SLI_REV4) && + (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)) { /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */ - if ((phba->sli_rev == LPFC_SLI_REV4) && fabric_param_changed) + if (fabric_param_changed) lpfc_unregister_fcf_prep(phba); /* This should just update the VFI CSPs*/ @@ -824,13 +835,21 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + vport->fc_flag |= FC_PT2PT; spin_unlock_irq(shost->host_lock); - phba->fc_edtov = FF_DEF_EDTOV; - phba->fc_ratov = FF_DEF_RATOV; + /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */ + if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) { + lpfc_unregister_fcf_prep(phba); + + spin_lock_irq(shost->host_lock); + vport->fc_flag &= ~FC_VFI_REGISTERED; + spin_unlock_irq(shost->host_lock); + phba->fc_topology_changed = 0; + } + rc = memcmp(&vport->fc_portname, &sp->portName, sizeof(vport->fc_portname)); - memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); if (rc >= 0) { /* This side will initiate the PLOGI */ @@ -839,38 +858,14 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_unlock_irq(shost->host_lock); /* - * N_Port ID cannot be 0, set our to LocalID the other - * side will be RemoteID. + * N_Port ID cannot be 0, set our Id to LocalID + * the other side will be RemoteID. */ /* not equal */ if (rc) vport->fc_myDID = PT2PT_LocalID; - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) - goto fail; - - lpfc_config_link(phba, mbox); - - mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - goto fail; - } - - /* - * For SLI4, the VFI/VPI are registered AFTER the - * Nport with the higher WWPN sends the PLOGI with - * an assigned NPortId. - */ - - /* not equal */ - if ((phba->sli_rev == LPFC_SLI_REV4) && rc) - lpfc_issue_reg_vfi(vport); - /* Decrement ndlp reference count indicating that ndlp can be * safely released when other references to it are done. */ @@ -912,29 +907,20 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* If we are pt2pt with another NPort, force NPIV off! */ phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; - spin_lock_irq(shost->host_lock); - vport->fc_flag |= FC_PT2PT; - spin_unlock_irq(shost->host_lock); - /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */ - if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) { - lpfc_unregister_fcf_prep(phba); + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mbox) + goto fail; - /* The FC_VFI_REGISTERED flag will get clear in the cmpl - * handler for unreg_vfi, but if we don't force the - * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be - * built with the update bit set instead of just the vp bit to - * change the Nport ID. We need to have the vp set and the - * Upd cleared on topology changes. - */ - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_VFI_REGISTERED; - spin_unlock_irq(shost->host_lock); - phba->fc_topology_changed = 0; - lpfc_issue_reg_vfi(vport); + lpfc_config_link(phba, mbox); + + mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(mbox, phba->mbox_mem_pool); + goto fail; } - /* Start discovery - this should just do CLEAR_LA */ - lpfc_disc_start(vport); return 0; fail: return -ENXIO; @@ -1157,6 +1143,7 @@ flogifail: spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_DISCOVERY; spin_unlock_irq(&phba->hbalock); + lpfc_nlp_put(ndlp); if (!lpfc_error_lost_link(irsp)) { @@ -3792,14 +3779,17 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE); } + + ndlp->nlp_flag |= NLP_REG_LOGIN_SEND; if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) != MBX_NOT_FINISHED) goto out; - else - /* Decrement the ndlp reference count we - * set for this failed mailbox command. - */ - lpfc_nlp_put(ndlp); + + /* Decrement the ndlp reference count we + * set for this failed mailbox command. + */ + lpfc_nlp_put(ndlp); + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; /* ELS rsp: Cannot issue reg_login for <NPortid> */ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, @@ -3856,6 +3846,7 @@ out: * the routine lpfc_els_free_iocb. */ cmdiocb->context1 = NULL; + } lpfc_els_free_iocb(phba, cmdiocb); @@ -3898,6 +3889,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, IOCB_t *oldcmd; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; + struct serv_parm *sp; uint16_t cmdsize; int rc; ELS_PKT *els_pkt_ptr; @@ -3927,6 +3919,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, "Issue ACC: did:x%x flg:x%x", ndlp->nlp_DID, ndlp->nlp_flag, 0); break; + case ELS_CMD_FLOGI: case ELS_CMD_PLOGI: cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t)); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, @@ -3944,10 +3937,34 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); - memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm)); + sp = (struct serv_parm *)pcmd; + + if (flag == ELS_CMD_FLOGI) { + /* Copy the received service parameters back */ + memcpy(sp, &phba->fc_fabparam, + sizeof(struct serv_parm)); + + /* Clear the F_Port bit */ + sp->cmn.fPort = 0; + + /* Mark all class service parameters as invalid */ + sp->cls1.classValid = 0; + sp->cls2.classValid = 0; + sp->cls3.classValid = 0; + sp->cls4.classValid = 0; + + /* Copy our worldwide names */ + memcpy(&sp->portName, &vport->fc_sparam.portName, + sizeof(struct lpfc_name)); + memcpy(&sp->nodeName, &vport->fc_sparam.nodeName, + sizeof(struct lpfc_name)); + } else { + memcpy(pcmd, &vport->fc_sparam, + sizeof(struct serv_parm)); + } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "Issue ACC PLOGI: did:x%x flg:x%x", + "Issue ACC FLOGI/PLOGI: did:x%x flg:x%x", ndlp->nlp_DID, ndlp->nlp_flag, 0); break; case ELS_CMD_PRLO: @@ -4681,28 +4698,25 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) desc->tag = cpu_to_be32(RDP_PORT_SPEED_DESC_TAG); - switch (phba->sli4_hba.link_state.speed) { - case LPFC_FC_LA_SPEED_1G: + switch (phba->fc_linkspeed) { + case LPFC_LINK_SPEED_1GHZ: rdp_speed = RDP_PS_1GB; break; - case LPFC_FC_LA_SPEED_2G: + case LPFC_LINK_SPEED_2GHZ: rdp_speed = RDP_PS_2GB; break; - case LPFC_FC_LA_SPEED_4G: + case LPFC_LINK_SPEED_4GHZ: rdp_speed = RDP_PS_4GB; break; - case LPFC_FC_LA_SPEED_8G: + case LPFC_LINK_SPEED_8GHZ: rdp_speed = RDP_PS_8GB; break; - case LPFC_FC_LA_SPEED_10G: + case LPFC_LINK_SPEED_10GHZ: rdp_speed = RDP_PS_10GB; break; - case LPFC_FC_LA_SPEED_16G: + case LPFC_LINK_SPEED_16GHZ: rdp_speed = RDP_PS_16GB; break; - case LPFC_FC_LA_SPEED_32G: - rdp_speed = RDP_PS_32GB; - break; default: rdp_speed = RDP_PS_UNKNOWN; break; @@ -5739,7 +5753,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, IOCB_t *icmd = &cmdiocb->iocb; struct serv_parm *sp; LPFC_MBOXQ_t *mbox; - struct ls_rjt stat; uint32_t cmd, did; int rc; uint32_t fc_flag = 0; @@ -5765,135 +5778,92 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, return 1; } - if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) { - /* For a FLOGI we accept, then if our portname is greater - * then the remote portname we initiate Nport login. - */ + (void) lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1); - rc = memcmp(&vport->fc_portname, &sp->portName, - sizeof(struct lpfc_name)); - if (!rc) { - if (phba->sli_rev < LPFC_SLI_REV4) { - mbox = mempool_alloc(phba->mbox_mem_pool, - GFP_KERNEL); - if (!mbox) - return 1; - lpfc_linkdown(phba); - lpfc_init_link(phba, mbox, - phba->cfg_topology, - phba->cfg_link_speed); - mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; - mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, - MBX_NOWAIT); - lpfc_set_loopback_flag(phba); - if (rc == MBX_NOT_FINISHED) - mempool_free(mbox, phba->mbox_mem_pool); - return 1; - } else { - /* abort the flogi coming back to ourselves - * due to external loopback on the port. - */ - lpfc_els_abort_flogi(phba); - return 0; - } - } else if (rc > 0) { /* greater than */ - spin_lock_irq(shost->host_lock); - vport->fc_flag |= FC_PT2PT_PLOGI; - spin_unlock_irq(shost->host_lock); + /* + * If our portname is greater than the remote portname, + * then we initiate Nport login. + */ - /* If we have the high WWPN we can assign our own - * myDID; otherwise, we have to WAIT for a PLOGI - * from the remote NPort to find out what it - * will be. - */ - vport->fc_myDID = PT2PT_LocalID; - } else - vport->fc_myDID = PT2PT_RemoteID; + rc = memcmp(&vport->fc_portname, &sp->portName, + sizeof(struct lpfc_name)); - /* - * The vport state should go to LPFC_FLOGI only - * AFTER we issue a FLOGI, not receive one. + if (!rc) { + if (phba->sli_rev < LPFC_SLI_REV4) { + mbox = mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!mbox) + return 1; + lpfc_linkdown(phba); + lpfc_init_link(phba, mbox, + phba->cfg_topology, + phba->cfg_link_speed); + mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, + MBX_NOWAIT); + lpfc_set_loopback_flag(phba); + if (rc == MBX_NOT_FINISHED) + mempool_free(mbox, phba->mbox_mem_pool); + return 1; + } + + /* abort the flogi coming back to ourselves + * due to external loopback on the port. */ + lpfc_els_abort_flogi(phba); + return 0; + + } else if (rc > 0) { /* greater than */ spin_lock_irq(shost->host_lock); - fc_flag = vport->fc_flag; - port_state = vport->port_state; - vport->fc_flag |= FC_PT2PT; - vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + vport->fc_flag |= FC_PT2PT_PLOGI; spin_unlock_irq(shost->host_lock); - lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "3311 Rcv Flogi PS x%x new PS x%x " - "fc_flag x%x new fc_flag x%x\n", - port_state, vport->port_state, - fc_flag, vport->fc_flag); - /* - * We temporarily set fc_myDID to make it look like we are - * a Fabric. This is done just so we end up with the right - * did / sid on the FLOGI ACC rsp. + /* If we have the high WWPN we can assign our own + * myDID; otherwise, we have to WAIT for a PLOGI + * from the remote NPort to find out what it + * will be. */ - did = vport->fc_myDID; - vport->fc_myDID = Fabric_DID; - + vport->fc_myDID = PT2PT_LocalID; } else { - /* Reject this request because invalid parameters */ - stat.un.b.lsRjtRsvd0 = 0; - stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; - stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; - stat.un.b.vendorUnique = 0; - - /* - * We temporarily set fc_myDID to make it look like we are - * a Fabric. This is done just so we end up with the right - * did / sid on the FLOGI LS_RJT rsp. - */ - did = vport->fc_myDID; - vport->fc_myDID = Fabric_DID; - - lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, - NULL); + vport->fc_myDID = PT2PT_RemoteID; + } - /* Now lets put fc_myDID back to what its supposed to be */ - vport->fc_myDID = did; + /* + * The vport state should go to LPFC_FLOGI only + * AFTER we issue a FLOGI, not receive one. + */ + spin_lock_irq(shost->host_lock); + fc_flag = vport->fc_flag; + port_state = vport->port_state; + vport->fc_flag |= FC_PT2PT; + vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + spin_unlock_irq(shost->host_lock); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "3311 Rcv Flogi PS x%x new PS x%x " + "fc_flag x%x new fc_flag x%x\n", + port_state, vport->port_state, + fc_flag, vport->fc_flag); - return 1; - } + /* + * We temporarily set fc_myDID to make it look like we are + * a Fabric. This is done just so we end up with the right + * did / sid on the FLOGI ACC rsp. + */ + did = vport->fc_myDID; + vport->fc_myDID = Fabric_DID; - /* send our FLOGI first */ - if (vport->port_state < LPFC_FLOGI) { - vport->fc_myDID = 0; - lpfc_initial_flogi(vport); - vport->fc_myDID = Fabric_DID; - } + memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); /* Send back ACC */ - lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); + lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, cmdiocb, ndlp, NULL); /* Now lets put fc_myDID back to what its supposed to be */ vport->fc_myDID = did; - if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { - - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) - goto fail; - - lpfc_config_link(phba, mbox); - - mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - goto fail; - } - } - return 0; -fail: - return 1; } /** @@ -7345,7 +7315,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* reject till our FLOGI completes */ if ((vport->port_state < LPFC_FABRIC_CFG_LINK) && - (cmd != ELS_CMD_FLOGI)) { + (cmd != ELS_CMD_FLOGI)) { rjt_err = LSRJT_UNABLE_TPC; rjt_exp = LSEXP_NOTHING_MORE; goto lsrjt; @@ -7381,6 +7351,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_NOTHING_MORE; break; } + if (vport->port_state < LPFC_DISC_AUTH) { if (!(phba->pport->fc_flag & FC_PT2PT) || (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index bfc2442dd74a..d3668aa555d5 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1083,7 +1083,7 @@ out: } -static void +void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; @@ -1113,8 +1113,10 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Start discovery by sending a FLOGI. port_state is identically * LPFC_FLOGI while waiting for FLOGI cmpl */ - if (vport->port_state != LPFC_FLOGI || vport->fc_flag & FC_PT2PT_PLOGI) + if (vport->port_state != LPFC_FLOGI) lpfc_initial_flogi(vport); + else if (vport->fc_flag & FC_PT2PT) + lpfc_disc_start(vport); return; out: @@ -2963,8 +2965,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) out_free_mem: mempool_free(mboxq, phba->mbox_mem_pool); - lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); - kfree(dmabuf); + if (dmabuf) { + lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); + kfree(dmabuf); + } return; } @@ -3448,10 +3452,10 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; spin_unlock_irq(shost->host_lock); - } else - /* Good status, call state machine */ - lpfc_disc_state_machine(vport, ndlp, pmb, - NLP_EVT_CMPL_REG_LOGIN); + } + + /* Call state machine */ + lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b0d92b84bcdc..c14ab6c3ae40 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8834,9 +8834,12 @@ found: * already mapped to this phys_id. */ if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) { - chann[saved_chann] = - cpup->channel_id; - saved_chann++; + if (saved_chann <= + LPFC_FCP_IO_CHAN_MAX) { + chann[saved_chann] = + cpup->channel_id; + saved_chann++; + } goto out; } diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index f87f90e9b7df..1e34b5408a29 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2145,10 +2145,12 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); reg_vfi->e_d_tov = phba->fc_edtov; reg_vfi->r_a_tov = phba->fc_ratov; - reg_vfi->bde.addrHigh = putPaddrHigh(phys); - reg_vfi->bde.addrLow = putPaddrLow(phys); - reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); - reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + if (phys) { + reg_vfi->bde.addrHigh = putPaddrHigh(phys); + reg_vfi->bde.addrLow = putPaddrLow(phys); + reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); + reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + } bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID); /* Only FC supports upd bit */ diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index ed9a2c80c4aa..193733e8c823 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -280,38 +280,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint32_t *lp; IOCB_t *icmd; struct serv_parm *sp; + uint32_t ed_tov; LPFC_MBOXQ_t *mbox; struct ls_rjt stat; int rc; memset(&stat, 0, sizeof (struct ls_rjt)); - if (vport->port_state <= LPFC_FDISC) { - /* Before responding to PLOGI, check for pt2pt mode. - * If we are pt2pt, with an outstanding FLOGI, abort - * the FLOGI and resend it first. - */ - if (vport->fc_flag & FC_PT2PT) { - lpfc_els_abort_flogi(phba); - if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { - /* If the other side is supposed to initiate - * the PLOGI anyway, just ACC it now and - * move on with discovery. - */ - phba->fc_edtov = FF_DEF_EDTOV; - phba->fc_ratov = FF_DEF_RATOV; - /* Start discovery - this should just do - CLEAR_LA */ - lpfc_disc_start(vport); - } else - lpfc_initial_flogi(vport); - } else { - stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; - stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; - lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, - ndlp, NULL); - return 0; - } - } pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; lp = (uint32_t *) pcmd->virt; sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); @@ -404,30 +378,46 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Check for Nport to NPort pt2pt protocol */ if ((vport->fc_flag & FC_PT2PT) && !(vport->fc_flag & FC_PT2PT_PLOGI)) { - /* rcv'ed PLOGI decides what our NPortId will be */ vport->fc_myDID = icmd->un.rcvels.parmRo; - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (mbox == NULL) - goto out; - lpfc_config_link(phba, mbox); - mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - goto out; + + ed_tov = be32_to_cpu(sp->cmn.e_d_tov); + if (sp->cmn.edtovResolution) { + /* E_D_TOV ticks are in nanoseconds */ + ed_tov = (phba->fc_edtov + 999999) / 1000000; } + /* - * For SLI4, the VFI/VPI are registered AFTER the - * Nport with the higher WWPN sends us a PLOGI with - * our assigned NPortId. + * For pt-to-pt, use the larger EDTOV + * RATOV = 2 * EDTOV */ + if (ed_tov > phba->fc_edtov) + phba->fc_edtov = ed_tov; + phba->fc_ratov = (2 * phba->fc_edtov) / 1000; + + memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); + + /* Issue config_link / reg_vfi to account for updated TOV's */ + if (phba->sli_rev == LPFC_SLI_REV4) lpfc_issue_reg_vfi(vport); + else { + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (mbox == NULL) + goto out; + lpfc_config_link(phba, mbox); + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(mbox, phba->mbox_mem_pool); + goto out; + } + } lpfc_can_disctmo(vport); } + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) goto out; @@ -1038,7 +1028,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, uint32_t *lp; IOCB_t *irsp; struct serv_parm *sp; + uint32_t ed_tov; LPFC_MBOXQ_t *mbox; + int rc; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; @@ -1094,18 +1086,63 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; + if ((vport->fc_flag & FC_PT2PT) && + (vport->fc_flag & FC_PT2PT_PLOGI)) { + ed_tov = be32_to_cpu(sp->cmn.e_d_tov); + if (sp->cmn.edtovResolution) { + /* E_D_TOV ticks are in nanoseconds */ + ed_tov = (phba->fc_edtov + 999999) / 1000000; + } + + /* + * Use the larger EDTOV + * RATOV = 2 * EDTOV for pt-to-pt + */ + if (ed_tov > phba->fc_edtov) + phba->fc_edtov = ed_tov; + phba->fc_ratov = (2 * phba->fc_edtov) / 1000; + + memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); + + /* Issue config_link / reg_vfi to account for updated TOV's */ + if (phba->sli_rev == LPFC_SLI_REV4) { + lpfc_issue_reg_vfi(vport); + } else { + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mbox) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0133 PLOGI: no memory " + "for config_link " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, + ndlp->nlp_flag, ndlp->nlp_rpi); + goto out; + } + + lpfc_config_link(phba, mbox); + + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(mbox, phba->mbox_mem_pool); + goto out; + } + } + } + + lpfc_unreg_rpi(vport, ndlp); + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0133 PLOGI: no memory for reg_login " - "Data: x%x x%x x%x x%x\n", - ndlp->nlp_DID, ndlp->nlp_state, - ndlp->nlp_flag, ndlp->nlp_rpi); + "0018 PLOGI: no memory for reg_login " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, + ndlp->nlp_flag, ndlp->nlp_rpi); goto out; } - lpfc_unreg_rpi(vport, ndlp); - if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID, (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) { switch (ndlp->nlp_DID) { @@ -2299,6 +2336,9 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport, if (vport->phba->sli_rev < LPFC_SLI_REV4) ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_flag |= NLP_RPI_REGISTERED; + if (ndlp->nlp_flag & NLP_LOGO_ACC) { + lpfc_unreg_rpi(vport, ndlp); + } } else { if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { lpfc_drop_node(vport, ndlp); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 4679ed4444a7..bae36cc3740b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3859,7 +3859,7 @@ int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba, uint32_t tag; uint16_t hwq; - if (shost_use_blk_mq(cmnd->device->host)) { + if (cmnd && shost_use_blk_mq(cmnd->device->host)) { tag = blk_mq_unique_tag(cmnd->request); hwq = blk_mq_unique_tag_to_hwq(tag); @@ -3908,9 +3908,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, uint32_t logit = LOG_FCP; /* Sanity check on return of outstanding command */ - if (!(lpfc_cmd->pCmd)) - return; cmd = lpfc_cmd->pCmd; + if (!cmd) + return; shost = cmd->device->host; lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f9585cdd8933..92dfd6a5178c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -14842,10 +14842,12 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) struct lpfc_dmabuf *h_buf; struct hbq_dmabuf *seq_dmabuf = NULL; struct hbq_dmabuf *temp_dmabuf = NULL; + uint8_t found = 0; INIT_LIST_HEAD(&dmabuf->dbuf.list); dmabuf->time_stamp = jiffies; new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; + /* Use the hdr_buf to find the sequence that this frame belongs to */ list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) { temp_hdr = (struct fc_frame_header *)h_buf->virt; @@ -14885,7 +14887,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) return seq_dmabuf; } /* find the correct place in the sequence to insert this frame */ - list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) { + d_buf = list_entry(seq_dmabuf->dbuf.list.prev, typeof(*d_buf), list); + while (!found) { temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); temp_hdr = (struct fc_frame_header *)temp_dmabuf->hbuf.virt; /* @@ -14895,9 +14898,17 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) if (be16_to_cpu(new_hdr->fh_seq_cnt) > be16_to_cpu(temp_hdr->fh_seq_cnt)) { list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list); - return seq_dmabuf; + found = 1; + break; } + + if (&d_buf->list == &seq_dmabuf->dbuf.list) + break; + d_buf = list_entry(d_buf->list.prev, typeof(*d_buf), list); } + + if (found) + return seq_dmabuf; return NULL; } @@ -16173,7 +16184,7 @@ fail_fcf_read: } /** - * lpfc_check_next_fcf_pri + * lpfc_check_next_fcf_pri_level * phba pointer to the lpfc_hba struct for this port. * This routine is called from the lpfc_sli4_fcf_rr_next_index_get * routine when the rr_bmask is empty. The FCF indecies are put into the @@ -16329,8 +16340,12 @@ next_priority: if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX && phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag & - LPFC_FCF_FLOGI_FAILED) + LPFC_FCF_FLOGI_FAILED) { + if (list_is_singular(&phba->fcf.fcf_pri_list)) + return LPFC_FCOE_FCF_NEXT_NONE; + goto next_priority; + } lpfc_printf_log(phba, KERN_INFO, LOG_FIP, "2845 Get next roundrobin failover FCF (x%x)\n", diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index c0f7c8ce54aa..ef4ff03242ea 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1083,6 +1083,8 @@ struct megasas_ctrl_info { #define VD_EXT_DEBUG 0 +#define SCAN_PD_CHANNEL 0x1 +#define SCAN_VD_CHANNEL 0x2 enum MR_SCSI_CMD_TYPE { READ_WRITE_LDIO = 0, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 00ce3e269a43..3f8d357b1bac 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -735,6 +735,7 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance, &(regs)->inbound_high_queue_port); writel((lower_32_bits(frame_phys_addr) | (frame_count<<1))|1, &(regs)->inbound_low_queue_port); + mmiowb(); spin_unlock_irqrestore(&instance->hba_lock, flags); } @@ -4669,7 +4670,7 @@ static int megasas_init_fw(struct megasas_instance *instance) /* Find first memory bar */ bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); - if (pci_request_selected_regions(instance->pdev, instance->bar, + if (pci_request_selected_regions(instance->pdev, 1<<instance->bar, "megasas: LSI")) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "IO memory region busy!\n"); return -EBUSY; @@ -4960,7 +4961,7 @@ fail_ready_state: iounmap(instance->reg_set); fail_ioremap: - pci_release_selected_regions(instance->pdev, instance->bar); + pci_release_selected_regions(instance->pdev, 1<<instance->bar); return -EINVAL; } @@ -4981,7 +4982,7 @@ static void megasas_release_mfi(struct megasas_instance *instance) iounmap(instance->reg_set); - pci_release_selected_regions(instance->pdev, instance->bar); + pci_release_selected_regions(instance->pdev, 1<<instance->bar); } /** @@ -5476,7 +5477,6 @@ static int megasas_probe_one(struct pci_dev *pdev, spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); - mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); /* @@ -6443,10 +6443,10 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) } spin_unlock_irqrestore(&instance->hba_lock, flags); - mutex_lock(&instance->aen_mutex); + mutex_lock(&instance->reset_mutex); error = megasas_register_aen(instance, aen.seq_num, aen.class_locale_word); - mutex_unlock(&instance->aen_mutex); + mutex_unlock(&instance->reset_mutex); return error; } @@ -6477,9 +6477,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) int i; int error = 0; compat_uptr_t ptr; - unsigned long local_raw_ptr; u32 local_sense_off; u32 local_sense_len; + u32 user_sense_off; if (clear_user(ioc, sizeof(*ioc))) return -EFAULT; @@ -6497,17 +6497,16 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) * sense_len is not null, so prepare the 64bit value under * the same condition. */ - if (get_user(local_raw_ptr, ioc->frame.raw) || - get_user(local_sense_off, &ioc->sense_off) || - get_user(local_sense_len, &ioc->sense_len)) + if (get_user(local_sense_off, &ioc->sense_off) || + get_user(local_sense_len, &ioc->sense_len) || + get_user(user_sense_off, &cioc->sense_off)) return -EFAULT; - if (local_sense_len) { void __user **sense_ioc_ptr = - (void __user **)((u8*)local_raw_ptr + local_sense_off); + (void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off); compat_uptr_t *sense_cioc_ptr = - (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); + (compat_uptr_t *)(((unsigned long)&cioc->frame.raw) + user_sense_off); if (get_user(ptr, sense_cioc_ptr) || put_user(compat_ptr(ptr), sense_ioc_ptr)) return -EFAULT; @@ -6648,6 +6647,7 @@ megasas_aen_polling(struct work_struct *work) int i, j, doscan = 0; u32 seq_num, wait_time = MEGASAS_RESET_WAIT_TIME; int error; + u8 dcmd_ret = 0; if (!instance) { printk(KERN_ERR "invalid instance!\n"); @@ -6660,16 +6660,7 @@ megasas_aen_polling(struct work_struct *work) wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF; /* Don't run the event workqueue thread if OCR is running */ - for (i = 0; i < wait_time; i++) { - if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) - break; - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - dev_notice(&instance->pdev->dev, "%s waiting for " - "controller reset to finish for scsi%d\n", - __func__, instance->host->host_no); - } - msleep(1000); - } + mutex_lock(&instance->reset_mutex); instance->ev = NULL; host = instance->host; @@ -6677,212 +6668,127 @@ megasas_aen_polling(struct work_struct *work) megasas_decode_evt(instance); switch (le32_to_cpu(instance->evt_detail->code)) { - case MR_EVT_PD_INSERTED: - if (megasas_get_pd_list(instance) == 0) { - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - pd_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, i, j, 0); - - if (instance->pd_list[pd_index].driveState - == MR_PD_STATE_SYSTEM) { - if (!sdev1) - scsi_add_device(host, i, j, 0); - - if (sdev1) - scsi_device_put(sdev1); - } - } - } - } - doscan = 0; - break; + case MR_EVT_PD_INSERTED: case MR_EVT_PD_REMOVED: - if (megasas_get_pd_list(instance) == 0) { - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - pd_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, i, j, 0); - - if (instance->pd_list[pd_index].driveState - == MR_PD_STATE_SYSTEM) { - if (sdev1) - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - } - doscan = 0; + dcmd_ret = megasas_get_pd_list(instance); + if (dcmd_ret == 0) + doscan = SCAN_PD_CHANNEL; break; case MR_EVT_LD_OFFLINE: case MR_EVT_CFG_CLEARED: case MR_EVT_LD_DELETED: - if (!instance->requestorId || - megasas_get_ld_vf_affiliation(instance, 0)) { - if (megasas_ld_list_query(instance, - MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); - - if (instance->ld_ids[ld_index] - != 0xff) { - if (sdev1) - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - doscan = 0; - } - break; case MR_EVT_LD_CREATED: if (!instance->requestorId || - megasas_get_ld_vf_affiliation(instance, 0)) { - if (megasas_ld_list_query(instance, - MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); - - if (instance->ld_ids[ld_index] - != 0xff) { - if (!sdev1) - scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); - } - if (sdev1) - scsi_device_put(sdev1); - } - } - doscan = 0; - } + (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) + dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + + if (dcmd_ret == 0) + doscan = SCAN_VD_CHANNEL; + break; + case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: case MR_EVT_FOREIGN_CFG_IMPORTED: case MR_EVT_LD_STATE_CHANGE: - doscan = 1; + dcmd_ret = megasas_get_pd_list(instance); + + if (dcmd_ret != 0) + break; + + if (!instance->requestorId || + (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) + dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + + if (dcmd_ret != 0) + break; + + doscan = SCAN_VD_CHANNEL | SCAN_PD_CHANNEL; + dev_info(&instance->pdev->dev, "scanning for scsi%d...\n", + instance->host->host_no); break; + case MR_EVT_CTRL_PROP_CHANGED: - megasas_get_ctrl_info(instance); - break; + dcmd_ret = megasas_get_ctrl_info(instance); + break; default: doscan = 0; break; } } else { dev_err(&instance->pdev->dev, "invalid evt_detail!\n"); + mutex_unlock(&instance->reset_mutex); kfree(ev); return; } - if (doscan) { - dev_info(&instance->pdev->dev, "scanning for scsi%d...\n", - instance->host->host_no); - if (megasas_get_pd_list(instance) == 0) { - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { - pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; - sdev1 = scsi_device_lookup(host, i, j, 0); - if (instance->pd_list[pd_index].driveState == - MR_PD_STATE_SYSTEM) { - if (!sdev1) { - scsi_add_device(host, i, j, 0); - } - if (sdev1) - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } + mutex_unlock(&instance->reset_mutex); + + if (doscan & SCAN_PD_CHANNEL) { + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { + pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; + sdev1 = scsi_device_lookup(host, i, j, 0); + if (instance->pd_list[pd_index].driveState == + MR_PD_STATE_SYSTEM) { + if (!sdev1) + scsi_add_device(host, i, j, 0); + else + scsi_device_put(sdev1); + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); } } } } + } - if (!instance->requestorId || - megasas_get_ld_vf_affiliation(instance, 0)) { - if (megasas_ld_list_query(instance, - MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, - MEGASAS_MAX_PD_CHANNELS + i, j, 0); - if (instance->ld_ids[ld_index] - != 0xff) { - if (!sdev1) - scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); - else - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } + if (doscan & SCAN_VD_CHANNEL) { + for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { + ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); + if (instance->ld_ids[ld_index] != 0xff) { + if (!sdev1) + scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); + else + scsi_device_put(sdev1); + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); } } } } } - if (instance->aen_cmd != NULL) { - kfree(ev); - return ; - } - - seq_num = le32_to_cpu(instance->evt_detail->seq_num) + 1; + if (dcmd_ret == 0) + seq_num = le32_to_cpu(instance->evt_detail->seq_num) + 1; + else + seq_num = instance->last_seq_num; /* Register AEN with FW for latest sequence number plus 1 */ class_locale.members.reserved = 0; class_locale.members.locale = MR_EVT_LOCALE_ALL; class_locale.members.class = MR_EVT_CLASS_DEBUG; - mutex_lock(&instance->aen_mutex); + + if (instance->aen_cmd != NULL) { + kfree(ev); + return; + } + + mutex_lock(&instance->reset_mutex); error = megasas_register_aen(instance, seq_num, class_locale.word); - mutex_unlock(&instance->aen_mutex); - if (error) - dev_err(&instance->pdev->dev, "register aen failed error %x\n", error); + dev_err(&instance->pdev->dev, + "register aen failed error %x\n", error); + mutex_unlock(&instance->reset_mutex); kfree(ev); } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 8d630a552b07..021b994fdae8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -201,6 +201,7 @@ megasas_fire_cmd_fusion(struct megasas_instance *instance, &instance->reg_set->inbound_low_queue_port); writel(le32_to_cpu(req_desc->u.high), &instance->reg_set->inbound_high_queue_port); + mmiowb(); spin_unlock_irqrestore(&instance->hba_lock, flags); #endif } @@ -2437,7 +2438,7 @@ megasas_release_fusion(struct megasas_instance *instance) iounmap(instance->reg_set); - pci_release_selected_regions(instance->pdev, instance->bar); + pci_release_selected_regions(instance->pdev, 1<<instance->bar); } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 11393ebf1a68..5b2c37f1e908 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2020,8 +2020,10 @@ mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) _base_free_irq(ioc); _base_disable_msix(ioc); - if (ioc->msix96_vector) + if (ioc->msix96_vector) { kfree(ioc->replyPostRegisterIndex); + ioc->replyPostRegisterIndex = NULL; + } if (ioc->chip_phys) { iounmap(ioc->chip); @@ -2155,6 +2157,17 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) } else ioc->msix96_vector = 0; + if (ioc->is_warpdrive) { + ioc->reply_post_host_index[0] = (resource_size_t __iomem *) + &ioc->chip->ReplyPostHostIndex; + + for (i = 1; i < ioc->cpu_msix_table_sz; i++) + ioc->reply_post_host_index[i] = + (resource_size_t __iomem *) + ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) + * 4))); + } + list_for_each_entry(reply_q, &ioc->reply_queue_list, list) pr_info(MPT3SAS_FMT "%s: IRQ %d\n", reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : @@ -2229,6 +2242,12 @@ mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr) return ioc->reply + (phys_addr - (u32)ioc->reply_dma); } +static inline u8 +_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc) +{ + return ioc->cpu_msix_table[raw_smp_processor_id()]; +} + /** * mpt3sas_base_get_smid - obtain a free smid from internal queue * @ioc: per adapter object @@ -2289,6 +2308,7 @@ mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, request->scmd = scmd; request->cb_idx = cb_idx; smid = request->smid; + request->msix_io = _base_get_msix_index(ioc); list_del(&request->tracker_list); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); return smid; @@ -2411,12 +2431,6 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) } #endif -static inline u8 -_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc) -{ - return ioc->cpu_msix_table[raw_smp_processor_id()]; -} - /** * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object @@ -2470,18 +2484,19 @@ mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware * @ioc: per adapter object * @smid: system request message index - * + * @msix_task: msix_task will be same as msix of IO incase of task abort else 0. * Return nothing. */ void -mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid) +mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 msix_task) { Mpi2RequestDescriptorUnion_t descriptor; u64 *request = (u64 *)&descriptor; descriptor.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; - descriptor.HighPriority.MSIxIndex = 0; + descriptor.HighPriority.MSIxIndex = msix_task; descriptor.HighPriority.SMID = cpu_to_le16(smid); descriptor.HighPriority.LMID = 0; descriptor.HighPriority.Reserved1 = 0; @@ -5201,17 +5216,6 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) if (r) goto out_free_resources; - if (ioc->is_warpdrive) { - ioc->reply_post_host_index[0] = (resource_size_t __iomem *) - &ioc->chip->ReplyPostHostIndex; - - for (i = 1; i < ioc->cpu_msix_table_sz; i++) - ioc->reply_post_host_index[i] = - (resource_size_t __iomem *) - ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) - * 4))); - } - pci_set_drvdata(ioc->pdev, ioc->shost); r = _base_get_ioc_facts(ioc, CAN_SLEEP); if (r) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 5ad271efbd45..92648a5ea2d2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -643,6 +643,7 @@ struct chain_tracker { * @cb_idx: callback index * @direct_io: To indicate whether I/O is direct (WARPDRIVE) * @tracker_list: list of free request (ioc->free_list) + * @msix_io: IO's msix */ struct scsiio_tracker { u16 smid; @@ -651,6 +652,7 @@ struct scsiio_tracker { u8 direct_io; struct list_head chain_list; struct list_head tracker_list; + u16 msix_io; }; /** @@ -1213,7 +1215,8 @@ void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle); void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle); -void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid); +void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, + u16 smid, u16 msix_task); void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid); void mpt3sas_base_initialize_callback_handler(void); u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index d8366b056b70..4ccde5a05b70 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -817,7 +817,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, tm_request->DevHandle)); ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_hi_priority(ioc, smid); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); break; } case MPI2_FUNCTION_SMP_PASSTHROUGH: diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 9ab77b06434d..6180f7970bbf 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2193,6 +2193,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, unsigned long timeleft; struct scsiio_tracker *scsi_lookup = NULL; int rc; + u16 msix_task = 0; if (m_type == TM_MUTEX_ON) mutex_lock(&ioc->tm_cmds.mutex); @@ -2256,7 +2257,12 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); mpt3sas_scsih_set_tm_flag(ioc, handle); init_completion(&ioc->tm_cmds.done); - mpt3sas_base_put_smid_hi_priority(ioc, smid); + if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) && + (scsi_lookup->msix_io < ioc->reply_queue_count)) + msix_task = scsi_lookup->msix_io; + else + msix_task = 0; + mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -3151,7 +3157,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); out: @@ -3332,7 +3338,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); } /** diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 75514a15bea0..f57d96984ae4 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1578,7 +1578,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0); else { - if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK) + if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX) qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts, mcmd->fc_tm_rsp, false); else |