diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 101 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 228 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 349 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 22 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 346 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 1513 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 46 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 16 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 38 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 26 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 104 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nvme.c | 41 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nvme.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nvmet.c | 85 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 598 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 2759 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 31 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 6 |
21 files changed, 3137 insertions, 3193 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 98cabe09c040..f0cf8ffdc5f3 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -917,6 +917,10 @@ struct lpfc_hba { (struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, uint8_t tmo); + int (*lpfc_scsi_prep_task_mgmt_cmd) + (struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + u64 lun, u8 task_mgmt_cmd); /* IOCB interface function jump table entries */ int (*__lpfc_sli_issue_iocb) @@ -928,8 +932,6 @@ struct lpfc_hba { void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *, struct lpfc_iocbq *); int (*lpfc_hba_down_post)(struct lpfc_hba *phba); - IOCB_t * (*lpfc_get_iocb_from_iocbq) - (struct lpfc_iocbq *); void (*lpfc_scsi_cmd_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); @@ -962,7 +964,23 @@ struct lpfc_hba { int (*lpfc_bg_scsi_prep_dma_buf) (struct lpfc_hba *, struct lpfc_io_buf *); - /* Add new entries here */ + + /* Prep SLI WQE/IOCB jump table entries */ + void (*__lpfc_sli_prep_els_req_rsp)(struct lpfc_iocbq *cmdiocbq, + struct lpfc_vport *vport, + struct lpfc_dmabuf *bmp, + u16 cmd_size, u32 did, u32 elscmd, + u8 tmo, u8 expect_rsp); + void (*__lpfc_sli_prep_gen_req)(struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, + u32 num_entry, u8 tmo); + void (*__lpfc_sli_prep_xmit_seq64)(struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, + u16 ox_id, u32 num_entry, u8 rctl, + u8 last_seq, u8 cr_cx_cmd); + void (*__lpfc_sli_prep_abort_xri)(struct lpfc_iocbq *cmdiocbq, + u16 ulp_context, u16 iotag, + u8 ulp_class, u16 cqid, bool ia); /* expedite pool */ struct lpfc_epd_pool epd_pool; @@ -1136,8 +1154,6 @@ struct lpfc_hba { uint32_t cfg_nvme_seg_cnt; uint32_t cfg_scsi_seg_cnt; uint32_t cfg_sg_dma_buf_size; - uint64_t cfg_soft_wwnn; - uint64_t cfg_soft_wwpn; uint32_t cfg_hba_queue_depth; uint32_t cfg_enable_hba_reset; uint32_t cfg_enable_hba_heartbeat; @@ -1269,7 +1285,6 @@ struct lpfc_hba { #define VPD_PORT 0x8 /* valid vpd port data */ #define VPD_MASK 0xf /* mask for any vpd data */ - uint8_t soft_wwn_enable; struct timer_list fcp_poll_timer; struct timer_list eratt_poll; @@ -1801,3 +1816,75 @@ static inline int lpfc_is_vmid_enabled(struct lpfc_hba *phba) { return phba->cfg_vmid_app_header || phba->cfg_vmid_priority_tagging; } + +static inline +u8 get_job_ulpstatus(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return bf_get(lpfc_wcqe_c_status, &iocbq->wcqe_cmpl); + else + return iocbq->iocb.ulpStatus; +} + +static inline +u32 get_job_word4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return iocbq->wcqe_cmpl.parameter; + else + return iocbq->iocb.un.ulpWord[4]; +} + +static inline +u8 get_job_cmnd(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return bf_get(wqe_cmnd, &iocbq->wqe.generic.wqe_com); + else + return iocbq->iocb.ulpCommand; +} + +static inline +u16 get_job_ulpcontext(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return bf_get(wqe_ctxt_tag, &iocbq->wqe.generic.wqe_com); + else + return iocbq->iocb.ulpContext; +} + +static inline +u16 get_job_rcvoxid(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return bf_get(wqe_rcvoxid, &iocbq->wqe.generic.wqe_com); + else + return iocbq->iocb.unsli3.rcvsli3.ox_id; +} + +static inline +u32 get_job_data_placed(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return iocbq->wcqe_cmpl.total_data_placed; + else + return iocbq->iocb.un.genreq64.bdl.bdeSize; +} + +static inline +u32 get_job_abtsiotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return iocbq->wqe.abort_cmd.wqe_com.abort_tag; + else + return iocbq->iocb.un.acxri.abortIoTag; +} + +static inline +u32 get_job_els_rsp64_did(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) +{ + if (phba->sli_rev == LPFC_SLI_REV4) + return bf_get(wqe_els_did, &iocbq->wqe.els_req.wqe_dest); + else + return iocbq->iocb.un.elsreq64.remoteID; +} diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index fa8415259cb8..9b982cc270d9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2838,7 +2838,6 @@ static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show, NULL); static DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL); -static char *lpfc_soft_wwn_key = "C99G71SL8032A"; #define WWN_SZ 8 /** * lpfc_wwn_set - Convert string to the 8 byte WWN value. @@ -2882,229 +2881,7 @@ lpfc_wwn_set(const char *buf, size_t cnt, char wwn[]) } return 0; } -/** - * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: containing the string lpfc_soft_wwn_key. - * @count: must be size of lpfc_soft_wwn_key. - * - * Returns: - * -EINVAL if the buffer does not contain lpfc_soft_wwn_key - * length of buf indicates success - **/ -static ssize_t -lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - unsigned int cnt = count; - uint8_t vvvl = vport->fc_sparam.cmn.valid_vendor_ver_level; - u32 *fawwpn_key = (uint32_t *)&vport->fc_sparam.un.vendorVersion[0]; - - /* - * We're doing a simple sanity check for soft_wwpn setting. - * We require that the user write a specific key to enable - * the soft_wwpn attribute to be settable. Once the attribute - * is written, the enable key resets. If further updates are - * desired, the key must be written again to re-enable the - * attribute. - * - * The "key" is not secret - it is a hardcoded string shown - * here. The intent is to protect against the random user or - * application that is just writing attributes. - */ - if (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0051 lpfc soft wwpn can not be enabled: " - "fawwpn is enabled\n"); - return -EINVAL; - } - - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if ((cnt != strlen(lpfc_soft_wwn_key)) || - (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0)) - return -EINVAL; - - phba->soft_wwn_enable = 1; - - dev_printk(KERN_WARNING, &phba->pcidev->dev, - "lpfc%d: soft_wwpn assignment has been enabled.\n", - phba->brd_no); - dev_printk(KERN_WARNING, &phba->pcidev->dev, - " The soft_wwpn feature is not supported by Broadcom."); - - return count; -} -static DEVICE_ATTR_WO(lpfc_soft_wwn_enable); - -/** - * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: on return contains the wwpn in hexadecimal. - * - * Returns: size of formatted string. - **/ -static ssize_t -lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - - return scnprintf(buf, PAGE_SIZE, "0x%llx\n", - (unsigned long long)phba->cfg_soft_wwpn); -} - -/** - * lpfc_soft_wwpn_store - Set the ww port name of the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: contains the wwpn in hexadecimal. - * @count: number of wwpn bytes in buf - * - * Returns: - * -EACCES hba reset not enabled, adapter over temp - * -EINVAL soft wwn not enabled, count is invalid, invalid wwpn byte invalid - * -EIO error taking adapter offline or online - * value of count on success - **/ -static ssize_t -lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - struct completion online_compl; - int stat1 = 0, stat2 = 0; - unsigned int cnt = count; - u8 wwpn[WWN_SZ]; - int rc; - - if (!phba->cfg_enable_hba_reset) - return -EACCES; - spin_lock_irq(&phba->hbalock); - if (phba->over_temp_state == HBA_OVER_TEMP) { - spin_unlock_irq(&phba->hbalock); - return -EACCES; - } - spin_unlock_irq(&phba->hbalock); - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if (!phba->soft_wwn_enable) - return -EINVAL; - - /* lock setting wwpn, wwnn down */ - phba->soft_wwn_enable = 0; - - rc = lpfc_wwn_set(buf, cnt, wwpn); - if (rc) { - /* not able to set wwpn, unlock it */ - phba->soft_wwn_enable = 1; - return rc; - } - - phba->cfg_soft_wwpn = wwn_to_u64(wwpn); - fc_host_port_name(shost) = phba->cfg_soft_wwpn; - if (phba->cfg_soft_wwnn) - fc_host_node_name(shost) = phba->cfg_soft_wwnn; - - dev_printk(KERN_NOTICE, &phba->pcidev->dev, - "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); - - stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); - if (stat1) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0463 lpfc_soft_wwpn attribute set failed to " - "reinit adapter - %d\n", stat1); - init_completion(&online_compl); - rc = lpfc_workq_post_event(phba, &stat2, &online_compl, - LPFC_EVT_ONLINE); - if (rc == 0) - return -ENOMEM; - wait_for_completion(&online_compl); - if (stat2) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0464 lpfc_soft_wwpn attribute set failed to " - "reinit adapter - %d\n", stat2); - return (stat1 || stat2) ? -EIO : count; -} -static DEVICE_ATTR_RW(lpfc_soft_wwpn); - -/** - * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: on return contains the wwnn in hexadecimal. - * - * Returns: size of formatted string. - **/ -static ssize_t -lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; - return scnprintf(buf, PAGE_SIZE, "0x%llx\n", - (unsigned long long)phba->cfg_soft_wwnn); -} - -/** - * lpfc_soft_wwnn_store - sets the ww node name of the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: contains the ww node name in hexadecimal. - * @count: number of wwnn bytes in buf. - * - * Returns: - * -EINVAL soft wwn not enabled, count is invalid, invalid wwnn byte invalid - * value of count on success - **/ -static ssize_t -lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; - unsigned int cnt = count; - u8 wwnn[WWN_SZ]; - int rc; - - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if (!phba->soft_wwn_enable) - return -EINVAL; - - rc = lpfc_wwn_set(buf, cnt, wwnn); - if (rc) { - /* Allow wwnn to be set many times, as long as the enable - * is set. However, once the wwpn is set, everything locks. - */ - return rc; - } - - phba->cfg_soft_wwnn = wwn_to_u64(wwnn); - - dev_printk(KERN_NOTICE, &phba->pcidev->dev, - "lpfc%d: soft_wwnn set. Value will take effect upon " - "setting of the soft_wwpn\n", phba->brd_no); - - return count; -} -static DEVICE_ATTR_RW(lpfc_soft_wwnn); /** * lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for @@ -6498,9 +6275,6 @@ static struct attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_nvme_enable_fb.attr, &dev_attr_lpfc_nvmet_fb_size.attr, &dev_attr_lpfc_enable_bg.attr, - &dev_attr_lpfc_soft_wwnn.attr, - &dev_attr_lpfc_soft_wwpn.attr, - &dev_attr_lpfc_soft_wwn_enable.attr, &dev_attr_lpfc_enable_hba_reset.attr, &dev_attr_lpfc_enable_hba_heartbeat.attr, &dev_attr_lpfc_EnableXLane.attr, @@ -7730,8 +7504,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->sli_rev == LPFC_SLI_REV4) phba->cfg_irq_chann = phba->cfg_hdw_queue; - phba->cfg_soft_wwnn = 0L; - phba->cfg_soft_wwpn = 0L; lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); lpfc_aer_support_init(phba, lpfc_aer_support); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index fdf08cb57207..8b586fa90f70 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -303,13 +303,12 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, struct bsg_job_data *dd_data; struct bsg_job *job; struct fc_bsg_reply *bsg_reply; - IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp, *rmp; struct lpfc_nodelist *ndlp; struct lpfc_bsg_iocb *iocb; unsigned long flags; - unsigned int rsp_size; int rc = 0; + u32 ulp_status, ulp_word4, total_data_placed; dd_data = cmdiocbq->context1; @@ -325,7 +324,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, /* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags); iocb = &dd_data->context_un.iocb; @@ -333,14 +332,16 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, rmp = iocb->rmp; cmp = cmdiocbq->context2; bmp = cmdiocbq->context3; - rsp = &rspiocbq->iocb; + ulp_status = get_job_ulpstatus(phba, rspiocbq); + ulp_word4 = get_job_word4(phba, rspiocbq); + total_data_placed = get_job_data_placed(phba, rspiocbq); /* Copy the completed data or set the error status */ if (job) { - if (rsp->ulpStatus) { - if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) { - switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) { + if (ulp_status) { + if (ulp_status == IOSTAT_LOCAL_REJECT) { + switch (ulp_word4 & IOERR_PARAM_MASK) { case IOERR_SEQUENCE_TIMEOUT: rc = -ETIMEDOUT; break; @@ -355,10 +356,9 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, rc = -EACCES; } } else { - rsp_size = rsp->un.genreq64.bdl.bdeSize; bsg_reply->reply_payload_rcv_len = lpfc_bsg_copy_data(rmp, &job->reply_payload, - rsp_size, 0); + total_data_placed, 0); } } @@ -388,22 +388,21 @@ static int lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); - struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data; + struct lpfc_hba *phba = vport->phba; struct lpfc_nodelist *ndlp = rdata->pnode; struct fc_bsg_reply *bsg_reply = job->reply; struct ulp_bde64 *bpl = NULL; - uint32_t timeout; struct lpfc_iocbq *cmdiocbq = NULL; - IOCB_t *cmd; struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL; - int request_nseg; - int reply_nseg; + int request_nseg, reply_nseg; + u32 num_entry; struct bsg_job_data *dd_data; unsigned long flags; uint32_t creg_val; int rc = 0; int iocb_stat; + u16 ulp_context; /* in case no data is transferred */ bsg_reply->reply_payload_rcv_len = 0; @@ -426,8 +425,6 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) goto free_dd; } - cmd = &cmdiocbq->iocb; - bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!bmp) { rc = -ENOMEM; @@ -461,31 +458,23 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) goto free_cmp; } - cmd->un.genreq64.bdl.ulpIoTag32 = 0; - cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); - cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); - cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - cmd->un.genreq64.bdl.bdeSize = - (request_nseg + reply_nseg) * sizeof(struct ulp_bde64); - cmd->ulpCommand = CMD_GEN_REQUEST64_CR; - cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); - cmd->un.genreq64.w5.hcsw.Dfctl = 0; - cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL; - cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT; - cmd->ulpBdeCount = 1; - cmd->ulpLe = 1; - cmd->ulpClass = CLASS3; - cmd->ulpContext = ndlp->nlp_rpi; + num_entry = request_nseg + reply_nseg; + if (phba->sli_rev == LPFC_SLI_REV4) - cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; - cmd->ulpOwner = OWN_CHIP; + ulp_context = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + else + ulp_context = ndlp->nlp_rpi; + + lpfc_sli_prep_gen_req(phba, cmdiocbq, bmp, ulp_context, num_entry, + phba->fc_ratov * 2); + + cmdiocbq->num_bdes = num_entry; cmdiocbq->vport = phba->pport; + cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; - cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; - timeout = phba->fc_ratov * 2; - cmd->ulpTimeout = timeout; + cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; - cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; + cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; cmdiocbq->context1 = dd_data; cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; @@ -516,9 +505,9 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) if (iocb_stat == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed yet */ - if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { + if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -575,7 +564,6 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, struct bsg_job_data *dd_data; struct bsg_job *job; struct fc_bsg_reply *bsg_reply; - IOCB_t *rsp; struct lpfc_nodelist *ndlp; struct lpfc_dmabuf *pcmd = NULL, *prsp = NULL; struct fc_bsg_ctels_reply *els_reply; @@ -583,6 +571,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, unsigned long flags; unsigned int rsp_size; int rc = 0; + u32 ulp_status, ulp_word4, total_data_placed; dd_data = cmdiocbq->context1; ndlp = dd_data->context_un.iocb.ndlp; @@ -600,10 +589,12 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, /* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags); - rsp = &rspiocbq->iocb; + ulp_status = get_job_ulpstatus(phba, rspiocbq); + ulp_word4 = get_job_word4(phba, rspiocbq); + total_data_placed = get_job_data_placed(phba, rspiocbq); pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2; prsp = (struct lpfc_dmabuf *)pcmd->list.next; @@ -612,24 +603,28 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, */ if (job) { - if (rsp->ulpStatus == IOSTAT_SUCCESS) { - rsp_size = rsp->un.elsreq64.bdl.bdeSize; + if (ulp_status == IOSTAT_SUCCESS) { + rsp_size = total_data_placed; bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, prsp->virt, rsp_size); - } else if (rsp->ulpStatus == IOSTAT_LS_RJT) { + } else if (ulp_status == IOSTAT_LS_RJT) { bsg_reply->reply_payload_rcv_len = sizeof(struct fc_bsg_ctels_reply); /* LS_RJT data returned in word 4 */ - rjt_data = (uint8_t *)&rsp->un.ulpWord[4]; + rjt_data = (uint8_t *)&ulp_word4; els_reply = &bsg_reply->reply_data.ctels_reply; els_reply->status = FC_CTELS_STATUS_REJECT; els_reply->rjt_data.action = rjt_data[3]; els_reply->rjt_data.reason_code = rjt_data[2]; els_reply->rjt_data.reason_explanation = rjt_data[1]; els_reply->rjt_data.vendor_unique = rjt_data[0]; + } else if (ulp_status == IOSTAT_LOCAL_REJECT && + (ulp_word4 & IOERR_PARAM_MASK) == + IOERR_SEQUENCE_TIMEOUT) { + rc = -ETIMEDOUT; } else { rc = -EIO; } @@ -706,7 +701,6 @@ lpfc_bsg_rport_els(struct bsg_job *job) * we won't be dma into memory that is no longer allocated to for the * request. */ - cmdiocbq = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID, elscmd); if (!cmdiocbq) { @@ -718,18 +712,19 @@ lpfc_bsg_rport_els(struct bsg_job *job) sg_copy_to_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, ((struct lpfc_dmabuf *)cmdiocbq->context2)->virt, - cmdsize); + job->request_payload.payload_len); rpi = ndlp->nlp_rpi; if (phba->sli_rev == LPFC_SLI_REV4) - cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi]; + bf_set(wqe_ctxt_tag, &cmdiocbq->wqe.generic.wqe_com, + phba->sli4_hba.rpi_ids[rpi]); else cmdiocbq->iocb.ulpContext = rpi; - cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; + cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; cmdiocbq->context1 = dd_data; cmdiocbq->context_un.ndlp = ndlp; - cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp; + cmdiocbq->cmd_cmpl = lpfc_bsg_rport_els_cmp; dd_data->type = TYPE_IOCB; dd_data->set_job = job; dd_data->context_un.iocb.cmdiocbq = cmdiocbq; @@ -757,9 +752,9 @@ lpfc_bsg_rport_els(struct bsg_job *job) if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ - if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { + if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -916,6 +911,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_bsg_event *evt; struct event_data *evt_dat = NULL; struct lpfc_iocbq *iocbq; + IOCB_t *iocb = NULL; size_t offset = 0; struct list_head head; struct ulp_bde64 *bde; @@ -923,13 +919,13 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int i; struct lpfc_dmabuf *bdeBuf1 = piocbq->context2; struct lpfc_dmabuf *bdeBuf2 = piocbq->context3; - struct lpfc_hbq_entry *hbqe; struct lpfc_sli_ct_request *ct_req; struct bsg_job *job = NULL; struct fc_bsg_reply *bsg_reply; struct bsg_job_data *dd_data = NULL; unsigned long flags; int size = 0; + u32 bde_count = 0; INIT_LIST_HEAD(&head); list_add_tail(&head, &piocbq->list); @@ -959,12 +955,17 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { /* take accumulated byte count from the last iocbq */ iocbq = list_entry(head.prev, typeof(*iocbq), list); - evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len; + if (phba->sli_rev == LPFC_SLI_REV4) + evt_dat->len = iocbq->wcqe_cmpl.total_data_placed; + else + evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len; } else { list_for_each_entry(iocbq, &head, list) { - for (i = 0; i < iocbq->iocb.ulpBdeCount; i++) + iocb = &iocbq->iocb; + for (i = 0; i < iocb->ulpBdeCount; + i++) evt_dat->len += - iocbq->iocb.un.cont64[i].tus.f.bdeSize; + iocb->un.cont64[i].tus.f.bdeSize; } } @@ -986,20 +987,20 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { bdeBuf1 = iocbq->context2; bdeBuf2 = iocbq->context3; + } - for (i = 0; i < iocbq->iocb.ulpBdeCount; i++) { + if (phba->sli_rev == LPFC_SLI_REV4) + bde_count = iocbq->wcqe_cmpl.word3; + else + bde_count = iocbq->iocb.ulpBdeCount; + for (i = 0; i < bde_count; i++) { if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { if (i == 0) { - hbqe = (struct lpfc_hbq_entry *) - &iocbq->iocb.un.ulpWord[0]; - size = hbqe->bde.tus.f.bdeSize; + size = iocbq->wqe.gen_req.bde.tus.f.bdeSize; dmabuf = bdeBuf1; } else if (i == 1) { - hbqe = (struct lpfc_hbq_entry *) - &iocbq->iocb.unsli3. - sli3Words[4]; - size = hbqe->bde.tus.f.bdeSize; + size = iocbq->unsol_rcv_len; dmabuf = bdeBuf2; } if ((offset + size) > evt_dat->len) @@ -1053,17 +1054,17 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_in_buf_free(phba, dmabuf); } else { - lpfc_post_buffer(phba, - pring, - 1); + lpfc_sli3_post_buffer(phba, + pring, + 1); } break; default: if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_post_buffer(phba, - pring, - 1); + lpfc_sli3_post_buffer(phba, + pring, + 1); break; } } @@ -1086,14 +1087,15 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->ct_ctx[ evt_dat->immed_dat].SID); phba->ct_ctx[evt_dat->immed_dat].rxid = - piocbq->iocb.ulpContext; + get_job_ulpcontext(phba, piocbq); phba->ct_ctx[evt_dat->immed_dat].oxid = - piocbq->iocb.unsli3.rcvsli3.ox_id; + get_job_rcvoxid(phba, piocbq); phba->ct_ctx[evt_dat->immed_dat].SID = - piocbq->iocb.un.rcvels.remoteID; + bf_get(wqe_els_did, + &piocbq->wqe.xmit_els_rsp.wqe_dest); phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID; } else - evt_dat->immed_dat = piocbq->iocb.ulpContext; + evt_dat->immed_dat = get_job_ulpcontext(phba, piocbq); evt_dat->type = FC_REG_CT_EVENT; list_add(&evt_dat->node, &evt->events_to_see); @@ -1376,11 +1378,11 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, struct bsg_job_data *dd_data; struct bsg_job *job; struct fc_bsg_reply *bsg_reply; - IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp; struct lpfc_nodelist *ndlp; unsigned long flags; int rc = 0; + u32 ulp_status, ulp_word4; dd_data = cmdiocbq->context1; @@ -1395,21 +1397,23 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, /* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags); ndlp = dd_data->context_un.iocb.ndlp; cmp = cmdiocbq->context2; bmp = cmdiocbq->context3; - rsp = &rspiocbq->iocb; + + ulp_status = get_job_ulpstatus(phba, rspiocbq); + ulp_word4 = get_job_word4(phba, rspiocbq); /* Copy the completed job data or set the error status */ if (job) { bsg_reply = job->reply; - if (rsp->ulpStatus) { - if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) { - switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) { + if (ulp_status) { + if (ulp_status == IOSTAT_LOCAL_REJECT) { + switch (ulp_word4 & IOERR_PARAM_MASK) { case IOERR_SEQUENCE_TIMEOUT: rc = -ETIMEDOUT; break; @@ -1459,13 +1463,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp, int num_entry) { - IOCB_t *icmd; struct lpfc_iocbq *ctiocb = NULL; int rc = 0; struct lpfc_nodelist *ndlp = NULL; struct bsg_job_data *dd_data; unsigned long flags; uint32_t creg_val; + u16 ulp_context, iotag; ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID); if (!ndlp) { @@ -1492,70 +1496,44 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, goto no_ctiocb; } - icmd = &ctiocb->iocb; - icmd->un.xseq64.bdl.ulpIoTag32 = 0; - icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys); - icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys); - icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64)); - icmd->un.xseq64.w5.hcsw.Fctl = (LS | LA); - icmd->un.xseq64.w5.hcsw.Dfctl = 0; - icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL; - icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT; - - /* Fill in rest of iocb */ - icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; - icmd->ulpBdeCount = 1; - icmd->ulpLe = 1; - icmd->ulpClass = CLASS3; if (phba->sli_rev == LPFC_SLI_REV4) { /* Do not issue unsol response if oxid not marked as valid */ if (phba->ct_ctx[tag].valid != UNSOL_VALID) { rc = IOCB_ERROR; goto issue_ct_rsp_exit; } - icmd->ulpContext = phba->ct_ctx[tag].rxid; - icmd->unsli3.rcvsli3.ox_id = phba->ct_ctx[tag].oxid; - ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID); - if (!ndlp) { - lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, - "2721 ndlp null for oxid %x SID %x\n", - icmd->ulpContext, - phba->ct_ctx[tag].SID); - rc = IOCB_ERROR; - goto issue_ct_rsp_exit; - } - - /* get a refernece count so the ndlp doesn't go away while - * we respond - */ - if (!lpfc_nlp_get(ndlp)) { - rc = IOCB_ERROR; - goto issue_ct_rsp_exit; - } - icmd->un.ulpWord[3] = - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi], + phba->ct_ctx[tag].oxid, num_entry, + FC_RCTL_DD_SOL_CTL, 1, + CMD_XMIT_SEQUENCE64_WQE); /* The exchange is done, mark the entry as invalid */ phba->ct_ctx[tag].valid = UNSOL_INVALID; - } else - icmd->ulpContext = (ushort) tag; + iotag = get_wqe_reqtag(ctiocb); + } else { + lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp, 0, tag, num_entry, + FC_RCTL_DD_SOL_CTL, 1, + CMD_XMIT_SEQUENCE64_CX); + ctiocb->num_bdes = num_entry; + iotag = ctiocb->iocb.ulpIoTag; + } - icmd->ulpTimeout = phba->fc_ratov * 2; + ulp_context = get_job_ulpcontext(phba, ctiocb); /* Xmit CT response on exchange <xid> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n", - icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state); + "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n", + ulp_context, iotag, tag, phba->link_state); - ctiocb->iocb_flag |= LPFC_IO_LIBDFC; + ctiocb->cmd_flag |= LPFC_IO_LIBDFC; ctiocb->vport = phba->pport; ctiocb->context1 = dd_data; ctiocb->context2 = cmp; ctiocb->context3 = bmp; ctiocb->context_un.ndlp = ndlp; - ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp; + ctiocb->cmd_cmpl = lpfc_issue_ct_rsp_cmp; dd_data->type = TYPE_IOCB; dd_data->set_job = job; @@ -1582,9 +1560,9 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ - if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) { + if (ctiocb->cmd_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; + ctiocb->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -2633,7 +2611,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, { struct lpfc_bsg_event *evt; struct lpfc_iocbq *cmdiocbq, *rspiocbq; - IOCB_t *cmd, *rsp; struct lpfc_dmabuf *dmabuf; struct ulp_bde64 *bpl = NULL; struct lpfc_sli_ct_request *ctreq = NULL; @@ -2641,6 +2618,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, int time_left; int iocb_stat = IOCB_SUCCESS; unsigned long flags; + u32 status; *txxri = 0; *rxxri = 0; @@ -2684,9 +2662,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, goto err_get_xri_exit; } - cmd = &cmdiocbq->iocb; - rsp = &rspiocbq->iocb; - memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ); ctreq->RevisionId.bits.Revision = SLI_CT_REVISION; @@ -2696,36 +2671,24 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_XRI_SETUP; ctreq->CommandResponse.bits.Size = 0; - - cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(dmabuf->phys); - cmd->un.xseq64.bdl.addrLow = putPaddrLow(dmabuf->phys); - cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - cmd->un.xseq64.bdl.bdeSize = sizeof(*bpl); - - cmd->un.xseq64.w5.hcsw.Fctl = LA; - cmd->un.xseq64.w5.hcsw.Dfctl = 0; - cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL; - cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT; - - cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR; - cmd->ulpBdeCount = 1; - cmd->ulpLe = 1; - cmd->ulpClass = CLASS3; - cmd->ulpContext = rpi; - - cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; + cmdiocbq->context3 = dmabuf; + cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; cmdiocbq->vport = phba->pport; - cmdiocbq->iocb_cmpl = NULL; + cmdiocbq->cmd_cmpl = NULL; + + lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, dmabuf, rpi, 0, 1, + FC_RCTL_DD_SOL_CTL, 0, CMD_XMIT_SEQUENCE64_CR); iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, - rspiocbq, - (phba->fc_ratov * 2) - + LPFC_DRVR_TIMEOUT); - if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) { + rspiocbq, (phba->fc_ratov * 2) + + LPFC_DRVR_TIMEOUT); + + status = get_job_ulpstatus(phba, rspiocbq); + if (iocb_stat != IOCB_SUCCESS || status != IOCB_SUCCESS) { ret_val = -EIO; goto err_get_xri_exit; } - *txxri = rsp->ulpContext; + *txxri = get_job_ulpcontext(phba, rspiocbq); evt->waiting = 1; evt->wait_time_stamp = jiffies; @@ -2926,7 +2889,7 @@ out: } /** - * lpfcdiag_loop_post_rxbufs - post the receive buffers for an unsol CT cmd + * lpfcdiag_sli3_loop_post_rxbufs - post the receive buffers for an unsol CT cmd * @phba: Pointer to HBA context object * @rxxri: Receive exchange id * @len: Number of data bytes @@ -2934,8 +2897,8 @@ out: * This function allocates and posts a data buffer of sufficient size to receive * an unsolicted CT command. **/ -static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, - size_t len) +static int lpfcdiag_sli3_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, + size_t len) { struct lpfc_sli_ring *pring; struct lpfc_iocbq *cmdiocbq; @@ -2972,7 +2935,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, /* Queue buffers for the receive exchange */ num_bde = (uint32_t)rxbuffer->flag; dmp = &rxbuffer->dma; - cmd = &cmdiocbq->iocb; i = 0; @@ -3040,7 +3002,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, ret_val = -EIO; goto err_post_rxbufs_exit; } - cmd = &cmdiocbq->iocb; i = 0; } @@ -3092,7 +3053,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job) size_t segment_len = 0, segment_offset = 0, current_offset = 0; uint16_t rpi = 0; struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL; - IOCB_t *cmd, *rsp = NULL; + union lpfc_wqe128 *cmdwqe, *rspwqe; struct lpfc_sli_ct_request *ctreq; struct lpfc_dmabuf *txbmp; struct ulp_bde64 *txbpl = NULL; @@ -3185,7 +3146,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job) goto loopback_test_exit; } - rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size); + rc = lpfcdiag_sli3_loop_post_rxbufs(phba, rxxri, full_size); if (rc) { lpfcdiag_loop_self_unreg(phba, rpi); goto loopback_test_exit; @@ -3228,9 +3189,12 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job) goto err_loopback_test_exit; } - cmd = &cmdiocbq->iocb; - if (phba->sli_rev < LPFC_SLI_REV4) - rsp = &rspiocbq->iocb; + cmdwqe = &cmdiocbq->wqe; + memset(cmdwqe, 0, sizeof(union lpfc_wqe)); + if (phba->sli_rev < LPFC_SLI_REV4) { + rspwqe = &rspiocbq->wqe; + memset(rspwqe, 0, sizeof(union lpfc_wqe)); + } INIT_LIST_HEAD(&head); list_add_tail(&head, &txbuffer->dma.list); @@ -3262,41 +3226,32 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job) /* Build the XMIT_SEQUENCE iocb */ num_bde = (uint32_t)txbuffer->flag; - cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys); - cmd->un.xseq64.bdl.addrLow = putPaddrLow(txbmp->phys); - cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - cmd->un.xseq64.bdl.bdeSize = (num_bde * sizeof(struct ulp_bde64)); - - cmd->un.xseq64.w5.hcsw.Fctl = (LS | LA); - cmd->un.xseq64.w5.hcsw.Dfctl = 0; - cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL; - cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT; - - cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; - cmd->ulpBdeCount = 1; - cmd->ulpLe = 1; - cmd->ulpClass = CLASS3; + cmdiocbq->num_bdes = num_bde; + cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK; + cmdiocbq->vport = phba->pport; + cmdiocbq->cmd_cmpl = NULL; + cmdiocbq->context3 = txbmp; if (phba->sli_rev < LPFC_SLI_REV4) { - cmd->ulpContext = txxri; + lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp, 0, txxri, + num_bde, FC_RCTL_DD_UNSOL_CTL, 1, + CMD_XMIT_SEQUENCE64_CX); + } else { - cmd->un.xseq64.bdl.ulpIoTag32 = 0; - cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi]; - cmdiocbq->context3 = txbmp; + lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp, + phba->sli4_hba.rpi_ids[rpi], 0xffff, + full_size, FC_RCTL_DD_UNSOL_CTL, 1, + CMD_XMIT_SEQUENCE64_WQE); cmdiocbq->sli4_xritag = NO_XRI; - cmd->unsli3.rcvsli3.ox_id = 0xffff; } - cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; - cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK; - cmdiocbq->vport = phba->pport; - cmdiocbq->iocb_cmpl = NULL; + iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq, (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT); - - if ((iocb_stat != IOCB_SUCCESS) || - ((phba->sli_rev < LPFC_SLI_REV4) && - (rsp->ulpStatus != IOSTAT_SUCCESS))) { + if (iocb_stat != IOCB_SUCCESS || + (phba->sli_rev < LPFC_SLI_REV4 && + (get_job_ulpstatus(phba, rspiocbq) != IOSTAT_SUCCESS))) { lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, "3126 Failed loopback test issue iocb: " "iocb_stat:x%x\n", iocb_stat); @@ -5273,11 +5228,11 @@ lpfc_menlo_cmd(struct bsg_job *job) cmd->ulpClass = CLASS3; cmd->ulpOwner = OWN_CHIP; cmd->ulpLe = 1; /* Limited Edition */ - cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; + cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; cmdiocbq->vport = phba->pport; /* We want the firmware to timeout before we do */ cmd->ulpTimeout = MENLO_TIMEOUT - 5; - cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp; + cmdiocbq->cmd_cmpl = lpfc_bsg_menlo_cmd_cmp; cmdiocbq->context1 = dd_data; cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; @@ -6001,7 +5956,7 @@ lpfc_bsg_timeout(struct bsg_job *job) spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O abort window is still open */ - if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) { + if (!(cmdiocb->cmd_flag & LPFC_IO_CMD_OUTSTANDING)) { spin_unlock_irqrestore(&phba->hbalock, flags); return -EAGAIN; } diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 89e36bf14d8f..96408cd6c4c8 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -129,6 +129,7 @@ void lpfc_disc_list_loopmap(struct lpfc_vport *); void lpfc_disc_start(struct lpfc_vport *); void lpfc_cleanup_discovery_resources(struct lpfc_vport *); void lpfc_cleanup(struct lpfc_vport *); +void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd); void lpfc_disc_timeout(struct timer_list *); int lpfc_unregister_fcf_prep(struct lpfc_hba *); @@ -190,6 +191,7 @@ void lpfc_els_timeout_handler(struct lpfc_vport *); struct lpfc_iocbq *lpfc_prep_els_iocb(struct lpfc_vport *, uint8_t, uint16_t, uint8_t, struct lpfc_nodelist *, uint32_t, uint32_t); +void lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job); void lpfc_hb_timeout_handler(struct lpfc_hba *); void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, @@ -211,7 +213,7 @@ int lpfc_sli4_refresh_params(struct lpfc_hba *phba); int lpfc_hba_down_prep(struct lpfc_hba *); int lpfc_hba_down_post(struct lpfc_hba *); void lpfc_hba_init(struct lpfc_hba *, uint32_t *); -int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int); +int lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); int lpfc_online(struct lpfc_hba *); void lpfc_unblock_mgmt_io(struct lpfc_hba *); @@ -351,6 +353,22 @@ int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_iocbq *pwqe); int lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, void *cmpl); +void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdiocbq, + struct lpfc_vport *vport, + struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, + u32 elscmd, u8 tmo, u8 expect_rsp); +void lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, + u8 tmo); +void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, + u32 num_entry, u8 rctl, u8 last_seq, + u8 cr_cx_cmd); +void lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid, + bool ia); struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri); struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index dfcb7d4bd7fa..4b024aa03c1b 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -87,12 +87,12 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "0146 Ignoring unsolicited CT No HBQ " "status = x%x\n", - piocbq->iocb.ulpStatus); + get_job_ulpstatus(phba, piocbq)); } lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "0145 Ignoring unsolicted CT HBQ Size:%d " "status = x%x\n", - size, piocbq->iocb.ulpStatus); + size, get_job_ulpstatus(phba, piocbq)); } static void @@ -143,7 +143,7 @@ lpfc_ct_unsol_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * lpfc_ct_reject_event - Issue reject for unhandled CT MIB commands * @ndlp: pointer to a node-list data structure. * @ct_req: pointer to the CT request data structure. - * @rx_id: rx_id of the received UNSOL CT command + * @ulp_context: context of received UNSOL CT command * @ox_id: ox_id of the UNSOL CT command * * This routine is invoked by the lpfc_ct_handle_mibreq routine for sending @@ -152,7 +152,7 @@ lpfc_ct_unsol_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, static void lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, struct lpfc_sli_ct_request *ct_req, - u16 rx_id, u16 ox_id) + u16 ulp_context, u16 ox_id) { struct lpfc_vport *vport = ndlp->vport; struct lpfc_hba *phba = vport->phba; @@ -161,8 +161,8 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, struct lpfc_dmabuf *bmp = NULL; struct lpfc_dmabuf *mp = NULL; struct ulp_bde64 *bpl; - IOCB_t *icmd; u8 rc = 0; + u32 tmo; /* fill in BDEs for command */ mp = kmalloc(sizeof(*mp), GFP_KERNEL); @@ -220,43 +220,41 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, goto ct_free_bmpvirt; } - icmd = &cmdiocbq->iocb; - icmd->un.genreq64.bdl.ulpIoTag32 = 0; - icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); - icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); - icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - icmd->un.genreq64.bdl.bdeSize = sizeof(struct ulp_bde64); - icmd->un.genreq64.w5.hcsw.Fctl = (LS | LA); - icmd->un.genreq64.w5.hcsw.Dfctl = 0; - icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL; - icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT; - icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; - icmd->ulpBdeCount = 1; - icmd->ulpLe = 1; - icmd->ulpClass = CLASS3; + if (phba->sli_rev == LPFC_SLI_REV4) { + lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, bmp, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi], + ox_id, 1, FC_RCTL_DD_SOL_CTL, 1, + CMD_XMIT_SEQUENCE64_WQE); + } else { + lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, bmp, 0, ulp_context, 1, + FC_RCTL_DD_SOL_CTL, 1, + CMD_XMIT_SEQUENCE64_CX); + } /* Save for completion so we can release these resources */ - cmdiocbq->context1 = lpfc_nlp_get(ndlp); cmdiocbq->context2 = (uint8_t *)mp; cmdiocbq->context3 = (uint8_t *)bmp; - cmdiocbq->iocb_cmpl = lpfc_ct_unsol_cmpl; - icmd->ulpContext = rx_id; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = ox_id; - icmd->un.ulpWord[3] = - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; - icmd->ulpTimeout = (3 * phba->fc_ratov); + cmdiocbq->cmd_cmpl = lpfc_ct_unsol_cmpl; + tmo = (3 * phba->fc_ratov); cmdiocbq->retry = 0; cmdiocbq->vport = vport; cmdiocbq->context_un.ndlp = NULL; - cmdiocbq->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; + cmdiocbq->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT; + + cmdiocbq->context1 = lpfc_nlp_get(ndlp); + if (!cmdiocbq->context1) + goto ct_no_ndlp; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); - if (!rc) - return; + if (rc) { + lpfc_nlp_put(ndlp); + goto ct_no_ndlp; + } + return; +ct_no_ndlp: rc = 6; - lpfc_nlp_put(ndlp); lpfc_sli_release_iocbq(phba, cmdiocbq); ct_free_bmpvirt: lpfc_mbuf_free(phba, bmp->virt, bmp->phys); @@ -286,25 +284,17 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) { struct lpfc_sli_ct_request *ct_req; struct lpfc_nodelist *ndlp = NULL; - struct lpfc_vport *vport = NULL; - IOCB_t *icmd = &ctiocbq->iocb; - u32 mi_cmd, vpi; - u32 did = 0; - - vpi = ctiocbq->iocb.unsli3.rcvsli3.vpi; - vport = lpfc_find_vport_by_vpid(phba, vpi); - if (!vport) { - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "6437 Unsol CT: VPORT NULL vpi : x%x\n", - vpi); - return; - } - - did = ctiocbq->iocb.un.rcvels.remoteID; - if (icmd->ulpStatus) { + struct lpfc_vport *vport = ctiocbq->vport; + u32 ulp_status = get_job_ulpstatus(phba, ctiocbq); + u32 ulp_word4 = get_job_word4(phba, ctiocbq); + u32 did; + u32 mi_cmd; + + did = bf_get(els_rsp64_sid, &ctiocbq->wqe.xmit_els_rsp); + if (ulp_status) { lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6438 Unsol CT: status:x%x/x%x did : x%x\n", - icmd->ulpStatus, icmd->un.ulpWord[4], did); + ulp_status, ulp_word4, did); return; } @@ -322,13 +312,14 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) ct_req = ((struct lpfc_sli_ct_request *) (((struct lpfc_dmabuf *)ctiocbq->context2)->virt)); - mi_cmd = ct_req->CommandResponse.bits.CmdRsp; lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6442 : MI Cmd : x%x Not Supported\n", mi_cmd); lpfc_ct_reject_event(ndlp, ct_req, - ctiocbq->iocb.ulpContext, - ctiocbq->iocb.unsli3.rcvsli3.ox_id); + bf_get(wqe_ctxt_tag, + &ctiocbq->wqe.xmit_els_rsp.wqe_com), + bf_get(wqe_rcvoxid, + &ctiocbq->wqe.xmit_els_rsp.wqe_com)); } /** @@ -351,52 +342,49 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, IOCB_t *icmd = &ctiocbq->iocb; int i; struct lpfc_iocbq *iocbq; + struct lpfc_iocbq *iocb; dma_addr_t dma_addr; uint32_t size; struct list_head head; struct lpfc_sli_ct_request *ct_req; struct lpfc_dmabuf *bdeBuf1 = ctiocbq->context2; struct lpfc_dmabuf *bdeBuf2 = ctiocbq->context3; + u32 status, parameter, bde_count = 0; + struct lpfc_wcqe_complete *wcqe_cmpl = NULL; ctiocbq->context1 = NULL; ctiocbq->context2 = NULL; ctiocbq->context3 = NULL; - if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) { + wcqe_cmpl = &ctiocbq->wcqe_cmpl; + status = get_job_ulpstatus(phba, ctiocbq); + parameter = get_job_word4(phba, ctiocbq); + if (phba->sli_rev == LPFC_SLI_REV4) + bde_count = wcqe_cmpl->word3; + else + bde_count = icmd->ulpBdeCount; + + if (unlikely(status == IOSTAT_NEED_BUFFER)) { lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); - } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((icmd->un.ulpWord[4] & IOERR_PARAM_MASK) == + } else if ((status == IOSTAT_LOCAL_REJECT) && + ((parameter & IOERR_PARAM_MASK) == IOERR_RCV_BUFFER_WAITING)) { /* Not enough posted buffers; Try posting more buffers */ phba->fc_stat.NoRcvBuf++; if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_post_buffer(phba, pring, 2); + lpfc_sli3_post_buffer(phba, pring, 2); return; } /* If there are no BDEs associated * with this IOCB, there is nothing to do. */ - if (icmd->ulpBdeCount == 0) + if (bde_count == 0) return; - if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { - ctiocbq->context2 = bdeBuf1; - if (icmd->ulpBdeCount == 2) - ctiocbq->context3 = bdeBuf2; - } else { - dma_addr = getPaddr(icmd->un.cont64[0].addrHigh, - icmd->un.cont64[0].addrLow); - ctiocbq->context2 = lpfc_sli_ringpostbuf_get(phba, pring, - dma_addr); - if (icmd->ulpBdeCount == 2) { - dma_addr = getPaddr(icmd->un.cont64[1].addrHigh, - icmd->un.cont64[1].addrLow); - ctiocbq->context3 = lpfc_sli_ringpostbuf_get(phba, - pring, - dma_addr); - } - } + ctiocbq->context2 = bdeBuf1; + if (bde_count == 2) + ctiocbq->context3 = bdeBuf2; ct_req = ((struct lpfc_sli_ct_request *) (((struct lpfc_dmabuf *)ctiocbq->context2)->virt)); @@ -412,19 +400,29 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { INIT_LIST_HEAD(&head); list_add_tail(&head, &ctiocbq->list); - list_for_each_entry(iocbq, &head, list) { - icmd = &iocbq->iocb; - if (icmd->ulpBdeCount == 0) + list_for_each_entry(iocb, &head, list) { + if (phba->sli_rev == LPFC_SLI_REV4) + bde_count = iocb->wcqe_cmpl.word3; + else + bde_count = iocb->iocb.ulpBdeCount; + + if (!bde_count) continue; - bdeBuf1 = iocbq->context2; - iocbq->context2 = NULL; - size = icmd->un.cont64[0].tus.f.bdeSize; + bdeBuf1 = iocb->context2; + iocb->context2 = NULL; + if (phba->sli_rev == LPFC_SLI_REV4) + size = iocb->wqe.gen_req.bde.tus.f.bdeSize; + else + size = iocb->iocb.un.cont64[0].tus.f.bdeSize; lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf1, size); lpfc_in_buf_free(phba, bdeBuf1); - if (icmd->ulpBdeCount == 2) { - bdeBuf2 = iocbq->context3; - iocbq->context3 = NULL; - size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize; + if (bde_count == 2) { + bdeBuf2 = iocb->context3; + iocb->context3 = NULL; + if (phba->sli_rev == LPFC_SLI_REV4) + size = iocb->unsol_rcv_len; + else + size = iocb->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize; lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf2, size); lpfc_in_buf_free(phba, bdeBuf2); @@ -447,7 +445,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_ct_unsol_buffer(phba, iocbq, mp, size); lpfc_in_buf_free(phba, mp); } - lpfc_post_buffer(phba, pring, i); + lpfc_sli3_post_buffer(phba, pring, i); } list_del(&head); } @@ -588,15 +586,15 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) static int lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, - void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_iocbq *), + void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_iocbq *), struct lpfc_nodelist *ndlp, uint32_t event_tag, uint32_t num_entry, uint32_t tmo, uint8_t retry) { struct lpfc_hba *phba = vport->phba; - IOCB_t *icmd; struct lpfc_iocbq *geniocb; int rc; + u16 ulp_context; /* Allocate buffer for command iocb */ geniocb = lpfc_sli_get_iocbq(phba); @@ -604,12 +602,8 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, if (geniocb == NULL) return 1; - icmd = &geniocb->iocb; - icmd->un.genreq64.bdl.ulpIoTag32 = 0; - icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); - icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); - icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64)); + /* Update the num_entry bde count */ + geniocb->num_bdes = num_entry; geniocb->context3 = (uint8_t *) bmp; @@ -619,50 +613,34 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, geniocb->event_tag = event_tag; - /* Fill in payload, bp points to frame payload */ - icmd->ulpCommand = CMD_GEN_REQUEST64_CR; - - /* Fill in rest of iocb */ - icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); - icmd->un.genreq64.w5.hcsw.Dfctl = 0; - icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL; - icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT; - if (!tmo) { /* FC spec states we need 3 * ratov for CT requests */ tmo = (3 * phba->fc_ratov); } - icmd->ulpTimeout = tmo; - icmd->ulpBdeCount = 1; - icmd->ulpLe = 1; - icmd->ulpClass = CLASS3; - icmd->ulpContext = ndlp->nlp_rpi; + if (phba->sli_rev == LPFC_SLI_REV4) - icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + ulp_context = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + else + ulp_context = ndlp->nlp_rpi; - if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { - /* For GEN_REQUEST64_CR, use the RPI */ - icmd->ulpCt_h = 0; - icmd->ulpCt_l = 0; - } + lpfc_sli_prep_gen_req(phba, geniocb, bmp, ulp_context, num_entry, tmo); /* Issue GEN REQ IOCB for NPORT <did> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0119 Issue GEN REQ IOCB to NPORT x%x " "Data: x%x x%x\n", - ndlp->nlp_DID, icmd->ulpIoTag, + ndlp->nlp_DID, geniocb->iotag, vport->port_state); - geniocb->iocb_cmpl = cmpl; - geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; + geniocb->cmd_cmpl = cmpl; + geniocb->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT; geniocb->vport = vport; geniocb->retry = retry; geniocb->context_un.ndlp = lpfc_nlp_get(ndlp); if (!geniocb->context_un.ndlp) goto out; - rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0); + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0); if (rc == IOCB_ERROR) { - geniocb->context_un.ndlp = NULL; lpfc_nlp_put(ndlp); goto out; } @@ -938,12 +916,13 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - IOCB_t *irsp; struct lpfc_dmabuf *outp; struct lpfc_dmabuf *inp; struct lpfc_sli_ct_request *CTrsp; struct lpfc_sli_ct_request *CTreq; struct lpfc_nodelist *ndlp; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); int rc, type; /* First save ndlp, before we overwrite it */ @@ -951,13 +930,13 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; + inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; - irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT cmpl: status:x%x/x%x rtry:%d", - irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); + ulp_status, ulp_word4, vport->fc_ns_retry); /* Ignore response if link flipped after this request was made */ if (cmdiocb->event_tag != phba->fc_eventTag) { @@ -981,7 +960,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out; } - if (lpfc_error_lost_link(irsp)) { + if (lpfc_error_lost_link(ulp_status, ulp_word4)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0226 NS query failed due to link event\n"); if (vport->fc_flag & FC_RSCN_MODE) @@ -1013,11 +992,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } spin_unlock_irq(shost->host_lock); - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { - if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || - (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) != + if (ulp_status != IOSTAT_LOCAL_REJECT || + (ulp_word4 & IOERR_PARAM_MASK) != IOERR_NO_RESOURCES) vport->fc_ns_retry++; @@ -1040,7 +1019,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0257 GID_FT Query error: 0x%x 0x%x\n", - irsp->ulpStatus, vport->fc_ns_retry); + ulp_status, vport->fc_ns_retry); } else { /* Good status, continue checking */ CTreq = (struct lpfc_sli_ct_request *) inp->virt; @@ -1054,12 +1033,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, CTreq->un.gid.Fc4Type, vport->num_disc_nodes, vport->gidft_inp, - irsp->un.genreq64.bdl.bdeSize); + get_job_data_placed(phba, rspiocb)); lpfc_ns_rsp(vport, outp, CTreq->un.gid.Fc4Type, - (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); + get_job_data_placed(phba, rspiocb)); } else if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* NameServer Rsp Error */ @@ -1154,12 +1133,13 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - IOCB_t *irsp; struct lpfc_dmabuf *outp; struct lpfc_dmabuf *inp; struct lpfc_sli_ct_request *CTrsp; struct lpfc_sli_ct_request *CTreq; struct lpfc_nodelist *ndlp; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); int rc; /* First save ndlp, before we overwrite it */ @@ -1169,11 +1149,10 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmdiocb->context_un.rsp_iocb = rspiocb; inp = (struct lpfc_dmabuf *)cmdiocb->context1; outp = (struct lpfc_dmabuf *)cmdiocb->context2; - irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_PT cmpl: status:x%x/x%x rtry:%d", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, vport->fc_ns_retry); /* Ignore response if link flipped after this request was made */ @@ -1198,7 +1177,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out; } - if (lpfc_error_lost_link(irsp)) { + if (lpfc_error_lost_link(ulp_status, ulp_word4)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4166 NS query failed due to link event\n"); if (vport->fc_flag & FC_RSCN_MODE) @@ -1230,11 +1209,11 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } spin_unlock_irq(shost->host_lock); - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { - if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || - (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) != + if (ulp_status != IOSTAT_LOCAL_REJECT || + (ulp_word4 & IOERR_PARAM_MASK) != IOERR_NO_RESOURCES) vport->fc_ns_retry++; @@ -1253,7 +1232,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4103 GID_FT Query error: 0x%x 0x%x\n", - irsp->ulpStatus, vport->fc_ns_retry); + ulp_status, vport->fc_ns_retry); } else { /* Good status, continue checking */ CTreq = (struct lpfc_sli_ct_request *)inp->virt; @@ -1267,12 +1246,12 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, CTreq->un.gid.Fc4Type, vport->num_disc_nodes, vport->gidft_inp, - irsp->un.genreq64.bdl.bdeSize); + get_job_data_placed(phba, rspiocb)); lpfc_ns_rsp(vport, outp, CTreq->un.gid.Fc4Type, - (uint32_t)(irsp->un.genreq64.bdl.bdeSize)); + get_job_data_placed(phba, rspiocb)); } else if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* NameServer Rsp Error */ @@ -1367,20 +1346,21 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp; int did, rc, retry; uint8_t fbits; struct lpfc_nodelist *ndlp = NULL, *free_ndlp = NULL; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; did = be32_to_cpu(did); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GFF_ID cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], did); + ulp_status, ulp_word4, did); /* Ignore response if link flipped after this request was made */ if (cmdiocb->event_tag != phba->fc_eventTag) { @@ -1389,7 +1369,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto iocb_free; } - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { /* Good status, continue checking */ CTrsp = (struct lpfc_sli_ct_request *) outp->virt; fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET]; @@ -1419,8 +1399,8 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check for retry */ if (cmdiocb->retry < LPFC_MAX_NS_RETRY) { retry = 1; - if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) { - switch ((irsp->un.ulpWord[4] & + if (ulp_status == IOSTAT_LOCAL_REJECT) { + switch ((ulp_word4 & IOERR_PARAM_MASK)) { case IOERR_NO_RESOURCES: @@ -1456,7 +1436,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0267 NameServer GFF Rsp " "x%x Error (%d %d) Data: x%x x%x\n", - did, irsp->ulpStatus, irsp->un.ulpWord[4], + did, ulp_status, ulp_word4, vport->fc_flag, vport->fc_rscn_id_cnt); } @@ -1511,10 +1491,9 @@ iocb_free: static void lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) + struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *)cmdiocb->context1; struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *)cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp; @@ -1522,13 +1501,15 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ns_ndlp = NULL; uint32_t fc4_data_0, fc4_data_1; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); did = ((struct lpfc_sli_ct_request *)inp->virt)->un.gft.PortId; did = be32_to_cpu(did); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GFT_ID cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], did); + ulp_status, ulp_word4, did); /* Ignore response if link flipped after this request was made */ if ((uint32_t) cmdiocb->event_tag != phba->fc_eventTag) { @@ -1540,7 +1521,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Preserve the nameserver node to release the reference. */ ns_ndlp = cmdiocb->context_un.ndlp; - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { /* Good status, continue checking */ CTrsp = (struct lpfc_sli_ct_request *)outp->virt; fc4_data_0 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[0]); @@ -1601,7 +1582,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } else lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); + "3065 GFT_ID failed x%08x\n", ulp_status); out: lpfc_ct_free_iocb(phba, cmdiocb); @@ -1615,12 +1596,13 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_dmabuf *inp; struct lpfc_dmabuf *outp; - IOCB_t *irsp; struct lpfc_sli_ct_request *CTrsp; struct lpfc_nodelist *ndlp; int cmdcode, rc; uint8_t retry; uint32_t latt; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); /* First save ndlp, before we overwrite it */ ndlp = cmdiocb->context_un.ndlp; @@ -1630,7 +1612,6 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; - irsp = &rspiocb->iocb; cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> CommandResponse.bits.CmdRsp); @@ -1638,28 +1619,28 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, latt = lpfc_els_chk_latt(vport); - /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ + /* RFT request completes status <ulp_status> CmdRsp <CmdRsp> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0209 CT Request completes, latt %d, " - "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", - latt, irsp->ulpStatus, + "ulp_status x%x CmdRsp x%x, Context x%x, Tag x%x\n", + latt, ulp_status, CTrsp->CommandResponse.bits.CmdRsp, - cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); + get_job_ulpcontext(phba, cmdiocb), cmdiocb->iotag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "CT cmd cmpl: status:x%x/x%x cmd:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); + ulp_status, ulp_word4, cmdcode); - if (irsp->ulpStatus) { + if (ulp_status) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0268 NS cmd x%x Error (x%x x%x)\n", - cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]); + cmdcode, ulp_status, ulp_word4); - if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - (((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == - IOERR_SLI_DOWN) || - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == - IOERR_SLI_ABORTED))) + if (ulp_status == IOSTAT_LOCAL_REJECT && + (((ulp_word4 & IOERR_PARAM_MASK) == + IOERR_SLI_DOWN) || + ((ulp_word4 & IOERR_PARAM_MASK) == + IOERR_SLI_ABORTED))) goto out; retry = cmdiocb->retry; @@ -1684,10 +1665,10 @@ static void lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_vport *vport = cmdiocb->vport; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; @@ -1705,10 +1686,10 @@ static void lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_vport *vport = cmdiocb->vport; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; @@ -1726,10 +1707,10 @@ static void lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_vport *vport = cmdiocb->vport; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; @@ -1747,10 +1728,10 @@ static void lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_vport *vport = cmdiocb->vport; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; @@ -1780,10 +1761,10 @@ static void lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_vport *vport = cmdiocb->vport; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; @@ -2194,20 +2175,21 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_sli_ct_request *CTrsp = outp->virt; uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_nodelist *ndlp, *free_ndlp = NULL; uint32_t latt, cmd, err; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); latt = lpfc_els_chk_latt(vport); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "FDMI cmpl: status:x%x/x%x latt:%d", - irsp->ulpStatus, irsp->un.ulpWord[4], latt); + ulp_status, ulp_word4, latt); - if (latt || irsp->ulpStatus) { + if (latt || ulp_status) { /* Look for a retryable error */ - if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) { - switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) { + if (ulp_status == IOSTAT_LOCAL_REJECT) { + switch ((ulp_word4 & IOERR_PARAM_MASK)) { case IOERR_SLI_ABORTED: case IOERR_SLI_DOWN: /* Driver aborted this IO. No retry as error @@ -2237,9 +2219,9 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0229 FDMI cmd %04x failed, latt = %d " - "ulpStatus: x%x, rid x%x\n", - be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, - irsp->un.ulpWord[4]); + "ulp_status: x%x, rid x%x\n", + be16_to_cpu(fdmi_cmd), latt, ulp_status, + ulp_word4); } free_ndlp = cmdiocb->context_un.ndlp; @@ -3813,7 +3795,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (cmd == SLI_CTAS_DALLAPP_ID) lpfc_ct_free_iocb(phba, cmdiocb); - if (lpfc_els_chk_latt(vport) || rspiocb->iocb.ulpStatus) { + if (lpfc_els_chk_latt(vport) || get_job_ulpstatus(phba, rspiocb)) { if (cmd != SLI_CTAS_DALLAPP_ID) return; } diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 30fac2f6fb06..7b24c932e812 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -6272,9 +6272,9 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) phba->hba_debugfs_root, phba, &lpfc_debugfs_op_slow_ring_trc); if (!phba->slow_ring_trc) { - phba->slow_ring_trc = kmalloc( - (sizeof(struct lpfc_debugfs_trc) * - lpfc_debugfs_max_slow_ring_trc), + phba->slow_ring_trc = kcalloc( + lpfc_debugfs_max_slow_ring_trc, + sizeof(struct lpfc_debugfs_trc), GFP_KERNEL); if (!phba->slow_ring_trc) { lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, @@ -6283,9 +6283,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) goto debug_failed; } atomic_set(&phba->slow_ring_trc_cnt, 0); - memset(phba->slow_ring_trc, 0, - (sizeof(struct lpfc_debugfs_trc) * - lpfc_debugfs_max_slow_ring_trc)); } snprintf(name, sizeof(name), "nvmeio_trc"); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f936833c9909..ef6e8cd8c26a 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -134,9 +134,9 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) /** * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure * @vport: pointer to a host virtual N_Port data structure. - * @expectRsp: flag indicating whether response is expected. - * @cmdSize: size of the ELS command. - * @retry: number of retries to the command IOCB when it fails. + * @expect_rsp: flag indicating whether response is expected. + * @cmd_size: size of the ELS command. + * @retry: number of retries to the command when it fails. * @ndlp: pointer to a node-list data structure. * @did: destination identifier. * @elscmd: the ELS command code. @@ -160,25 +160,23 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) * NULL - when els iocb data structure allocation/preparation failed **/ struct lpfc_iocbq * -lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, - uint16_t cmdSize, uint8_t retry, - struct lpfc_nodelist *ndlp, uint32_t did, - uint32_t elscmd) +lpfc_prep_els_iocb(struct lpfc_vport *vport, u8 expect_rsp, + u16 cmd_size, u8 retry, + struct lpfc_nodelist *ndlp, u32 did, + u32 elscmd) { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; - struct lpfc_dmabuf *pcmd, *prsp, *pbuflist; - struct ulp_bde64 *bpl; - IOCB_t *icmd; - + struct lpfc_dmabuf *pcmd, *prsp, *pbuflist, *bmp; + struct ulp_bde64_le *bpl; + u32 timeout = 0; if (!lpfc_is_link_up(phba)) return NULL; /* Allocate buffer for command iocb */ elsiocb = lpfc_sli_get_iocbq(phba); - - if (elsiocb == NULL) + if (!elsiocb) return NULL; /* @@ -186,35 +184,33 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, * in FIP mode send FLOGI, FDISC and LOGO as FIP frames. */ if ((did == Fabric_DID) && - (phba->hba_flag & HBA_FIP_SUPPORT) && - ((elscmd == ELS_CMD_FLOGI) || - (elscmd == ELS_CMD_FDISC) || - (elscmd == ELS_CMD_LOGO))) + (phba->hba_flag & HBA_FIP_SUPPORT) && + ((elscmd == ELS_CMD_FLOGI) || + (elscmd == ELS_CMD_FDISC) || + (elscmd == ELS_CMD_LOGO))) switch (elscmd) { case ELS_CMD_FLOGI: - elsiocb->iocb_flag |= - ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) - & LPFC_FIP_ELS_ID_MASK); - break; + elsiocb->cmd_flag |= + ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; case ELS_CMD_FDISC: - elsiocb->iocb_flag |= - ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) - & LPFC_FIP_ELS_ID_MASK); - break; + elsiocb->cmd_flag |= + ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; case ELS_CMD_LOGO: - elsiocb->iocb_flag |= - ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) - & LPFC_FIP_ELS_ID_MASK); - break; + elsiocb->cmd_flag |= + ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; } else - elsiocb->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; - - icmd = &elsiocb->iocb; + elsiocb->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; /* fill in BDEs for command */ /* Allocate buffer for command payload */ - pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); + pcmd = kmalloc(sizeof(*pcmd), GFP_KERNEL); if (pcmd) pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys); if (!pcmd || !pcmd->virt) @@ -223,19 +219,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, INIT_LIST_HEAD(&pcmd->list); /* Allocate buffer for response payload */ - if (expectRsp) { - prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); + if (expect_rsp) { + prsp = kmalloc(sizeof(*prsp), GFP_KERNEL); if (prsp) prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &prsp->phys); if (!prsp || !prsp->virt) goto els_iocb_free_prsp_exit; INIT_LIST_HEAD(&prsp->list); - } else + } else { prsp = NULL; + } /* Allocate buffer for Buffer ptr list */ - pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); + pbuflist = kmalloc(sizeof(*pbuflist), GFP_KERNEL); if (pbuflist) pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pbuflist->phys); @@ -244,70 +241,42 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, INIT_LIST_HEAD(&pbuflist->list); - if (expectRsp) { - icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); - icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys); - icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); - - icmd->un.elsreq64.remoteID = did; /* DID */ - icmd->ulpCommand = CMD_ELS_REQUEST64_CR; - if (elscmd == ELS_CMD_FLOGI) - icmd->ulpTimeout = FF_DEF_RATOV * 2; - else if (elscmd == ELS_CMD_LOGO) - icmd->ulpTimeout = phba->fc_ratov; - else - icmd->ulpTimeout = phba->fc_ratov * 2; - } else { - icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); - icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys); - icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; - icmd->un.xseq64.bdl.bdeSize = sizeof(struct ulp_bde64); - icmd->un.xseq64.xmit_els_remoteID = did; /* DID */ - icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; - } - icmd->ulpBdeCount = 1; - icmd->ulpLe = 1; - icmd->ulpClass = CLASS3; - - /* - * If we have NPIV enabled, we want to send ELS traffic by VPI. - * For SLI4, since the driver controls VPIs we also want to include - * all ELS pt2pt protocol traffic as well. - */ - if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) || - ((phba->sli_rev == LPFC_SLI_REV4) && - (vport->fc_flag & FC_PT2PT))) { - - if (expectRsp) { - icmd->un.elsreq64.myID = vport->fc_myDID; - - /* For ELS_REQUEST64_CR, use the VPI by default */ - icmd->ulpContext = phba->vpi_ids[vport->vpi]; + if (expect_rsp) { + switch (elscmd) { + case ELS_CMD_FLOGI: + timeout = FF_DEF_RATOV * 2; + break; + case ELS_CMD_LOGO: + timeout = phba->fc_ratov; + break; + default: + timeout = phba->fc_ratov * 2; } - icmd->ulpCt_h = 0; - /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ - if (elscmd == ELS_CMD_ECHO) - icmd->ulpCt_l = 0; /* context = invalid RPI */ - else - icmd->ulpCt_l = 1; /* context = VPI */ + /* Fill SGE for the num bde count */ + elsiocb->num_bdes = 2; } - bpl = (struct ulp_bde64 *) pbuflist->virt; - bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys)); - bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys)); - bpl->tus.f.bdeSize = cmdSize; - bpl->tus.f.bdeFlags = 0; - bpl->tus.w = le32_to_cpu(bpl->tus.w); + if (phba->sli_rev == LPFC_SLI_REV4) + bmp = pcmd; + else + bmp = pbuflist; - if (expectRsp) { + lpfc_sli_prep_els_req_rsp(phba, elsiocb, vport, bmp, cmd_size, did, + elscmd, timeout, expect_rsp); + + bpl = (struct ulp_bde64_le *)pbuflist->virt; + bpl->addr_low = cpu_to_le32(putPaddrLow(pcmd->phys)); + bpl->addr_high = cpu_to_le32(putPaddrHigh(pcmd->phys)); + bpl->type_size = cpu_to_le32(cmd_size); + bpl->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64); + + if (expect_rsp) { bpl++; - bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys)); - bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys)); - bpl->tus.f.bdeSize = FCELSSIZE; - bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; - bpl->tus.w = le32_to_cpu(bpl->tus.w); + bpl->addr_low = cpu_to_le32(putPaddrLow(prsp->phys)); + bpl->addr_high = cpu_to_le32(putPaddrHigh(prsp->phys)); + bpl->type_size = cpu_to_le32(FCELSSIZE); + bpl->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64); } elsiocb->context2 = pcmd; @@ -316,18 +285,17 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, elsiocb->vport = vport; elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; - if (prsp) { + if (prsp) list_add(&prsp->list, &pcmd->list); - } - if (expectRsp) { + if (expect_rsp) { /* Xmit ELS command <elsCmd> to remote NPORT <did> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0116 Xmit ELS command x%x to remote " "NPORT x%x I/O tag: x%x, port state:x%x " - "rpi x%x fc_flag:x%x nlp_flag:x%x vport:x%p\n", + "rpi x%x fc_flag:x%x\n", elscmd, did, elsiocb->iotag, vport->port_state, ndlp->nlp_rpi, - vport->fc_flag, ndlp->nlp_flag, vport); + vport->fc_flag); } else { /* Xmit ELS response <elsCmd> to remote NPORT <did> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -335,13 +303,14 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, "NPORT x%x I/O tag: x%x, size: x%x " "port_state x%x rpi x%x fc_flag x%x\n", elscmd, ndlp->nlp_DID, elsiocb->iotag, - cmdSize, vport->port_state, + cmd_size, vport->port_state, ndlp->nlp_rpi, vport->fc_flag); } + return elsiocb; els_iocb_free_pbuf_exit: - if (expectRsp) + if (expect_rsp) lpfc_mbuf_free(phba, prsp->virt, prsp->phys); kfree(pbuflist); @@ -650,7 +619,7 @@ lpfc_check_clean_addr_bit(struct lpfc_vport *vport, * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @sp: pointer to service parameter data structure. - * @irsp: pointer to the IOCB within the lpfc response IOCB. + * @ulp_word4: command response value * * This routine is invoked by the lpfc_cmpl_els_flogi() completion callback * function to handle the completion of a Fabric Login (FLOGI) into a fabric @@ -667,7 +636,7 @@ lpfc_check_clean_addr_bit(struct lpfc_vport *vport, **/ static int lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, - struct serv_parm *sp, IOCB_t *irsp) + struct serv_parm *sp, uint32_t ulp_word4) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; @@ -692,7 +661,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_unlock_irq(shost->host_lock); } - vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; + vport->fc_myDID = ulp_word4 & Mask_DID; memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name)); memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name)); ndlp->nlp_class_sup = 0; @@ -903,10 +872,12 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (rc) vport->fc_myDID = PT2PT_LocalID; - /* Decrement ndlp reference count indicating that ndlp can be - * safely released when other references to it are done. + /* If not registered with a transport, decrement ndlp reference + * count indicating that ndlp can be safely released when other + * references are removed. */ - lpfc_nlp_put(ndlp); + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) + lpfc_nlp_put(ndlp); ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID); if (!ndlp) { @@ -943,11 +914,12 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, goto fail; } } else { - /* This side will wait for the PLOGI, decrement ndlp reference - * count indicating that ndlp can be released when other - * references to it are done. + /* This side will wait for the PLOGI. If not registered with + * a transport, decrement node reference count indicating that + * ndlp can be released when other references are removed. */ - lpfc_nlp_put(ndlp); + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) + lpfc_nlp_put(ndlp); /* Start discovery - this should just do CLEAR_LA */ lpfc_disc_start(vport); @@ -987,28 +959,40 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_nodelist *ndlp = cmdiocb->context1; + IOCB_t *irsp; struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp; struct serv_parm *sp; uint16_t fcf_index; int rc; + u32 ulp_status, ulp_word4, tmo; /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { /* One additional decrement on node reference count to * trigger the release of the node */ - lpfc_nlp_put(ndlp); + if (!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) + lpfc_nlp_put(ndlp); goto out; } + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + } + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "FLOGI cmpl: status:x%x/x%x state:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, vport->port_state); - if (irsp->ulpStatus) { + if (ulp_status) { /* * In case of FIP mode, perform roundrobin FCF failover * due to new FCF discovery @@ -1019,8 +1003,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto stop_rr_fcf_flogi; if ((phba->fcoe_cvl_eventtag_attn == phba->fcoe_cvl_eventtag) && - (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + (ulp_status == IOSTAT_LOCAL_REJECT) && + ((ulp_word4 & IOERR_PARAM_MASK) == IOERR_SLI_ABORTED)) goto stop_rr_fcf_flogi; else @@ -1031,8 +1015,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "status:x%x/x%x, tmo:x%x, perform " "roundrobin FCF failover\n", phba->fcf.current_rec.fcf_indx, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout); + ulp_status, ulp_word4, tmo); lpfc_sli4_set_fcf_flogi_fail(phba, phba->fcf.current_rec.fcf_indx); fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); @@ -1043,15 +1026,14 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, stop_rr_fcf_flogi: /* FLOGI failure */ - if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + if (!(ulp_status == IOSTAT_LOCAL_REJECT && + ((ulp_word4 & IOERR_PARAM_MASK) == IOERR_LOOP_OPEN_FAILURE))) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2858 FLOGI failure Status:x%x/x%x TMO" ":x%x Data x%x x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, phba->hba_flag, - phba->fcf.fcf_flag); + ulp_status, ulp_word4, tmo, + phba->hba_flag, phba->fcf.fcf_flag); /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) @@ -1060,15 +1042,20 @@ stop_rr_fcf_flogi: lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT, "0150 FLOGI failure Status:x%x/x%x " "xri x%x TMO:x%x refcnt %d\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - cmdiocb->sli4_xritag, irsp->ulpTimeout, - kref_read(&ndlp->kref)); + ulp_status, ulp_word4, cmdiocb->sli4_xritag, + tmo, kref_read(&ndlp->kref)); /* If this is not a loop open failure, bail out */ - if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == - IOERR_LOOP_OPEN_FAILURE))) + if (!(ulp_status == IOSTAT_LOCAL_REJECT && + ((ulp_word4 & IOERR_PARAM_MASK) == + IOERR_LOOP_OPEN_FAILURE))) { + /* FLOGI failure */ + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0100 FLOGI failure Status:x%x/x%x " + "TMO:x%x\n", + ulp_status, ulp_word4, tmo); goto flogifail; + } /* FLOGI failed, so there is no fabric */ spin_lock_irq(shost->host_lock); @@ -1099,7 +1086,7 @@ stop_rr_fcf_flogi: } /* Do not register VFI if the driver aborted FLOGI */ - if (!lpfc_error_lost_link(irsp)) + if (!lpfc_error_lost_link(ulp_status, ulp_word4)) lpfc_issue_reg_vfi(vport); lpfc_nlp_put(ndlp); @@ -1123,10 +1110,10 @@ stop_rr_fcf_flogi: /* FLOGI completes successfully */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "0101 FLOGI completes successfully, I/O tag:x%x, " + "0101 FLOGI completes successfully, I/O tag:x%x " "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x %d\n", cmdiocb->iotag, cmdiocb->sli4_xritag, - irsp->un.ulpWord[4], sp->cmn.e_d_tov, + ulp_word4, sp->cmn.e_d_tov, sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution, vport->port_state, vport->fc_flag, sp->cmn.priority_tagging, kref_read(&ndlp->kref)); @@ -1140,7 +1127,8 @@ stop_rr_fcf_flogi: * we are point to point, if Fport we are Fabric. */ if (sp->cmn.fPort) - rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp); + rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, + ulp_word4); else if (!(phba->hba_flag & HBA_FCOE_MODE)) rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); else { @@ -1207,16 +1195,16 @@ flogifail: phba->fcf.fcf_flag &= ~FCF_DISCOVERY; spin_unlock_irq(&phba->hbalock); - if (!lpfc_error_lost_link(irsp)) { + if (!lpfc_error_lost_link(ulp_status, ulp_word4)) { /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); /* Start discovery */ lpfc_disc_start(vport); - } else if (((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || - (((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) != + } else if (((ulp_status != IOSTAT_LOCAL_REJECT) || + (((ulp_word4 & IOERR_PARAM_MASK) != IOERR_SLI_ABORTED) && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) != + ((ulp_word4 & IOERR_PARAM_MASK) != IOERR_SLI_DOWN))) && (phba->link_state != LPFC_CLEAR_LA)) { /* If FLOGI failed enable link interrupt. */ @@ -1240,22 +1228,24 @@ static void lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp; uint32_t *pcmd; uint32_t cmd; + u32 ulp_status, ulp_word4; pcmd = (uint32_t *)(((struct lpfc_dmabuf *)cmdiocb->context2)->virt); cmd = *pcmd; - irsp = &rspiocb->iocb; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "6445 ELS completes after LINK_DOWN: " " Status %x/%x cmd x%x flg x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], cmd, - cmdiocb->iocb_flag); + ulp_status, ulp_word4, cmd, + cmdiocb->cmd_flag); - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) { - cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; + if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) { + cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; atomic_dec(&phba->fabric_iocb_count); } lpfc_els_free_iocb(phba, cmdiocb); @@ -1288,10 +1278,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_hba *phba = vport->phba; struct serv_parm *sp; - IOCB_t *icmd; + union lpfc_wqe128 *wqe = NULL; + IOCB_t *icmd = NULL; struct lpfc_iocbq *elsiocb; struct lpfc_iocbq defer_flogi_acc; - uint8_t *pcmd; + u8 *pcmd, ct; uint16_t cmdsize; uint32_t tmo, did; int rc; @@ -1303,8 +1294,9 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; + wqe = &elsiocb->wqe; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + icmd = &elsiocb->iocb; /* For FLOGI request, remainder of payload is service parameters */ *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI; @@ -1337,12 +1329,15 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (phba->sli_rev == LPFC_SLI_REV4) { if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_IF_TYPE_0) { - elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1); - elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1); /* FLOGI needs to be 3 for WQE FCFI */ + ct = ((SLI4_CT_FCFI >> 1) & 1) | (SLI4_CT_FCFI & 1); + bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); + /* Set the fcfi to the fcfi we registered with */ - elsiocb->iocb.ulpContext = phba->fcf.fcfi; + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->fcf.fcfi); } + /* Can't do SLI4 class2 without support sequence coalescing */ sp->cls2.classValid = 0; sp->cls2.seqDelivery = 0; @@ -1355,13 +1350,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */ icmd->ulpCt_h = 1; icmd->ulpCt_l = 0; - } else + } else { sp->cmn.request_multiple_Nport = 0; - } + } - if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) { - icmd->un.elsreq64.myID = 0; - icmd->un.elsreq64.fl = 1; + if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) { + icmd->un.elsreq64.myID = 0; + icmd->un.elsreq64.fl = 1; + } } tmo = phba->fc_ratov; @@ -1370,7 +1366,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->fc_ratov = tmo; phba->fc_stat.elsXmitFLOGI++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; + elsiocb->cmd_cmpl = lpfc_cmpl_els_flogi; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue FLOGI: opt:x%x", @@ -1393,14 +1389,29 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Check for a deferred FLOGI ACC condition */ if (phba->defer_flogi_acc_flag) { + /* lookup ndlp for received FLOGI */ + ndlp = lpfc_findnode_did(vport, 0); + if (!ndlp) + return 0; + did = vport->fc_myDID; vport->fc_myDID = Fabric_DID; memset(&defer_flogi_acc, 0, sizeof(struct lpfc_iocbq)); - defer_flogi_acc.iocb.ulpContext = phba->defer_flogi_acc_rx_id; - defer_flogi_acc.iocb.unsli3.rcvsli3.ox_id = - phba->defer_flogi_acc_ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + bf_set(wqe_ctxt_tag, + &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com, + phba->defer_flogi_acc_rx_id); + bf_set(wqe_rcvoxid, + &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com, + phba->defer_flogi_acc_ox_id); + } else { + icmd = &defer_flogi_acc.iocb; + icmd->ulpContext = phba->defer_flogi_acc_rx_id; + icmd->unsli3.rcvsli3.ox_id = + phba->defer_flogi_acc_ox_id; + } lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3354 Xmit deferred FLOGI ACC: rx_id: x%x," @@ -1413,8 +1424,12 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp, NULL); phba->defer_flogi_acc_flag = false; - vport->fc_myDID = did; + + /* Decrement ndlp reference count to indicate the node can be + * released when other references are removed. + */ + lpfc_nlp_put(ndlp); } return 0; @@ -1440,7 +1455,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_nodelist *ndlp; - IOCB_t *icmd; + u32 ulp_command; /* Abort outstanding I/O on NPort <nlp_DID> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, @@ -1457,13 +1472,13 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) */ spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { - icmd = &iocb->iocb; - if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { + ulp_command = get_job_cmnd(phba, iocb); + if (ulp_command == CMD_ELS_REQUEST64_CR) { ndlp = (struct lpfc_nodelist *)(iocb->context1); if (ndlp && ndlp->nlp_DID == Fabric_DID) { if ((phba->pport->fc_flag & FC_PT2PT) && !(phba->pport->fc_flag & FC_PT2PT_PLOGI)) - iocb->fabric_iocb_cmpl = + iocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); @@ -1892,43 +1907,43 @@ lpfc_end_rscn(struct lpfc_vport *vport) static void lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) + struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - IOCB_t *irsp; struct lpfc_nodelist *ndlp = cmdiocb->context1; struct lpfc_node_rrq *rrq; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); /* we pass cmdiocb to state machine which needs rspiocb as well */ rrq = cmdiocb->context_un.rrq; cmdiocb->context_un.rsp_iocb = rspiocb; - irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "RRQ cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + ulp_status, ulp_word4, + get_job_els_rsp64_did(phba, cmdiocb)); + /* rrq completes to NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "2880 RRQ completes to DID x%x " "Data: x%x x%x x%x x%x x%x\n", - irsp->un.elsreq64.remoteID, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, rrq->xritag, rrq->rxid); + ndlp->nlp_DID, ulp_status, ulp_word4, + get_wqe_tmo(cmdiocb), rrq->xritag, rrq->rxid); - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ /* RRQ failed Don't print the vport to vport rjts */ - if (irsp->ulpStatus != IOSTAT_LS_RJT || - (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && - ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || - (phba)->pport->cfg_log_verbose & LOG_ELS) + if (ulp_status != IOSTAT_LS_RJT || + (((ulp_word4) >> 16 != LSRJT_INVALID_CMD) && + ((ulp_word4) >> 16 != LSRJT_UNABLE_TPC)) || + (phba)->pport->cfg_log_verbose & LOG_ELS) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2881 RRQ failure DID:%06X Status:" "x%x/x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4]); + ndlp->nlp_DID, ulp_status, + ulp_word4); } lpfc_clr_rrq_active(phba, rrq->xritag, rrq); @@ -1967,24 +1982,32 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *prsp; int disc; struct serv_parm *sp = NULL; + u32 ulp_status, ulp_word4, did, iotag; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - irsp = &rspiocb->iocb; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + did = get_job_els_rsp64_did(phba, cmdiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + iotag = get_wqe_reqtag(cmdiocb); + } else { + irsp = &rspiocb->iocb; + iotag = irsp->ulpIoTag; + } + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "PLOGI cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + ulp_status, ulp_word4, did); - ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); + ndlp = lpfc_findnode_did(vport, did); if (!ndlp) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0136 PLOGI completes to NPort x%x " "with no ndlp. Data: x%x x%x x%x\n", - irsp->un.elsreq64.remoteID, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpIoTag); + did, ulp_status, ulp_word4, iotag); goto out_freeiocb; } @@ -2001,7 +2024,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "0102 PLOGI completes to NPort x%06x " "Data: x%x x%x x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_fc4_type, - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, disc, vport->num_disc_nodes); /* Check to see if link went down during discovery */ @@ -2012,7 +2035,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ @@ -2024,17 +2047,18 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } /* PLOGI failed Don't print the vport to vport rjts */ - if (irsp->ulpStatus != IOSTAT_LS_RJT || - (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && - ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || - (phba)->pport->cfg_log_verbose & LOG_ELS) + if (ulp_status != IOSTAT_LS_RJT || + (((ulp_word4) >> 16 != LSRJT_INVALID_CMD) && + ((ulp_word4) >> 16 != LSRJT_UNABLE_TPC)) || + (phba)->pport->cfg_log_verbose & LOG_ELS) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4]); + "2753 PLOGI failure DID:%06X " + "Status:x%x/x%x\n", + ndlp->nlp_DID, ulp_status, + ulp_word4); /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (!lpfc_error_lost_link(irsp)) + if (!lpfc_error_lost_link(ulp_status, ulp_word4)) lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_PLOGI); @@ -2226,7 +2250,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) } phba->fc_stat.elsXmitPLOGI++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; + elsiocb->cmd_cmpl = lpfc_cmpl_els_plogi; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue PLOGI: did:x%x refcnt %d", @@ -2265,16 +2289,20 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - IOCB_t *irsp; struct lpfc_nodelist *ndlp; char *mode; u32 loglevel; + u32 ulp_status; + u32 ulp_word4; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - irsp = &(rspiocb->iocb); ndlp = (struct lpfc_nodelist *) cmdiocb->context1; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_PRLI_SND; @@ -2285,21 +2313,21 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "PRLI cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, ndlp->nlp_DID); /* PRLI completes to NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0103 PRLI completes to NPort x%06x " "Data: x%x x%x x%x x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + ndlp->nlp_DID, ulp_status, ulp_word4, vport->num_disc_nodes, ndlp->fc4_prli_sent); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) goto out; - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ @@ -2322,11 +2350,11 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, mode, loglevel, "2754 PRLI failure DID:%06X Status:x%x/x%x, " "data: x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], ndlp->fc4_prli_sent); + ndlp->nlp_DID, ulp_status, + ulp_word4, ndlp->fc4_prli_sent); /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (!lpfc_error_lost_link(irsp)) + if (!lpfc_error_lost_link(ulp_status, ulp_word4)) lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI); @@ -2485,7 +2513,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* For FCP support */ npr->prliType = PRLI_FCP_TYPE; npr->initiatorFunc = 1; - elsiocb->iocb_flag |= LPFC_PRLI_FCP_REQ; + elsiocb->cmd_flag |= LPFC_PRLI_FCP_REQ; /* Remove FCP type - processed. */ local_nlp_type &= ~NLP_FC4_FCP; @@ -2519,14 +2547,14 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); - elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ; + elsiocb->cmd_flag |= LPFC_PRLI_NVME_REQ; /* Remove NVME type - processed. */ local_nlp_type &= ~NLP_FC4_NVME; } phba->fc_stat.elsXmitPRLI++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; + elsiocb->cmd_cmpl = lpfc_cmpl_els_prli; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_PRLI_SND; @@ -2720,16 +2748,26 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, IOCB_t *irsp; struct lpfc_nodelist *ndlp; int disc; + u32 ulp_status, ulp_word4, tmo; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - irsp = &(rspiocb->iocb); ndlp = (struct lpfc_nodelist *) cmdiocb->context1; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + } + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "ADISC cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, ndlp->nlp_DID); /* Since ndlp can be freed in the disc state machine, note if this node @@ -2743,8 +2781,8 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0104 ADISC completes to NPort x%x " "Data: x%x x%x x%x x%x x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, disc, vport->num_disc_nodes); + ndlp->nlp_DID, ulp_status, ulp_word4, + tmo, disc, vport->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { spin_lock_irq(&ndlp->lock); @@ -2753,7 +2791,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } - if (irsp->ulpStatus) { + if (ulp_status) { /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ @@ -2768,11 +2806,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* ADISC failed */ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2755 ADISC failure DID:%06X Status:x%x/x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4]); - + ndlp->nlp_DID, ulp_status, + ulp_word4); lpfc_disc_state_machine(vport, ndlp, cmdiocb, - NLP_EVT_CMPL_ADISC); + NLP_EVT_CMPL_ADISC); /* As long as this node is not registered with the SCSI or NVMe * transport, it is no longer an active node. Otherwise @@ -2849,7 +2886,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ap->DID = be32_to_cpu(vport->fc_myDID); phba->fc_stat.elsXmitADISC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; + elsiocb->cmd_cmpl = lpfc_cmpl_els_adisc; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_ADISC_SND; spin_unlock_irq(&ndlp->lock); @@ -2862,6 +2899,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue ADISC: did:x%x refcnt %d", ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); @@ -2899,11 +2937,23 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, unsigned long flags; uint32_t skip_recovery = 0; int wake_up_waiter = 0; + u32 ulp_status; + u32 ulp_word4; + u32 tmo; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - irsp = &(rspiocb->iocb); + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + } + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_LOGO_SND; if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) { @@ -2914,7 +2964,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "LOGO cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, ndlp->nlp_DID); /* LOGO completes to NPort <nlp_DID> */ @@ -2922,8 +2972,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "0105 LOGO completes to NPort x%x " "refcnt %d nflags x%x Data: x%x x%x x%x x%x\n", ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, vport->num_disc_nodes); + ulp_status, ulp_word4, + tmo, vport->num_disc_nodes); if (lpfc_els_chk_latt(vport)) { skip_recovery = 1; @@ -2935,14 +2985,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * all acceptable. Note the failure and move forward with * discovery. The PLOGI will retry. */ - if (irsp->ulpStatus) { + if (ulp_status) { /* LOGO failed */ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4]); - /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (lpfc_error_lost_link(irsp)) { + "2756 LOGO failure, No Retry DID:%06X " + "Status:x%x/x%x\n", + ndlp->nlp_DID, ulp_status, + ulp_word4); + + if (lpfc_error_lost_link(ulp_status, ulp_word4)) { skip_recovery = 1; goto out; } @@ -2997,8 +3048,8 @@ out: lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3187 LOGO completes to NPort x%x: Start " "Recovery Data: x%x x%x x%x x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout, + ndlp->nlp_DID, ulp_status, + ulp_word4, tmo, vport->num_disc_nodes); lpfc_disc_start(vport); return; @@ -3072,7 +3123,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); phba->fc_stat.elsXmitLOGO++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; + elsiocb->cmd_cmpl = lpfc_cmpl_els_logo; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; @@ -3086,6 +3137,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue LOGO: did:x%x refcnt %d", ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); @@ -3128,19 +3180,29 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_nodelist *free_ndlp; IOCB_t *irsp; + u32 ulp_status, ulp_word4, tmo, did, iotag; - irsp = &rspiocb->iocb; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + did = get_job_els_rsp64_did(phba, cmdiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + iotag = get_wqe_reqtag(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + iotag = irsp->ulpIoTag; + } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "ELS cmd cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + ulp_status, ulp_word4, did); /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", - irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout); + iotag, ulp_status, ulp_word4, tmo); /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); @@ -3262,20 +3324,29 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, u32 *pdata; u32 cmd; struct lpfc_nodelist *ndlp = cmdiocb->context1; + u32 ulp_status, ulp_word4, tmo, did, iotag; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + did = get_job_els_rsp64_did(phba, cmdiocb); - irsp = &rspiocb->iocb; + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + iotag = get_wqe_reqtag(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + iotag = irsp->ulpIoTag; + } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "ELS cmd cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + ulp_status, ulp_word4, did); + /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT, - "0217 ELS cmd tag x%x completes Data: x%x x%x x%x " - "x%x\n", - irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout, - cmdiocb->retry); + "0217 ELS cmd tag x%x completes Data: x%x x%x x%x x%x\n", + iotag, ulp_status, ulp_word4, tmo, cmdiocb->retry); pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; if (!pcmd) @@ -3287,8 +3358,8 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmd = *pdata; /* Only 1 retry for ELS Timeout only */ - if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + if (ulp_status == IOSTAT_LOCAL_REJECT && + ((ulp_word4 & IOERR_PARAM_MASK) == IOERR_SEQUENCE_TIMEOUT)) { cmdiocb->retry++; if (cmdiocb->retry <= 1) { @@ -3313,11 +3384,11 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb); return; } - if (irsp->ulpStatus) { + if (ulp_status) { /* ELS discovery cmd completes with error */ - lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT, "4203 ELS cmd x%x error: x%x x%X\n", cmd, - irsp->ulpStatus, irsp->un.ulpWord[4]); + ulp_status, ulp_word4); goto out; } @@ -3342,7 +3413,7 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "4677 Fabric RDF Notification Grant " "Data: 0x%08x Reg: %x %x\n", be32_to_cpu( - prdf->reg_d1.desc_tags[i]), + prdf->reg_d1.desc_tags[i]), phba->cgn_reg_signal, phba->cgn_reg_fpin); } @@ -3424,7 +3495,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) ndlp->nlp_DID, 0, 0); phba->fc_stat.elsXmitSCR++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3521,7 +3592,7 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) event->portid.rscn_fid[2] = nportid & 0x000000FF; phba->fc_stat.elsXmitRSCN++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; + elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3587,7 +3658,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) } elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, - ndlp->nlp_DID, ELS_CMD_RNID); + ndlp->nlp_DID, ELS_CMD_FARPR); if (!elsiocb) return 1; @@ -3620,7 +3691,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ndlp->nlp_DID, 0, 0); phba->fc_stat.elsXmitFARPR++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; + elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3711,7 +3782,7 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) phba->cgn_reg_fpin); phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ; - elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3889,7 +3960,7 @@ static void lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp; + IOCB_t *irsp_iocb; struct fc_els_edc_resp *edc_rsp; struct fc_tlv_desc *tlv; struct fc_diag_cg_sig_desc *pcgd; @@ -3900,20 +3971,31 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, int desc_cnt = 0, bytes_remain; bool rcv_cap_desc = false; struct lpfc_nodelist *ndlp; + u32 ulp_status, ulp_word4, tmo, did, iotag; - irsp = &rspiocb->iocb; ndlp = cmdiocb->context1; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + did = get_job_els_rsp64_did(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(rspiocb); + iotag = get_wqe_reqtag(rspiocb); + } else { + irsp_iocb = &rspiocb->iocb; + tmo = irsp_iocb->ulpTimeout; + iotag = irsp_iocb->ulpIoTag; + } + lpfc_debugfs_disc_trc(phba->pport, LPFC_DISC_TRC_ELS_CMD, "EDC cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + ulp_status, ulp_word4, did); /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT, "4201 EDC cmd tag x%x completes Data: x%x x%x x%x\n", - irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout); + iotag, ulp_status, ulp_word4, tmo); pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; if (!pcmd) @@ -3924,7 +4006,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; /* Need to clear signal values, send features MB and RDF with FPIN. */ - if (irsp->ulpStatus) + if (ulp_status) goto out; prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); @@ -4182,7 +4264,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry) ndlp->nlp_DID, phba->cgn_reg_signal, phba->cgn_reg_fpin); - elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -4461,7 +4543,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - IOCB_t *irsp = &rspiocb->iocb; + union lpfc_wqe128 *irsp = &rspiocb->wqe; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; uint32_t *elscmd; @@ -4471,6 +4553,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, uint32_t cmd = 0; uint32_t did; int link_reset = 0, rc; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); /* Note: context2 may be 0 for internal driver abort @@ -4486,7 +4570,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, did = ndlp->nlp_DID; else { /* We should only hit this case for retrying PLOGI */ - did = irsp->un.elsreq64.remoteID; + did = get_job_els_rsp64_did(phba, rspiocb); ndlp = lpfc_findnode_did(vport, did); if (!ndlp && (cmd != ELS_CMD_PLOGI)) return 0; @@ -4494,9 +4578,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Retry ELS: wd7:x%x wd4:x%x did:x%x", - *(((uint32_t *)irsp) + 7), irsp->un.ulpWord[4], did); + *(((uint32_t *)irsp) + 7), ulp_word4, did); - switch (irsp->ulpStatus) { + switch (ulp_status) { case IOSTAT_FCP_RSP_ERROR: break; case IOSTAT_REMOTE_STOP: @@ -4510,7 +4594,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } break; case IOSTAT_LOCAL_REJECT: - switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) { + switch ((ulp_word4 & IOERR_PARAM_MASK)) { case IOERR_LOOP_OPEN_FAILURE: if (cmd == ELS_CMD_FLOGI) { if (PCI_DEVICE_ID_HORNET == @@ -4591,7 +4675,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, case IOSTAT_NPORT_RJT: case IOSTAT_FABRIC_RJT: - if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) { + if (ulp_word4 & RJT_UNAVAIL_TEMP) { retry = 1; break; } @@ -4604,7 +4688,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, break; case IOSTAT_LS_RJT: - stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]); + stat.un.ls_rjt_error_be = cpu_to_be32(ulp_word4); /* Added for Vendor specifc support * Just keep retrying for these Rsn / Exp codes */ @@ -4747,12 +4831,14 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * on this rport. */ if (stat.un.b.lsRjtRsnCodeExp == - LSEXP_REQ_UNSUPPORTED && cmd == ELS_CMD_PRLI) { - spin_lock_irq(&ndlp->lock); - ndlp->nlp_flag |= NLP_FCP_PRLI_RJT; - spin_unlock_irq(&ndlp->lock); - retry = 0; - goto out_retry; + LSEXP_REQ_UNSUPPORTED) { + if (cmd == ELS_CMD_PRLI) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_FCP_PRLI_RJT; + spin_unlock_irq(&ndlp->lock); + retry = 0; + goto out_retry; + } } break; } @@ -4784,7 +4870,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if ((cmd == ELS_CMD_FLOGI) && (phba->fc_topology != LPFC_TOPOLOGY_LOOP) && - !lpfc_error_lost_link(irsp)) { + !lpfc_error_lost_link(ulp_status, ulp_word4)) { /* FLOGI retry policy */ retry = 1; /* retry FLOGI forever */ @@ -4797,7 +4883,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, delay = 5000; else if (cmdiocb->retry >= 32) delay = 1000; - } else if ((cmd == ELS_CMD_FDISC) && !lpfc_error_lost_link(irsp)) { + } else if ((cmd == ELS_CMD_FDISC) && + !lpfc_error_lost_link(ulp_status, ulp_word4)) { /* retry FDISCs every second up to devloss */ retry = 1; maxretry = vport->cfg_devloss_tmo; @@ -4834,8 +4921,8 @@ out_retry: cmd, did, cmdiocb->retry, delay); if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) && - ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) != + ((ulp_status != IOSTAT_LOCAL_REJECT) || + ((ulp_word4 & IOERR_PARAM_MASK) != IOERR_NO_RESOURCES))) { /* Don't reset timer for no resources */ @@ -4907,15 +4994,15 @@ out_retry: lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0137 No retry ELS command x%x to remote " "NPORT x%x: Out of Resources: Error:x%x/%x\n", - cmd, did, irsp->ulpStatus, - irsp->un.ulpWord[4]); + cmd, did, ulp_status, + ulp_word4); } else { lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0108 No retry ELS command x%x to remote " "NPORT x%x Retried:%d Error:x%x/%x\n", - cmd, did, cmdiocb->retry, irsp->ulpStatus, - irsp->un.ulpWord[4]); + cmd, did, cmdiocb->retry, ulp_status, + ulp_word4); } return 0; } @@ -5009,12 +5096,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) /* context2 = cmd, context2->next = rsp, context3 = bpl */ if (elsiocb->context2) { - if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) { + if (elsiocb->cmd_flag & LPFC_DELAY_MEM_FREE) { /* Firmware could still be in progress of DMAing * payload, so don't free data buffer till after * a hbeat. */ - elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE; + elsiocb->cmd_flag &= ~LPFC_DELAY_MEM_FREE; buf_ptr = elsiocb->context2; elsiocb->context2 = NULL; if (buf_ptr) { @@ -5073,12 +5160,14 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_vport *vport = cmdiocb->vport; - IOCB_t *irsp; + u32 ulp_status, ulp_word4; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); - irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "ACC LOGO cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); + ulp_status, ulp_word4, ndlp->nlp_DID); /* ACC to LOGO completes to NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0109 ACC to LOGO completes to NPort x%x refcnt %d " @@ -5096,7 +5185,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; if (ndlp->nlp_state == NLP_STE_NPR_NODE) { - /* If PLOGI is being retried, PLOGI completion will cleanup the * node. The NLP_NPR_2B_DISC flag needs to be retained to make * progress on nodes discovered from last RSCN. @@ -5203,8 +5291,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, IOCB_t *irsp; LPFC_MBOXQ_t *mbox = NULL; struct lpfc_dmabuf *mp = NULL; - - irsp = &rspiocb->iocb; + u32 ulp_status, ulp_word4, tmo, did, iotag; if (!vport) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -5214,6 +5301,19 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (cmdiocb->context_un.mbox) mbox = cmdiocb->context_un.mbox; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + did = get_job_els_rsp64_did(phba, cmdiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + tmo = get_wqe_tmo(cmdiocb); + iotag = get_wqe_reqtag(cmdiocb); + } else { + irsp = &rspiocb->iocb; + tmo = irsp->ulpTimeout; + iotag = irsp->ulpIoTag; + } + /* Check to see if link went down during discovery */ if (!ndlp || lpfc_els_chk_latt(vport)) { if (mbox) { @@ -5229,22 +5329,22 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "ELS rsp cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - cmdiocb->iocb.un.elsreq64.remoteID); + ulp_status, ulp_word4, did); /* ELS response tag <ulpIoTag> completes */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0110 ELS response tag x%x completes " - "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%px\n", - cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, - rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, + "Data: x%x x%x x%x x%x x%x x%x x%x x%x %p %p\n", + iotag, ulp_status, ulp_word4, tmo, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi, kref_read(&ndlp->kref), mbox); + ndlp->nlp_rpi, kref_read(&ndlp->kref), mbox, ndlp); if (mbox) { - if ((rspiocb->iocb.ulpStatus == 0) && - (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { + if (ulp_status == 0 + && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { if (!lpfc_unreg_rpi(vport, ndlp) && (!(vport->fc_flag & FC_PT2PT))) { - if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) { + if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || + ndlp->nlp_state == + NLP_STE_REG_LOGIN_ISSUE) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0314 PLOGI recov " @@ -5325,12 +5425,15 @@ out: (vport && vport->port_type == LPFC_NPIV_PORT) && !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) && ndlp->nlp_flag & NLP_RELEASE_RPI) { - lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); - spin_lock_irq(&ndlp->lock); - ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - ndlp->nlp_flag &= ~NLP_RELEASE_RPI; - spin_unlock_irq(&ndlp->lock); - lpfc_drop_node(vport, ndlp); + if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { + lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); + spin_lock_irq(&ndlp->lock); + ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + spin_unlock_irq(&ndlp->lock); + lpfc_drop_node(vport, ndlp); + } } /* Release the originating I/O reference. */ @@ -5372,6 +5475,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, struct lpfc_hba *phba = vport->phba; IOCB_t *icmd; IOCB_t *oldcmd; + union lpfc_wqe128 *wqe; + union lpfc_wqe128 *oldwqe = &oldiocb->wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; struct serv_parm *sp; @@ -5380,8 +5485,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, ELS_PKT *els_pkt_ptr; struct fc_els_rdf_resp *rdf_resp; - oldcmd = &oldiocb->iocb; - switch (flag) { case ELS_CMD_ACC: cmdsize = sizeof(uint32_t); @@ -5394,9 +5497,25 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, return 1; } - icmd = &elsiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* XRI / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_ctxt_tag, + &oldwqe->xmit_els_rsp.wqe_com)); + + /* oxid */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_rcvoxid, + &oldwqe->xmit_els_rsp.wqe_com)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } + pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); @@ -5413,9 +5532,25 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* XRI / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_ctxt_tag, + &oldwqe->xmit_els_rsp.wqe_com)); + + /* oxid */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_rcvoxid, + &oldwqe->xmit_els_rsp.wqe_com)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } + pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); if (mbox) @@ -5475,9 +5610,25 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* XRI / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_ctxt_tag, + &oldwqe->xmit_els_rsp.wqe_com)); + + /* oxid */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_rcvoxid, + &oldwqe->xmit_els_rsp.wqe_com)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } + pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt, @@ -5497,9 +5648,25 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* XRI / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_ctxt_tag, + &oldwqe->xmit_els_rsp.wqe_com)); + + /* oxid */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + bf_get(wqe_rcvoxid, + &oldwqe->xmit_els_rsp.wqe_com)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } + pcmd = (((struct lpfc_dmabuf *)elsiocb->context2)->virt); rdf_resp = (struct fc_els_rdf_resp *)pcmd; memset(rdf_resp, 0, sizeof(*rdf_resp)); @@ -5522,9 +5689,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, ndlp->nlp_flag & NLP_REG_LOGIN_SEND)) ndlp->nlp_flag &= ~NLP_LOGO_ACC; spin_unlock_irq(&ndlp->lock); - elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; + elsiocb->cmd_cmpl = lpfc_cmpl_els_logo_acc; } else { - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; } phba->fc_stat.elsXmitACC++; @@ -5583,6 +5750,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, struct lpfc_hba *phba = vport->phba; IOCB_t *icmd; IOCB_t *oldcmd; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; @@ -5593,10 +5761,19 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); /* Xri / rx_id */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + } + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT; @@ -5612,14 +5789,14 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " "rpi x%x\n", rejectError, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, + get_job_ulpcontext(phba, elsiocb), ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "Issue LS_RJT: did:x%x flg:x%x err:x%x", ndlp->nlp_DID, ndlp->nlp_flag, rejectError); phba->fc_stat.elsXmitLSRJT++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -5670,6 +5847,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_els_edc_rsp *edc_rsp; struct lpfc_iocbq *elsiocb; IOCB_t *icmd, *cmd; + union lpfc_wqe128 *wqe; uint8_t *pcmd; int cmdsize, rc; @@ -5679,11 +5857,21 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - cmd = &cmdiocb->iocb; - icmd->ulpContext = cmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = cmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, cmdiocb)); /* Xri / rx_id */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, cmdiocb)); + } else { + icmd = &elsiocb->iocb; + cmd = &cmdiocb->iocb; + icmd->ulpContext = cmd->ulpContext; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = cmd->unsli3.rcvsli3.ox_id; + } + pcmd = (((struct lpfc_dmabuf *)elsiocb->context2)->virt); + memset(pcmd, 0, cmdsize); edc_rsp = (struct lpfc_els_edc_rsp *)pcmd; @@ -5700,7 +5888,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, "Issue EDC ACC: did:x%x flg:x%x refcnt %d", ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); @@ -5754,10 +5942,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, struct lpfc_hba *phba = vport->phba; ADISC *ap; IOCB_t *icmd, *oldcmd; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; int rc; + u32 ulp_context; cmdsize = sizeof(uint32_t) + sizeof(ADISC); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, @@ -5765,16 +5955,29 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* XRI / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); + ulp_context = get_job_ulpcontext(phba, elsiocb); + /* oxid */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + ulp_context = elsiocb->iocb.ulpContext; + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } /* Xmit ADISC ACC response tag <ulpIoTag> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0130 Xmit ADISC ACC response iotag x%x xri: " "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -5793,7 +5996,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -5807,14 +6010,6 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, return 1; } - /* Xmit ELS ACC response tag <ulpIoTag> */ - lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "0128 Xmit ELS ACC response Status: x%x, IoTag: x%x, " - "XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x " - "RPI: x%x, fc_flag x%x\n", - rc, elsiocb->iotag, elsiocb->sli4_xritag, - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi, vport->fc_flag); return 0; } @@ -5847,13 +6042,14 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, lpfc_vpd_t *vpd; IOCB_t *icmd; IOCB_t *oldcmd; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; uint32_t prli_fc4_req, *req_payload; struct lpfc_dmabuf *req_buf; int rc; - u32 elsrspcmd; + u32 elsrspcmd, ulp_context; /* Need the incoming PRLI payload to determine if the ACC is for an * FC4 or NVME PRLI type. The PRLI type is at word 1. @@ -5879,20 +6075,31 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, } elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, - ndlp->nlp_DID, elsrspcmd); + ndlp->nlp_DID, elsrspcmd); if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); /* Xri / rx_id */ + ulp_context = get_job_ulpcontext(phba, elsiocb); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + ulp_context = elsiocb->iocb.ulpContext; + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } /* Xmit PRLI ACC response tag <ulpIoTag> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0131 Xmit PRLI ACC response tag x%x xri x%x, " "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -5967,7 +6174,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6011,10 +6218,12 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, struct lpfc_hba *phba = vport->phba; RNID *rn; IOCB_t *icmd, *oldcmd; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; int rc; + u32 ulp_context; cmdsize = sizeof(uint32_t) + sizeof(uint32_t) + (2 * sizeof(struct lpfc_name)); @@ -6026,15 +6235,26 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); /* Xri / rx_id */ + ulp_context = get_job_ulpcontext(phba, elsiocb); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + ulp_context = elsiocb->iocb.ulpContext; + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } /* Xmit RNID ACC response tag <ulpIoTag> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0132 Xmit RNID ACC response tag x%x xri x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext); + elsiocb->iotag, ulp_context); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); @@ -6068,7 +6288,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6117,7 +6337,8 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport, be32_to_cpu(bf_get(rrq_did, rrq)), bf_get(rrq_oxid, rrq), rxid, - iocb->iotag, iocb->iocb.ulpContext); + get_wqe_reqtag(iocb), + get_job_ulpcontext(phba, iocb)); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", @@ -6148,12 +6369,18 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) { struct lpfc_hba *phba = vport->phba; + IOCB_t *icmd, *oldcmd; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; int rc; + u32 ulp_context; - cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len; + if (phba->sli_rev == LPFC_SLI_REV4) + cmdsize = oldiocb->wcqe_cmpl.total_data_placed; + else + cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len; /* The accumulated length can exceed the BPL_SIZE. For * now, use this as the limit @@ -6165,13 +6392,26 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, if (!elsiocb) return 1; - elsiocb->iocb.ulpContext = oldiocb->iocb.ulpContext; /* Xri / rx_id */ - elsiocb->iocb.unsli3.rcvsli3.ox_id = oldiocb->iocb.unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); /* Xri / rx_id */ + ulp_context = get_job_ulpcontext(phba, elsiocb); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ + ulp_context = elsiocb->iocb.ulpContext; + icmd->unsli3.rcvsli3.ox_id = + oldcmd->unsli3.rcvsli3.ox_id; + } /* Xmit ECHO ACC response tag <ulpIoTag> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "2876 Xmit ECHO ACC response tag x%x xri x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext); + elsiocb->iotag, ulp_context); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); @@ -6182,7 +6422,7 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6767,12 +7007,14 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, struct lpfc_iocbq *elsiocb; struct ulp_bde64 *bpl; IOCB_t *icmd; + union lpfc_wqe128 *wqe; uint8_t *pcmd; struct ls_rjt *stat; struct fc_rdp_res_frame *rdp_res; uint32_t cmdsize, len; uint16_t *flag_ptr; int rc; + u32 ulp_context; if (status != SUCCESS) goto error; @@ -6781,19 +7023,29 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, cmdsize = sizeof(struct fc_rdp_res_frame); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, - lpfc_max_els_tries, rdp_context->ndlp, - rdp_context->ndlp->nlp_DID, ELS_CMD_ACC); + lpfc_max_els_tries, rdp_context->ndlp, + rdp_context->ndlp->nlp_DID, ELS_CMD_ACC); if (!elsiocb) goto free_rdp_context; - icmd = &elsiocb->iocb; - icmd->ulpContext = rdp_context->rx_id; - icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id; + ulp_context = get_job_ulpcontext(phba, elsiocb); + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* ox-id of the frame */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + rdp_context->ox_id); + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + rdp_context->rx_id); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = rdp_context->rx_id; + icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id; + } lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "2171 Xmit RDP response tag x%x xri x%x, " "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); rdp_res = (struct fc_rdp_res_frame *) @@ -6846,7 +7098,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, rdp_context->page_a0, vport); rdp_res->length = cpu_to_be32(len - 8); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; /* Now that we know the true size of the payload, update the BPL */ bpl = (struct ulp_bde64 *) @@ -6877,9 +7129,20 @@ error: if (!elsiocb) goto free_rdp_context; - icmd = &elsiocb->iocb; - icmd->ulpContext = rdp_context->rx_id; - icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* ox-id of the frame */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + rdp_context->ox_id); + bf_set(wqe_ctxt_tag, + &wqe->xmit_els_rsp.wqe_com, + rdp_context->rx_id); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = rdp_context->rx_id; + icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id; + } + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT; @@ -6887,7 +7150,7 @@ error: stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; phba->fc_stat.elsXmitLSRJT++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6902,7 +7165,7 @@ error: free_rdp_context: /* This reference put is for the original unsolicited RDP. If the - * iocb prep failed, there is no reference to remove. + * prep failed, there is no reference to remove. */ lpfc_nlp_put(ndlp); kfree(rdp_context); @@ -6968,7 +7231,7 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, uint8_t rjt_err, rjt_expl = LSEXP_NOTHING_MORE; struct fc_rdp_req_frame *rdp_req; struct lpfc_rdp_context *rdp_context; - IOCB_t *cmd = NULL; + union lpfc_wqe128 *cmd = NULL; struct ls_rjt stat; if (phba->sli_rev < LPFC_SLI_REV4 || @@ -7010,15 +7273,17 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, goto error; } - cmd = &cmdiocb->iocb; + cmd = &cmdiocb->wqe; rdp_context->ndlp = lpfc_nlp_get(ndlp); if (!rdp_context->ndlp) { kfree(rdp_context); rjt_err = LSRJT_UNABLE_TPC; goto error; } - rdp_context->ox_id = cmd->unsli3.rcvsli3.ox_id; - rdp_context->rx_id = cmd->ulpContext; + rdp_context->ox_id = bf_get(wqe_rcvoxid, + &cmd->xmit_els_rsp.wqe_com); + rdp_context->rx_id = bf_get(wqe_ctxt_tag, + &cmd->xmit_els_rsp.wqe_com); rdp_context->cmpl = lpfc_els_rdp_cmpl; if (lpfc_get_rdp_info(phba, rdp_context)) { lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_ELS, @@ -7048,6 +7313,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { MAILBOX_t *mb; IOCB_t *icmd; + union lpfc_wqe128 *wqe; uint8_t *pcmd; struct lpfc_iocbq *elsiocb; struct lpfc_nodelist *ndlp; @@ -7098,9 +7364,17 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) (((struct lpfc_dmabuf *)elsiocb->context2)->virt); memset(lcb_res, 0, sizeof(struct fc_lcb_res_frame)); - icmd = &elsiocb->iocb; - icmd->ulpContext = lcb_context->rx_id; - icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id; + + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, lcb_context->rx_id); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + lcb_context->ox_id); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = lcb_context->rx_id; + icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id; + } pcmd = (uint8_t *)(((struct lpfc_dmabuf *)elsiocb->context2)->virt); *((uint32_t *)(pcmd)) = ELS_CMD_ACC; @@ -7109,7 +7383,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lcb_res->capability = lcb_context->capability; lcb_res->lcb_frequency = lcb_context->frequency; lcb_res->lcb_duration = lcb_context->duration; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); @@ -7130,15 +7404,23 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) error: cmdsize = sizeof(struct fc_lcb_res_frame); elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, - lpfc_max_els_tries, ndlp, - ndlp->nlp_DID, ELS_CMD_LS_RJT); + lpfc_max_els_tries, ndlp, + ndlp->nlp_DID, ELS_CMD_LS_RJT); lpfc_nlp_put(ndlp); if (!elsiocb) goto free_lcb_context; - icmd = &elsiocb->iocb; - icmd->ulpContext = lcb_context->rx_id; - icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, lcb_context->rx_id); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + lcb_context->ox_id); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = lcb_context->rx_id; + icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id; + } + pcmd = (uint8_t *)(((struct lpfc_dmabuf *)elsiocb->context2)->virt); *((uint32_t *)(pcmd)) = ELS_CMD_LS_RJT; @@ -7148,7 +7430,7 @@ error: if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitLSRJT++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -7303,8 +7585,8 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lcb_context->type = beacon->lcb_type; lcb_context->frequency = beacon->lcb_frequency; lcb_context->duration = beacon->lcb_duration; - lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id; - lcb_context->rx_id = cmdiocb->iocb.ulpContext; + lcb_context->ox_id = get_job_rcvoxid(phba, cmdiocb); + lcb_context->rx_id = get_job_ulpcontext(phba, cmdiocb); lcb_context->ndlp = lpfc_nlp_get(ndlp); if (!lcb_context->ndlp) { rjt_err = LSRJT_UNABLE_TPC; @@ -7645,6 +7927,13 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); + /* Restart disctmo if its already running */ + if (vport->fc_flag & FC_DISC_TMO) { + tmo = ((phba->fc_ratov * 3) + 3); + mod_timer(&vport->fc_disctmo, + jiffies + + msecs_to_jiffies(1000 * tmo)); + } return 0; } } @@ -7866,7 +8155,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_hba *phba = vport->phba; struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; uint32_t *lp = (uint32_t *) pcmd->virt; - IOCB_t *icmd = &cmdiocb->iocb; + union lpfc_wqe128 *wqe = &cmdiocb->wqe; struct serv_parm *sp; LPFC_MBOXQ_t *mbox; uint32_t cmd, did; @@ -7883,7 +8172,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* We should never receive a FLOGI in loop mode, ignore it */ - did = icmd->un.elsreq64.remoteID; + did = bf_get(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest); /* An FLOGI ELS command <elsCmd> was received from DID <did> in Loop Mode */ @@ -7979,9 +8268,10 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, /* Defer ACC response until AFTER we issue a FLOGI */ if (!(phba->hba_flag & HBA_FLOGI_ISSUED)) { - phba->defer_flogi_acc_rx_id = cmdiocb->iocb.ulpContext; - phba->defer_flogi_acc_ox_id = - cmdiocb->iocb.unsli3.rcvsli3.ox_id; + phba->defer_flogi_acc_rx_id = bf_get(wqe_ctxt_tag, + &wqe->xmit_els_rsp.wqe_com); + phba->defer_flogi_acc_ox_id = bf_get(wqe_rcvoxid, + &wqe->xmit_els_rsp.wqe_com); vport->fc_myDID = did; @@ -8158,6 +8448,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) int rc = 0; MAILBOX_t *mb; IOCB_t *icmd; + union lpfc_wqe128 *wqe; struct RLS_RSP *rls_rsp; uint8_t *pcmd; struct lpfc_iocbq *elsiocb; @@ -8165,6 +8456,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) uint16_t oxid; uint16_t rxid; uint32_t cmdsize; + u32 ulp_context; mb = &pmb->u.mb; @@ -8192,9 +8484,17 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; } - icmd = &elsiocb->iocb; - icmd->ulpContext = rxid; - icmd->unsli3.rcvsli3.ox_id = oxid; + ulp_context = get_job_ulpcontext(phba, elsiocb); + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* Xri / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, rxid); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, oxid); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = rxid; + icmd->unsli3.rcvsli3.ox_id = oxid; + } pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; @@ -8212,10 +8512,10 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, "2874 Xmit ELS RLS ACC response tag x%x xri x%x, " "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8256,6 +8556,8 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *mbox; struct ls_rjt stat; + u32 ctx = get_job_ulpcontext(phba, cmdiocb); + u32 ox_id = get_job_rcvoxid(phba, cmdiocb); if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) @@ -8266,8 +8568,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if (mbox) { lpfc_read_lnk_stat(phba, mbox); mbox->ctx_buf = (void *)((unsigned long) - ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | - cmdiocb->iocb.ulpContext)); /* rx_id */ + (ox_id << 16 | ctx)); mbox->ctx_ndlp = lpfc_nlp_get(ndlp); if (!mbox->ctx_ndlp) goto node_err; @@ -8320,13 +8621,15 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp) { int rc = 0; + IOCB_t *icmd; + union lpfc_wqe128 *wqe; struct lpfc_hba *phba = vport->phba; struct ls_rjt stat; struct RTV_RSP *rtv_rsp; uint8_t *pcmd; struct lpfc_iocbq *elsiocb; uint32_t cmdsize; - + u32 ulp_context; if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) @@ -8345,9 +8648,19 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); /* Skip past command */ + ulp_context = get_job_ulpcontext(phba, elsiocb); /* use the command's xri in the response */ - elsiocb->iocb.ulpContext = cmdiocb->iocb.ulpContext; /* Xri / rx_id */ - elsiocb->iocb.unsli3.rcvsli3.ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id; + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, cmdiocb)); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, cmdiocb)); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = get_job_ulpcontext(phba, cmdiocb); + icmd->unsli3.rcvsli3.ox_id = get_job_rcvoxid(phba, cmdiocb); + } rtv_rsp = (struct RTV_RSP *)pcmd; @@ -8363,11 +8676,11 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, "2875 Xmit ELS RTV ACC response tag x%x xri x%x, " "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x, " "Data: x%x x%x x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi, rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8444,7 +8757,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, "Issue RRQ: did:x%x", did, rrq->xritag, rrq->rxid); elsiocb->context_un.rrq = rrq; - elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rrq; lpfc_nlp_get(ndlp); elsiocb->context1 = ndlp; @@ -8512,10 +8825,12 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, { int rc = 0; struct lpfc_hba *phba = vport->phba; - IOCB_t *icmd, *oldcmd; + IOCB_t *icmd; + union lpfc_wqe128 *wqe; RPL_RSP rpl_rsp; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; + u32 ulp_context; elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, ndlp->nlp_DID, ELS_CMD_ACC); @@ -8523,10 +8838,19 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ - icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; + ulp_context = get_job_ulpcontext(phba, elsiocb); + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + /* Xri / rx_id */ + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + get_job_ulpcontext(phba, oldiocb)); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + get_job_rcvoxid(phba, oldiocb)); + } else { + icmd = &elsiocb->iocb; + icmd->ulpContext = get_job_ulpcontext(phba, oldiocb); + icmd->unsli3.rcvsli3.ox_id = get_job_rcvoxid(phba, oldiocb); + } pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; @@ -8547,10 +8871,10 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, "0120 Xmit ELS RPL ACC response tag x%x " "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " "rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, + elsiocb->iotag, ulp_context, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8656,12 +8980,10 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, { struct lpfc_dmabuf *pcmd; uint32_t *lp; - IOCB_t *icmd; FARP *fp; uint32_t cnt, did; - icmd = &cmdiocb->iocb; - did = icmd->un.elsreq64.remoteID; + did = get_job_els_rsp64_did(vport->phba, cmdiocb); pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; lp = (uint32_t *) pcmd->virt; @@ -8729,11 +9051,9 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, { struct lpfc_dmabuf *pcmd; uint32_t *lp; - IOCB_t *icmd; uint32_t did; - icmd = &cmdiocb->iocb; - did = icmd->un.elsreq64.remoteID; + did = get_job_els_rsp64_did(vport->phba, cmdiocb); pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; lp = (uint32_t *) pcmd->virt; @@ -8972,6 +9292,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) uint32_t timeout; uint32_t remote_ID = 0xffffffff; LIST_HEAD(abort_list); + u32 ulp_command = 0, ulp_context = 0, did = 0, iotag = 0; timeout = (uint32_t)(phba->fc_ratov << 1); @@ -8988,11 +9309,21 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) spin_lock(&pring->ring_lock); list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { - cmd = &piocb->iocb; + ulp_command = get_job_cmnd(phba, piocb); + ulp_context = get_job_ulpcontext(phba, piocb); + did = get_job_els_rsp64_did(phba, piocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + iotag = get_wqe_reqtag(piocb); + } else { + cmd = &piocb->iocb; + iotag = cmd->ulpIoTag; + } - if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || - piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || - piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) + if ((piocb->cmd_flag & LPFC_IO_LIBDFC) != 0 || + ulp_command == CMD_ABORT_XRI_CX || + ulp_command == CMD_ABORT_XRI_CN || + ulp_command == CMD_CLOSE_XRI_CN) continue; if (piocb->vport != vport) @@ -9016,11 +9347,11 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) } remote_ID = 0xffffffff; - if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR) - remote_ID = cmd->un.elsreq64.remoteID; - else { + if (ulp_command != CMD_GEN_REQUEST64_CR) { + remote_ID = did; + } else { struct lpfc_nodelist *ndlp; - ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext); + ndlp = __lpfc_findnode_rpi(vport, ulp_context); if (ndlp) remote_ID = ndlp->nlp_DID; } @@ -9031,11 +9362,11 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) spin_unlock_irq(&phba->hbalock); list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { - cmd = &piocb->iocb; lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0127 ELS timeout Data: x%x x%x x%x " "x%x\n", els_command, - remote_ID, cmd->ulpCommand, cmd->ulpIoTag); + remote_ID, ulp_command, iotag); + spin_lock_irq(&phba->hbalock); list_del_init(&piocb->dlist); lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL); @@ -9078,7 +9409,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) struct lpfc_hba *phba = vport->phba; struct lpfc_sli_ring *pring; struct lpfc_iocbq *tmp_iocb, *piocb; - IOCB_t *cmd = NULL; + u32 ulp_command; unsigned long iflags = 0; lpfc_fabric_abort_vport(vport); @@ -9103,20 +9434,20 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) /* First we need to issue aborts to outstanding cmds on txcmpl */ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { - if (piocb->iocb_flag & LPFC_IO_LIBDFC) + if (piocb->cmd_flag & LPFC_IO_LIBDFC) continue; if (piocb->vport != vport) continue; - if (piocb->iocb_flag & LPFC_DRIVER_ABORTED) + if (piocb->cmd_flag & LPFC_DRIVER_ABORTED) continue; /* On the ELS ring we can have ELS_REQUESTs or * GEN_REQUESTs waiting for a response. */ - cmd = &piocb->iocb; - if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR) { + ulp_command = get_job_cmnd(phba, piocb); + if (ulp_command == CMD_ELS_REQUEST64_CR) { list_add_tail(&piocb->dlist, &abort_list); /* If the link is down when flushing ELS commands @@ -9127,9 +9458,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) * and avoid any retry logic. */ if (phba->link_state == LPFC_LINK_DOWN) - piocb->iocb_cmpl = lpfc_cmpl_els_link_down; + piocb->cmd_cmpl = lpfc_cmpl_els_link_down; } - if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) + if (ulp_command == CMD_GEN_REQUEST64_CR) list_add_tail(&piocb->dlist, &abort_list); } @@ -9160,17 +9491,17 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) * just queue them up for lpfc_sli_cancel_iocbs */ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { - cmd = &piocb->iocb; + ulp_command = get_job_cmnd(phba, piocb); - if (piocb->iocb_flag & LPFC_IO_LIBDFC) { + if (piocb->cmd_flag & LPFC_IO_LIBDFC) continue; - } /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ - if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || - cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || - cmd->ulpCommand == CMD_CLOSE_XRI_CN || - cmd->ulpCommand == CMD_ABORT_XRI_CN) + if (ulp_command == CMD_QUE_RING_BUF_CN || + ulp_command == CMD_QUE_RING_BUF64_CN || + ulp_command == CMD_CLOSE_XRI_CN || + ulp_command == CMD_ABORT_XRI_CN || + ulp_command == CMD_ABORT_XRI_CX) continue; if (piocb->vport != vport) @@ -9184,7 +9515,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) if (vport == phba->pport) { list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list, list) { - cmd = &piocb->iocb; list_del_init(&piocb->list); list_add_tail(&piocb->list, &abort_list); } @@ -9252,12 +9582,16 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, struct ls_rjt stat; struct lpfc_nodelist *ndlp; uint32_t *pcmd; + u32 ulp_status, ulp_word4; ndlp = cmdiocbp->context1; if (!ndlp) return; - if (rspiocbp->iocb.ulpStatus == IOSTAT_LS_RJT) { + ulp_status = get_job_ulpstatus(phba, rspiocbp); + ulp_word4 = get_job_word4(phba, rspiocbp); + + if (ulp_status == IOSTAT_LS_RJT) { lsrjt_event.header.event_type = FC_REG_ELS_EVENT; lsrjt_event.header.subcategory = LPFC_EVENT_LSRJT_RCV; memcpy(lsrjt_event.header.wwpn, &ndlp->nlp_portname, @@ -9267,7 +9601,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, pcmd = (uint32_t *) (((struct lpfc_dmabuf *) cmdiocbp->context2)->virt); lsrjt_event.command = (pcmd != NULL) ? *pcmd : 0; - stat.un.lsRjtError = be32_to_cpu(rspiocbp->iocb.un.ulpWord[4]); + stat.un.ls_rjt_error_be = cpu_to_be32(ulp_word4); lsrjt_event.reason_code = stat.un.b.lsRjtRsnCode; lsrjt_event.explanation = stat.un.b.lsRjtRsnCodeExp; fc_host_post_vendor_event(shost, @@ -9277,10 +9611,10 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, LPFC_NL_VENDOR_ID); return; } - if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) || - (rspiocbp->iocb.ulpStatus == IOSTAT_FABRIC_BSY)) { + if (ulp_status == IOSTAT_NPORT_BSY || + ulp_status == IOSTAT_FABRIC_BSY) { fabric_event.event_type = FC_REG_FABRIC_EVENT; - if (rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) + if (ulp_status == IOSTAT_NPORT_BSY) fabric_event.subcategory = LPFC_EVENT_PORT_BUSY; else fabric_event.subcategory = LPFC_EVENT_FABRIC_BUSY; @@ -9793,27 +10127,32 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { struct lpfc_nodelist *ndlp; struct ls_rjt stat; - uint32_t *payload, payload_len; - uint32_t cmd, did, newnode; + u32 *payload, payload_len; + u32 cmd = 0, did = 0, newnode, status = 0; uint8_t rjt_exp, rjt_err = 0, init_link = 0; - IOCB_t *icmd = &elsiocb->iocb; + struct lpfc_wcqe_complete *wcqe_cmpl = NULL; LPFC_MBOXQ_t *mbox; if (!vport || !(elsiocb->context2)) goto dropit; newnode = 0; + wcqe_cmpl = &elsiocb->wcqe_cmpl; payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; - payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; + if (phba->sli_rev == LPFC_SLI_REV4) + payload_len = wcqe_cmpl->total_data_placed; + else + payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; + status = get_job_ulpstatus(phba, elsiocb); cmd = *payload; if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) - lpfc_post_buffer(phba, pring, 1); + lpfc_sli3_post_buffer(phba, pring, 1); - did = icmd->un.rcvels.remoteID; - if (icmd->ulpStatus) { + did = get_job_els_rsp64_did(phba, elsiocb); + if (status) { lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV Unsol ELS: status:x%x/x%x did:x%x", - icmd->ulpStatus, icmd->un.ulpWord[4], did); + status, get_job_word4(phba, elsiocb), did); goto dropit; } @@ -9899,7 +10238,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * the vfi. This is done in lpfc_rcv_plogi but * that is called after the reg_vfi. */ - vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo; + vport->fc_myDID = + bf_get(els_rsp64_sid, + &elsiocb->wqe.xmit_els_rsp); lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3312 Remote port assigned DID x%x " "%x\n", vport->fc_myDID, @@ -9952,6 +10293,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } lpfc_els_rcv_flogi(vport, elsiocb, ndlp); + /* retain node if our response is deferred */ + if (phba->defer_flogi_acc_flag) + break; if (newnode) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); @@ -10241,8 +10585,9 @@ dropit: if (vport && !(vport->load_flag & FC_UNLOADING)) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0111 Dropping received ELS cmd " - "Data: x%x x%x x%x\n", - icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout); + "Data: x%x x%x x%x x%x\n", + cmd, status, get_job_word4(phba, elsiocb), did); + phba->fc_stat.elsRcvDrop++; } @@ -10262,54 +10607,76 @@ void lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *elsiocb) { - struct lpfc_vport *vport = phba->pport; - IOCB_t *icmd = &elsiocb->iocb; - dma_addr_t paddr; + struct lpfc_vport *vport = elsiocb->vport; + u32 ulp_command, status, parameter, bde_count = 0; + IOCB_t *icmd; + struct lpfc_wcqe_complete *wcqe_cmpl = NULL; struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2; struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3; + dma_addr_t paddr; elsiocb->context1 = NULL; elsiocb->context2 = NULL; elsiocb->context3 = NULL; - if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) { + wcqe_cmpl = &elsiocb->wcqe_cmpl; + ulp_command = get_job_cmnd(phba, elsiocb); + status = get_job_ulpstatus(phba, elsiocb); + parameter = get_job_word4(phba, elsiocb); + if (phba->sli_rev == LPFC_SLI_REV4) + bde_count = wcqe_cmpl->word3; + else + bde_count = elsiocb->iocb.ulpBdeCount; + + if (status == IOSTAT_NEED_BUFFER) { lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); - } else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT && - (icmd->un.ulpWord[4] & IOERR_PARAM_MASK) == + } else if (status == IOSTAT_LOCAL_REJECT && + (parameter & IOERR_PARAM_MASK) == IOERR_RCV_BUFFER_WAITING) { phba->fc_stat.NoRcvBuf++; /* Not enough posted buffers; Try posting more buffers */ if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_post_buffer(phba, pring, 0); + lpfc_sli3_post_buffer(phba, pring, 0); return; } - if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && - (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX || - icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { - if (icmd->unsli3.rcvsli3.vpi == 0xffff) - vport = phba->pport; - else - vport = lpfc_find_vport_by_vpid(phba, + if (phba->sli_rev == LPFC_SLI_REV3) { + icmd = &elsiocb->iocb; + if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && + (ulp_command == CMD_IOCB_RCV_ELS64_CX || + ulp_command == CMD_IOCB_RCV_SEQ64_CX)) { + if (icmd->unsli3.rcvsli3.vpi == 0xffff) + vport = phba->pport; + else + vport = lpfc_find_vport_by_vpid(phba, icmd->unsli3.rcvsli3.vpi); + } } /* If there are no BDEs associated * with this IOCB, there is nothing to do. */ - if (icmd->ulpBdeCount == 0) + if (bde_count == 0) return; - /* type of ELS cmd is first 32bit word - * in packet - */ + /* Account for SLI2 or SLI3 and later unsolicited buffering */ if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { elsiocb->context2 = bdeBuf1; + if (bde_count == 2) + elsiocb->context3 = bdeBuf2; } else { + icmd = &elsiocb->iocb; paddr = getPaddr(icmd->un.cont64[0].addrHigh, icmd->un.cont64[0].addrLow); elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring, paddr); + if (bde_count == 2) { + paddr = getPaddr(icmd->un.cont64[1].addrHigh, + icmd->un.cont64[1].addrLow); + elsiocb->context3 = lpfc_sli_ringpostbuf_get(phba, + pring, + paddr); + } } lpfc_els_unsol_buffer(phba, pring, vport, elsiocb); @@ -10322,16 +10689,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, elsiocb->context2 = NULL; } - /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */ - if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) && - icmd->ulpBdeCount == 2) { - elsiocb->context2 = bdeBuf2; - lpfc_els_unsol_buffer(phba, pring, vport, elsiocb); - /* free mp if we are done with it */ - if (elsiocb->context2) { - lpfc_in_buf_free(phba, elsiocb->context2); - elsiocb->context2 = NULL; - } + if (elsiocb->context3) { + lpfc_in_buf_free(phba, elsiocb->context3); + elsiocb->context3 = NULL; } } @@ -10672,9 +11032,11 @@ lpfc_fabric_login_reqd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); - if ((rspiocb->iocb.ulpStatus != IOSTAT_FABRIC_RJT) || - (rspiocb->iocb.un.ulpWord[4] != RJT_LOGIN_REQUIRED)) + if (ulp_status != IOSTAT_FABRIC_RJT || + ulp_word4 != RJT_LOGIN_REQUIRED) return 0; else return 1; @@ -10709,15 +11071,18 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_nodelist *np; struct lpfc_nodelist *next_np; - IOCB_t *irsp = &rspiocb->iocb; struct lpfc_iocbq *piocb; struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp; struct serv_parm *sp; uint8_t fabric_param_changed; + u32 ulp_status, ulp_word4; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0123 FDISC completes. x%x/x%x prevDID: x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], + ulp_status, ulp_word4, vport->fc_prevDID); /* Since all FDISCs are being single threaded, we * must reset the discovery timer for ALL vports @@ -10729,9 +11094,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "FDISC cmpl: status:x%x/x%x prevdid:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); + ulp_status, ulp_word4, vport->fc_prevDID); - if (irsp->ulpStatus) { + if (ulp_status) { if (lpfc_fabric_login_reqd(phba, cmdiocb, rspiocb)) { lpfc_retry_pport_discovery(phba); @@ -10744,7 +11109,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* FDISC failed */ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0126 FDISC failed. (x%x/x%x)\n", - irsp->ulpStatus, irsp->un.ulpWord[4]); + ulp_status, ulp_word4); goto fdisc_failed; } @@ -10758,7 +11123,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport->fc_flag |= FC_PUBLIC_LOOP; spin_unlock_irq(shost->host_lock); - vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; + vport->fc_myDID = ulp_word4 & Mask_DID; lpfc_vport_set_state(vport, FC_VPORT_ACTIVE); prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); if (!prsp) @@ -10858,6 +11223,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_hba *phba = vport->phba; IOCB_t *icmd; + union lpfc_wqe128 *wqe = NULL; struct lpfc_iocbq *elsiocb; struct serv_parm *sp; uint8_t *pcmd; @@ -10877,15 +11243,14 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return 1; } - icmd = &elsiocb->iocb; - icmd->un.elsreq64.myID = 0; - icmd->un.elsreq64.fl = 1; - - /* - * SLI3 ports require a different context type value than SLI4. - * Catch SLI3 ports here and override the prep. - */ - if (phba->sli_rev == LPFC_SLI_REV3) { + if (phba->sli_rev == LPFC_SLI_REV4) { + wqe = &elsiocb->wqe; + bf_set(els_req64_sid, &wqe->els_req, 0); + bf_set(els_req64_sp, &wqe->els_req, 1); + } else { + icmd = &elsiocb->iocb; + icmd->un.elsreq64.myID = 0; + icmd->un.elsreq64.fl = 1; icmd->ulpCt_h = 1; icmd->ulpCt_l = 0; } @@ -10916,21 +11281,18 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_set_disctmo(vport); phba->fc_stat.elsXmitFDISC++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc; + elsiocb->cmd_cmpl = lpfc_cmpl_els_fdisc; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue FDISC: did:x%x", did, 0, 0); elsiocb->context1 = lpfc_nlp_get(ndlp); - if (!elsiocb->context1) { - lpfc_els_free_iocb(phba, elsiocb); + if (!elsiocb->context1) goto err_out; - } rc = lpfc_issue_fabric_iocb(phba, elsiocb); if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); lpfc_nlp_put(ndlp); goto err_out; } @@ -10939,6 +11301,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return 0; err_out: + lpfc_els_free_iocb(phba, elsiocb); lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0256 Issue FDISC: Cannot send IOCB\n"); @@ -10967,23 +11330,36 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, IOCB_t *irsp; struct lpfc_nodelist *ndlp; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); + u32 ulp_status, ulp_word4, did, tmo; ndlp = (struct lpfc_nodelist *)cmdiocb->context1; - irsp = &rspiocb->iocb; + + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + did = get_job_els_rsp64_did(phba, cmdiocb); + tmo = get_wqe_tmo(cmdiocb); + } else { + irsp = &rspiocb->iocb; + did = get_job_els_rsp64_did(phba, rspiocb); + tmo = irsp->ulpTimeout; + } + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "LOGO npiv cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID); + ulp_status, ulp_word4, did); /* NPIV LOGO completes to NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "2928 NPIV LOGO completes to NPort x%x " "Data: x%x x%x x%x x%x x%x x%x x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, vport->num_disc_nodes, + ndlp->nlp_DID, ulp_status, ulp_word4, + tmo, vport->num_disc_nodes, kref_read(&ndlp->kref), ndlp->nlp_flag, ndlp->fc4_xpt_flags); - if (irsp->ulpStatus == IOSTAT_SUCCESS) { + if (ulp_status == IOSTAT_SUCCESS) { spin_lock_irq(shost->host_lock); vport->fc_flag &= ~FC_NDISC_ACTIVE; vport->fc_flag &= ~FC_FABRIC; @@ -11049,7 +11425,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) "Issue LOGO npiv did:x%x flg:x%x", ndlp->nlp_DID, ndlp->nlp_flag, 0); - elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; + elsiocb->cmd_cmpl = lpfc_cmpl_els_npiv_logo; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; spin_unlock_irq(&ndlp->lock); @@ -11119,7 +11495,6 @@ lpfc_resume_fabric_iocbs(struct lpfc_hba *phba) struct lpfc_iocbq *iocb; unsigned long iflags; int ret; - IOCB_t *cmd; repeat: iocb = NULL; @@ -11134,24 +11509,23 @@ repeat: } spin_unlock_irqrestore(&phba->hbalock, iflags); if (iocb) { - iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; - iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; - iocb->iocb_flag |= LPFC_IO_FABRIC; + iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; + iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; + iocb->cmd_flag |= LPFC_IO_FABRIC; lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, - "Fabric sched1: ste:x%x", - iocb->vport->port_state, 0, 0); + "Fabric sched1: ste:x%x", + iocb->vport->port_state, 0, 0); ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0); if (ret == IOCB_ERROR) { - iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; - iocb->fabric_iocb_cmpl = NULL; - iocb->iocb_flag &= ~LPFC_IO_FABRIC; - cmd = &iocb->iocb; - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - iocb->iocb_cmpl(phba, iocb, iocb); + iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; + iocb->fabric_cmd_cmpl = NULL; + iocb->cmd_flag &= ~LPFC_IO_FABRIC; + set_job_ulpstatus(iocb, IOSTAT_LOCAL_REJECT); + iocb->wcqe_cmpl.parameter = IOERR_SLI_ABORTED; + iocb->cmd_cmpl(phba, iocb, iocb); atomic_dec(&phba->fabric_iocb_count); goto repeat; @@ -11207,26 +11581,27 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) * @rspiocb: pointer to lpfc response iocb data structure. * * This routine is the callback function that is put to the fabric iocb's - * callback function pointer (iocb->iocb_cmpl). The original iocb's callback - * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback + * callback function pointer (iocb->cmd_cmpl). The original iocb's callback + * function pointer has been stored in iocb->fabric_cmd_cmpl. This callback * function first restores and invokes the original iocb's callback function * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next * fabric bound iocb from the driver internal fabric iocb list onto the wire. **/ static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) + struct lpfc_iocbq *rspiocb) { struct ls_rjt stat; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); - BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); + WARN_ON((cmdiocb->cmd_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); - switch (rspiocb->iocb.ulpStatus) { + switch (ulp_status) { case IOSTAT_NPORT_RJT: case IOSTAT_FABRIC_RJT: - if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) { + if (ulp_word4 & RJT_UNAVAIL_TEMP) lpfc_block_fabric_iocbs(phba); - } break; case IOSTAT_NPORT_BSY: @@ -11235,8 +11610,8 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, break; case IOSTAT_LS_RJT: - stat.un.lsRjtError = - be32_to_cpu(rspiocb->iocb.un.ulpWord[4]); + stat.un.ls_rjt_error_be = + cpu_to_be32(ulp_word4); if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) || (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY)) lpfc_block_fabric_iocbs(phba); @@ -11245,10 +11620,10 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, BUG_ON(atomic_read(&phba->fabric_iocb_count) == 0); - cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl; - cmdiocb->fabric_iocb_cmpl = NULL; - cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; - cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb); + cmdiocb->cmd_cmpl = cmdiocb->fabric_cmd_cmpl; + cmdiocb->fabric_cmd_cmpl = NULL; + cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; + cmdiocb->cmd_cmpl(phba, cmdiocb, rspiocb); atomic_dec(&phba->fabric_iocb_count); if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) { @@ -11299,20 +11674,20 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) atomic_inc(&phba->fabric_iocb_count); spin_unlock_irqrestore(&phba->hbalock, iflags); if (ready) { - iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; - iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; - iocb->iocb_flag |= LPFC_IO_FABRIC; + iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; + iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; + iocb->cmd_flag |= LPFC_IO_FABRIC; lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, - "Fabric sched2: ste:x%x", - iocb->vport->port_state, 0, 0); + "Fabric sched2: ste:x%x", + iocb->vport->port_state, 0, 0); ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0); if (ret == IOCB_ERROR) { - iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; - iocb->fabric_iocb_cmpl = NULL; - iocb->iocb_flag &= ~LPFC_IO_FABRIC; + iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; + iocb->fabric_cmd_cmpl = NULL; + iocb->cmd_flag &= ~LPFC_IO_FABRIC; atomic_dec(&phba->fabric_iocb_count); } } else { @@ -11615,7 +11990,8 @@ lpfc_cmpl_els_qfpa(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vmid_priority_range *vmid_range = NULL; u32 *data; struct lpfc_dmabuf *dmabuf = cmdiocb->context2; - IOCB_t *irsp = &rspiocb->iocb; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); u8 *pcmd, max_desc; u32 len, i; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)cmdiocb->context1; @@ -11632,10 +12008,10 @@ lpfc_cmpl_els_qfpa(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, data[0], data[1]); goto out; } - if (irsp->ulpStatus) { + if (ulp_status) { lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, "6529 QFPA failed with status x%x x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4]); + ulp_status, ulp_word4); goto out; } @@ -11719,7 +12095,7 @@ int lpfc_issue_els_qfpa(struct lpfc_vport *vport) *((u32 *)(pcmd)) = ELS_CMD_QFPA; pcmd += 4; - elsiocb->iocb_cmpl = lpfc_cmpl_els_qfpa; + elsiocb->cmd_cmpl = lpfc_cmpl_els_qfpa; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -11802,7 +12178,7 @@ lpfc_vmid_uvem(struct lpfc_vport *vport, } inst_desc->word6 = cpu_to_be32(inst_desc->word6); - elsiocb->iocb_cmpl = lpfc_cmpl_els_uvem; + elsiocb->cmd_cmpl = lpfc_cmpl_els_uvem; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -11834,7 +12210,8 @@ lpfc_cmpl_els_uvem(struct lpfc_hba *phba, struct lpfc_iocbq *icmdiocb, struct lpfc_nodelist *ndlp = icmdiocb->context1; u8 *pcmd; u32 *data; - IOCB_t *irsp = &rspiocb->iocb; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); struct lpfc_dmabuf *dmabuf = icmdiocb->context2; struct lpfc_vmid *vmid; @@ -11852,10 +12229,10 @@ lpfc_cmpl_els_uvem(struct lpfc_hba *phba, struct lpfc_iocbq *icmdiocb, "4532 UVEM LS_RJT %x %x\n", data[0], data[1]); goto out; } - if (irsp->ulpStatus) { + if (ulp_status) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, "4533 UVEM error status %x: %x\n", - irsp->ulpStatus, irsp->un.ulpWord[4]); + ulp_status, ulp_word4); goto out; } spin_lock(&phba->hbalock); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 816fc406135b..0144da30e3db 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -5059,7 +5059,8 @@ lpfc_can_disctmo(struct lpfc_vport *vport) vport->port_state, vport->fc_ns_retry, vport->fc_flag); /* Turn off discovery timer if its running */ - if (vport->fc_flag & FC_DISC_TMO) { + if (vport->fc_flag & FC_DISC_TMO || + timer_pending(&vport->fc_disctmo)) { spin_lock_irqsave(shost->host_lock, iflags); vport->fc_flag &= ~FC_DISC_TMO; spin_unlock_irqrestore(shost->host_lock, iflags); @@ -5088,20 +5089,26 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp) { - IOCB_t *icmd = &iocb->iocb; - struct lpfc_vport *vport = ndlp->vport; + struct lpfc_vport *vport = ndlp->vport; + u8 ulp_command; + u16 ulp_context; + u32 remote_id; if (iocb->vport != vport) return 0; + ulp_command = get_job_cmnd(phba, iocb); + ulp_context = get_job_ulpcontext(phba, iocb); + remote_id = get_job_els_rsp64_did(phba, iocb); + if (pring->ringno == LPFC_ELS_RING) { - switch (icmd->ulpCommand) { + switch (ulp_command) { case CMD_GEN_REQUEST64_CR: if (iocb->context_un.ndlp == ndlp) return 1; fallthrough; case CMD_ELS_REQUEST64_CR: - if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID) + if (remote_id == ndlp->nlp_DID) return 1; fallthrough; case CMD_XMIT_ELS_RSP64_CX: @@ -5114,9 +5121,8 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, (ndlp->nlp_flag & NLP_DELAY_TMO)) { return 0; } - if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) { + if (ulp_context == ndlp->nlp_rpi) return 1; - } } return 0; } @@ -6027,9 +6033,9 @@ static void lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { LIST_HEAD(completions); - IOCB_t *icmd; struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_sli_ring *pring; + u32 ulp_command; pring = lpfc_phba_elsring(phba); if (unlikely(!pring)) @@ -6040,12 +6046,13 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) */ spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { - if (iocb->context1 != ndlp) { + if (iocb->context1 != ndlp) continue; - } - icmd = &iocb->iocb; - if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || - (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { + + ulp_command = get_job_cmnd(phba, iocb); + + if (ulp_command == CMD_ELS_REQUEST64_CR || + ulp_command == CMD_XMIT_ELS_RSP64_CX) { list_move_tail(&iocb->list, &completions); } @@ -6053,12 +6060,13 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) /* Next check the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { - if (iocb->context1 != ndlp) { + if (iocb->context1 != ndlp) continue; - } - icmd = &iocb->iocb; - if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR || - icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) { + + ulp_command = get_job_cmnd(phba, iocb); + + if (ulp_command == CMD_ELS_REQUEST64_CR || + ulp_command == CMD_XMIT_ELS_RSP64_CX) { lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); } } diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 4461c3d6fc4f..d6050f3c9efe 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -664,6 +664,7 @@ struct fc_vft_header { struct ls_rjt { /* Structure is in Big Endian format */ union { + __be32 ls_rjt_error_be; uint32_t lsRjtError; struct { uint8_t lsRjtRsvd0; /* FC Word 0, bit 24:31 */ @@ -4376,16 +4377,15 @@ lpfc_is_LC_HBA(unsigned short device) } /* - * Determine if an IOCB failed because of a link event or firmware reset. + * Determine if failed because of a link event or firmware reset. */ - static inline int -lpfc_error_lost_link(IOCB_t *iocbp) +lpfc_error_lost_link(u32 ulp_status, u32 ulp_word4) { - return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT && - (iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED || - iocbp->un.ulpWord[4] == IOERR_LINK_DOWN || - iocbp->un.ulpWord[4] == IOERR_SLI_DOWN)); + return (ulp_status == IOSTAT_LOCAL_REJECT && + (ulp_word4 == IOERR_SLI_ABORTED || + ulp_word4 == IOERR_LINK_DOWN || + ulp_word4 == IOERR_SLI_DOWN)); } #define MENLO_TRANSPORT_TYPE 0xfe diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 6ec42991d2ab..02e230ed6280 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -60,6 +60,14 @@ ((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \ ((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT)))) +#define get_wqe_reqtag(x) (((x)->wqe.words[9] >> 0) & 0xFFFF) +#define get_wqe_tmo(x) (((x)->wqe.words[7] >> 24) & 0x00FF) + +#define get_job_ulpword(x, y) ((x)->iocb.un.ulpWord[y]) + +#define set_job_ulpstatus(x, y) bf_set(lpfc_wcqe_c_status, &(x)->wcqe_cmpl, y) +#define set_job_ulpword4(x, y) ((&(x)->wcqe_cmpl)->parameter = y) + struct dma_address { uint32_t addr_lo; uint32_t addr_hi; @@ -230,6 +238,34 @@ struct lpfc_sli_intf { /* PORT_CAPABILITIES constants. */ #define LPFC_MAX_SUPPORTED_PAGES 8 +enum ulp_bde64_word3 { + ULP_BDE64_SIZE_MASK = 0xffffff, + + ULP_BDE64_TYPE_SHIFT = 24, + ULP_BDE64_TYPE_MASK = (0xff << ULP_BDE64_TYPE_SHIFT), + + /* BDE (Host_resident) */ + ULP_BDE64_TYPE_BDE_64 = (0x00 << ULP_BDE64_TYPE_SHIFT), + /* Immediate Data BDE */ + ULP_BDE64_TYPE_BDE_IMMED = (0x01 << ULP_BDE64_TYPE_SHIFT), + /* BDE (Port-resident) */ + ULP_BDE64_TYPE_BDE_64P = (0x02 << ULP_BDE64_TYPE_SHIFT), + /* Input BDE (Host-resident) */ + ULP_BDE64_TYPE_BDE_64I = (0x08 << ULP_BDE64_TYPE_SHIFT), + /* Input BDE (Port-resident) */ + ULP_BDE64_TYPE_BDE_64IP = (0x0A << ULP_BDE64_TYPE_SHIFT), + /* BLP (Host-resident) */ + ULP_BDE64_TYPE_BLP_64 = (0x40 << ULP_BDE64_TYPE_SHIFT), + /* BLP (Port-resident) */ + ULP_BDE64_TYPE_BLP_64P = (0x42 << ULP_BDE64_TYPE_SHIFT), +}; + +struct ulp_bde64_le { + __le32 type_size; /* type 31:24, size 23:0 */ + __le32 addr_low; + __le32 addr_high; +}; + struct ulp_bde64 { union ULP_BDE_TUS { uint32_t w; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 558f7d2559c4..eed6464bd880 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -340,7 +340,6 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /** * lpfc_update_vport_wwn - Updates the fc_nodename, fc_portname, - * cfg_soft_wwnn, cfg_soft_wwpn * @vport: pointer to lpfc vport data structure. * * @@ -353,19 +352,11 @@ lpfc_update_vport_wwn(struct lpfc_vport *vport) uint8_t vvvl = vport->fc_sparam.cmn.valid_vendor_ver_level; u32 *fawwpn_key = (u32 *)&vport->fc_sparam.un.vendorVersion[0]; - /* If the soft name exists then update it using the service params */ - if (vport->phba->cfg_soft_wwnn) - u64_to_wwn(vport->phba->cfg_soft_wwnn, - vport->fc_sparam.nodeName.u.wwn); - if (vport->phba->cfg_soft_wwpn) - u64_to_wwn(vport->phba->cfg_soft_wwpn, - vport->fc_sparam.portName.u.wwn); - /* * If the name is empty or there exists a soft name * then copy the service params name, otherwise use the fc name */ - if (vport->fc_nodename.u.wwn[0] == 0 || vport->phba->cfg_soft_wwnn) + if (vport->fc_nodename.u.wwn[0] == 0) memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); else @@ -382,7 +373,6 @@ lpfc_update_vport_wwn(struct lpfc_vport *vport) vport->vport_flag |= FAWWPN_PARAM_CHG; if (vport->fc_portname.u.wwn[0] == 0 || - vport->phba->cfg_soft_wwpn || (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR) || vport->vport_flag & FAWWPN_SET) { memcpy(&vport->fc_portname, &vport->fc_sparam.portName, @@ -1027,7 +1017,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba) spin_lock_irq(&pring->ring_lock); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; list_splice_init(&pring->txcmplq, &completions); pring->txcmplq_cnt = 0; spin_unlock_irq(&pring->ring_lock); @@ -2688,7 +2678,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) } /** - * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring + * lpfc_sli3_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring * @phba: pointer to lpfc hba data structure. * @pring: pointer to a IOCB ring. * @cnt: the number of IOCBs to be posted to the IOCB ring. @@ -2700,7 +2690,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) * The number of IOCBs NOT able to be posted to the IOCB ring. **/ int -lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) +lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) { IOCB_t *icmd; struct lpfc_iocbq *iocb; @@ -2806,7 +2796,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; /* Ring 0, ELS / CT buffers */ - lpfc_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); + lpfc_sli3_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); /* Ring 2 - FCP no buffers needed */ return 0; @@ -4260,8 +4250,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) qp = &phba->sli4_hba.hdwq[idx]; lpfc_cmd->hdwq_no = idx; lpfc_cmd->hdwq = qp; - lpfc_cmd->cur_iocbq.wqe_cmpl = NULL; - lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; + lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; spin_lock(&qp->io_buf_list_put_lock); list_add_tail(&lpfc_cmd->list, &qp->lpfc_io_buf_list_put); @@ -8546,7 +8535,6 @@ static void lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba) { if (phba->wq) { - flush_workqueue(phba->wq); destroy_workqueue(phba->wq); phba->wq = NULL; } diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 6c754ee96bee..e1404ab5000d 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -429,7 +429,7 @@ lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); /* - * SLI-3, Message Signaled Interrupt Fearure. + * SLI-3, Message Signaled Interrupt Feature. */ /* Multi-message attention configuration */ diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index fdf5e777bf11..c4e1a07066a2 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -171,9 +171,8 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *pcmd, *prsp; uint32_t *lp; void *ptr = NULL; - IOCB_t *irsp; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); - irsp = &rspiocb->iocb; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; /* For lpfc_els_abort, context2 could be zero'ed to delay @@ -187,10 +186,16 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ptr = (void *)((uint8_t *)lp + sizeof(uint32_t)); } } else { - /* Force ulpStatus error since we are returning NULL ptr */ - if (!(irsp->ulpStatus)) { - irsp->ulpStatus = IOSTAT_LOCAL_REJECT; - irsp->un.ulpWord[4] = IOERR_SLI_ABORTED; + /* Force ulp_status error since we are returning NULL ptr */ + if (!(ulp_status)) { + if (phba->sli_rev == LPFC_SLI_REV4) { + bf_set(lpfc_wcqe_c_status, &rspiocb->wcqe_cmpl, + IOSTAT_LOCAL_REJECT); + rspiocb->wcqe_cmpl.parameter = IOERR_SLI_ABORTED; + } else { + rspiocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; + rspiocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED; + } } ptr = NULL; } @@ -325,6 +330,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct lpfc_dmabuf *mp; uint64_t nlp_portwwn = 0; uint32_t *lp; + union lpfc_wqe128 *wqe; IOCB_t *icmd; struct serv_parm *sp; uint32_t ed_tov; @@ -334,6 +340,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct ls_rjt stat; uint32_t vid, flag; int rc; + u32 remote_did; memset(&stat, 0, sizeof (struct ls_rjt)); pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; @@ -367,7 +374,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, NULL); return 0; } - icmd = &cmdiocb->iocb; + + if (phba->sli_rev == LPFC_SLI_REV4) + wqe = &cmdiocb->wqe; + else + icmd = &cmdiocb->iocb; /* PLOGI chkparm OK */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -457,7 +468,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 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; + if (phba->sli_rev == LPFC_SLI_REV4) { + vport->fc_myDID = bf_get(els_rsp64_sid, + &cmdiocb->wqe.xmit_els_rsp); + } else { + vport->fc_myDID = icmd->un.rcvels.parmRo; + } /* If there is an outstanding FLOGI, abort it now. * The remote NPort is not going to ACC our FLOGI @@ -538,7 +554,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Issue REG_LOGIN first, before ACCing the PLOGI, thus we will * always be deferring the ACC. */ - rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID, + if (phba->sli_rev == LPFC_SLI_REV4) + remote_did = bf_get(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest); + else + remote_did = icmd->un.rcvels.remoteID; + rc = lpfc_reg_rpi(phba, vport->vpi, remote_did, (uint8_t *)sp, login_mbox, ndlp->nlp_rpi); if (rc) goto out; @@ -680,13 +700,13 @@ static int lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *cmdiocb) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; struct lpfc_dmabuf *pcmd; struct serv_parm *sp; struct lpfc_name *pnn, *ppn; struct ls_rjt stat; ADISC *ap; - IOCB_t *icmd; uint32_t *lp; uint32_t cmd; @@ -704,8 +724,8 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ppn = (struct lpfc_name *) & sp->portName; } - icmd = &cmdiocb->iocb; - if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) { + if (get_job_ulpstatus(phba, cmdiocb) == 0 && + lpfc_check_adisc(vport, ndlp, pnn, ppn)) { /* * As soon as we send ACC, the remote NPort can @@ -716,7 +736,6 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, elsiocb = kmalloc(sizeof(struct lpfc_iocbq), GFP_KERNEL); if (elsiocb) { - /* Save info from cmd IOCB used in rsp */ memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb, sizeof(struct lpfc_iocbq)); @@ -1312,23 +1331,24 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_dmabuf *pcmd, *prsp, *mp; uint32_t *lp; uint32_t vid, flag; - IOCB_t *irsp; struct serv_parm *sp; uint32_t ed_tov; LPFC_MBOXQ_t *mbox; int rc; + u32 ulp_status; + u32 did; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; + ulp_status = get_job_ulpstatus(phba, rspiocb); + if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { /* Recovery from PLOGI collision logic */ return ndlp->nlp_state; } - irsp = &rspiocb->iocb; - - if (irsp->ulpStatus) + if (ulp_status) goto out; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; @@ -1440,7 +1460,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, goto out; } - if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID, + did = get_job_els_rsp64_did(phba, cmdiocb); + + if (lpfc_reg_rpi(phba, vport->vpi, did, (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) { switch (ndlp->nlp_DID) { case NameServer_DID: @@ -1670,17 +1692,18 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb, *rspiocb; - IOCB_t *irsp; ADISC *ap; int rc; + u32 ulp_status; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; + ulp_status = get_job_ulpstatus(phba, rspiocb); + ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); - irsp = &rspiocb->iocb; - if ((irsp->ulpStatus) || + if ((ulp_status) || (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { /* 1 sec timeout */ mod_timer(&ndlp->nlp_delayfunc, @@ -2123,14 +2146,16 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_iocbq *cmdiocb, *rspiocb; struct lpfc_hba *phba = vport->phba; - IOCB_t *irsp; PRLI *npr; struct lpfc_nvme_prli *nvpr; void *temp_ptr; + u32 ulp_status; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; + ulp_status = get_job_ulpstatus(phba, rspiocb); + /* A solicited PRLI is either FCP or NVME. The PRLI cmd/rsp * format is different so NULL the two PRLI types so that the * driver correctly gets the correct context. @@ -2138,13 +2163,12 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, npr = NULL; nvpr = NULL; temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); - if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ) + if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ) npr = (PRLI *) temp_ptr; - else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ) + else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ) nvpr = (struct lpfc_nvme_prli *) temp_ptr; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus) { + if (ulp_status) { if ((vport->port_type == LPFC_NPIV_PORT) && vport->cfg_restrict_login) { goto out; @@ -2743,16 +2767,18 @@ static uint32_t lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb, *rspiocb; - IOCB_t *irsp; + u32 ulp_status; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus) { + ulp_status = get_job_ulpstatus(phba, rspiocb); + + if (ulp_status) return NLP_STE_FREED_NODE; - } + return ndlp->nlp_state; } @@ -2760,14 +2786,16 @@ static uint32_t lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb, *rspiocb; - IOCB_t *irsp; + u32 ulp_status; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { + ulp_status = get_job_ulpstatus(phba, rspiocb); + + if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { lpfc_drop_node(vport, ndlp); return NLP_STE_FREED_NODE; } @@ -2794,14 +2822,16 @@ static uint32_t lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb, *rspiocb; - IOCB_t *irsp; + u32 ulp_status; cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { + ulp_status = get_job_ulpstatus(phba, rspiocb); + + if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { lpfc_drop_node(vport, ndlp); return NLP_STE_FREED_NODE; } diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 9601edd838e1..1213a299f9aa 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -352,11 +352,12 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, static void lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_vport *vport = cmdwqe->vport; struct lpfc_nvme_lport *lport; uint32_t status; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; @@ -380,7 +381,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, struct nvmefc_ls_req *pnvme_lsreq, void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_wcqe_complete *), + struct lpfc_iocbq *), struct lpfc_nodelist *ndlp, uint32_t num_entry, uint32_t tmo, uint8_t retry) { @@ -401,7 +402,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, memset(wqe, 0, sizeof(union lpfc_wqe)); genwqe->context3 = (uint8_t *)bmp; - genwqe->iocb_flag |= LPFC_IO_NVME_LS; + genwqe->cmd_flag |= LPFC_IO_NVME_LS; /* Save for completion so we can release these resources */ genwqe->context1 = lpfc_nlp_get(ndlp); @@ -432,7 +433,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, first_len = xmit_len; } - genwqe->rsvd2 = num_entry; + genwqe->num_bdes = num_entry; genwqe->hba_wqidx = 0; /* Words 0 - 2 */ @@ -483,8 +484,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, /* Issue GEN REQ WQE for NPORT <did> */ - genwqe->wqe_cmpl = cmpl; - genwqe->iocb_cmpl = NULL; + genwqe->cmd_cmpl = cmpl; genwqe->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT; genwqe->vport = vport; genwqe->retry = retry; @@ -534,7 +534,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct nvmefc_ls_req *pnvme_lsreq, void (*gen_req_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe)) + struct lpfc_iocbq *rspwqe)) { struct lpfc_dmabuf *bmp; struct ulp_bde64 *bpl; @@ -722,7 +722,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_lock(&pring->ring_lock); list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) { if (wqe->context2 == pnvme_lsreq) { - wqe->iocb_flag |= LPFC_DRIVER_ABORTED; + wqe->cmd_flag |= LPFC_DRIVER_ABORTED; foundit = true; break; } @@ -906,7 +906,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, /* - * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO + * lpfc_nvme_io_cmd_cmpl - Complete an NVME-over-FCP IO * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -917,11 +917,12 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, * TODO: What are the failure codes. **/ static void -lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, - struct lpfc_wcqe_complete *wcqe) +lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + struct lpfc_iocbq *pwqeOut) { struct lpfc_io_buf *lpfc_ncmd = (struct lpfc_io_buf *)pwqeIn->context1; + struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; struct lpfc_vport *vport = pwqeIn->vport; struct nvmefc_fcp_req *nCmd; struct nvme_fc_ersp_iu *ep; @@ -1745,9 +1746,8 @@ lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "6145 ABORT_XRI_CN completing on rpi x%x " "original iotag x%x, abort cmd iotag x%x " "req_tag x%x, status x%x, hwstatus x%x\n", - cmdiocb->iocb.un.acxri.abortContextTag, - cmdiocb->iocb.un.acxri.abortIoTag, - cmdiocb->iotag, + bf_get(wqe_ctxt_tag, &cmdiocb->wqe.generic.wqe_com), + get_job_abtsiotag(phba, cmdiocb), cmdiocb->iotag, bf_get(lpfc_wcqe_c_request_tag, abts_cmpl), bf_get(lpfc_wcqe_c_status, abts_cmpl), bf_get(lpfc_wcqe_c_hw_status, abts_cmpl)); @@ -1866,7 +1866,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, } /* Don't abort IOs no longer on the pending queue. */ - if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { + if (!(nvmereq_wqe->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6142 NVME IO req x%px not queued - skipping " "abort req xri x%x\n", @@ -1880,7 +1880,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, nvmereq_wqe->hba_wqidx, pnvme_rport->port_id); /* Outstanding abort is in progress */ - if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) { + if (nvmereq_wqe->cmd_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6144 Outstanding NVME I/O Abort Request " "still pending on nvme_fcreq x%px, " @@ -1975,8 +1975,8 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, /* Setup key fields in buffer that may have been changed * if other protocols used this buffer. */ - pwqeq->iocb_flag = LPFC_IO_NVME; - pwqeq->wqe_cmpl = lpfc_nvme_io_cmd_wqe_cmpl; + pwqeq->cmd_flag = LPFC_IO_NVME; + pwqeq->cmd_cmpl = lpfc_nvme_io_cmd_cmpl; lpfc_ncmd->start_time = jiffies; lpfc_ncmd->flags = 0; @@ -2742,6 +2742,7 @@ lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) bf_set(lpfc_wcqe_c_xb, wcqep, 1); - (pwqeIn->wqe_cmpl)(phba, pwqeIn, wcqep); + memcpy(&pwqeIn->wcqe_cmpl, wcqep, sizeof(*wcqep)); + (pwqeIn->cmd_cmpl)(phba, pwqeIn, pwqeIn); #endif } diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index cc54ffb5c205..733c277948c0 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -234,7 +234,7 @@ int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct nvmefc_ls_req *pnvme_lsreq, void (*gen_req_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe)); + struct lpfc_iocbq *rspwqe)); void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); int __lpfc_nvme_ls_abort(struct lpfc_vport *vport, @@ -248,6 +248,6 @@ int __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, struct nvmefc_ls_rsp *ls_rsp, void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe)); + struct lpfc_iocbq *rspwqe)); void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, - struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); + struct lpfc_iocbq *cmdwqe, struct lpfc_iocbq *rspwqe); diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 731802527b81..95438265fb16 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -285,7 +285,7 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba, * transmission of an NVME LS response. * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. The function frees memory resources used for the command @@ -293,9 +293,10 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba, **/ void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_async_xchg_ctx *axchg = cmdwqe->context2; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; uint32_t status, result; @@ -331,7 +332,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME LS commands @@ -340,10 +341,11 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, **/ static void lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_nvmet_tgtport *tgtp; uint32_t status, result; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; if (!phba->targetport) goto finish; @@ -365,7 +367,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, } finish: - __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, wcqe); + __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, rspwqe); } /** @@ -707,7 +709,7 @@ out: * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME FCP commands @@ -715,12 +717,13 @@ out: **/ static void lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_nvmet_tgtport *tgtp; struct nvmefc_tgt_fcp_req *rsp; struct lpfc_async_xchg_ctx *ctxp; uint32_t status, result, op, start_clean, logerr; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; #ifdef CONFIG_SCSI_LPFC_DEBUG_FS int id; #endif @@ -817,7 +820,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, /* lpfc_nvmet_xmt_fcp_release() will recycle the context */ } else { ctxp->entry_cnt++; - start_clean = offsetof(struct lpfc_iocbq, iocb_flag); + start_clean = offsetof(struct lpfc_iocbq, cmd_flag); memset(((char *)cmdwqe) + start_clean, 0, (sizeof(struct lpfc_iocbq) - start_clean)); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS @@ -862,7 +865,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, struct nvmefc_ls_rsp *ls_rsp, void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe)) + struct lpfc_iocbq *rspwqe)) { struct lpfc_hba *phba = axchg->phba; struct hbq_dmabuf *nvmebuf = (struct hbq_dmabuf *)axchg->rqb_buffer; @@ -898,7 +901,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, } /* Save numBdes for bpl2sgl */ - nvmewqeq->rsvd2 = 1; + nvmewqeq->num_bdes = 1; nvmewqeq->hba_wqidx = 0; nvmewqeq->context3 = &dmabuf; dmabuf.virt = &bpl; @@ -913,8 +916,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, * be referenced after it returns back to this routine. */ - nvmewqeq->wqe_cmpl = xmt_ls_rsp_cmp; - nvmewqeq->iocb_cmpl = NULL; + nvmewqeq->cmd_cmpl = xmt_ls_rsp_cmp; nvmewqeq->context2 = axchg; lpfc_nvmeio_data(phba, "NVMEx LS RSP: xri x%x wqidx x%x len x%x\n", @@ -1072,10 +1074,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, goto aerr; } - nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; - nvmewqeq->iocb_cmpl = NULL; + nvmewqeq->cmd_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; nvmewqeq->context2 = ctxp; - nvmewqeq->iocb_flag |= LPFC_IO_NVMET; + nvmewqeq->cmd_flag |= LPFC_IO_NVMET; ctxp->wqeq->hba_wqidx = rsp->hwqid; lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n", @@ -1275,7 +1276,7 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport, * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request * @phba: Pointer to HBA context object * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * This function is the completion handler for NVME LS requests. * The function updates any states and statistics, then calls the @@ -1283,8 +1284,9 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport, **/ static void lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; __lpfc_nvme_ls_req_cmp(phba, cmdwqe->vport, cmdwqe, wcqe); } @@ -1581,7 +1583,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) "6406 Ran out of NVMET iocb/WQEs\n"); return -ENOMEM; } - ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET; + ctx_buf->iocbq->cmd_flag = LPFC_IO_NVMET; nvmewqe = ctx_buf->iocbq; wqe = &nvmewqe->wqe; @@ -2027,8 +2029,10 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq, list_del(&nvmewqeq->list); spin_unlock_irqrestore(&pring->ring_lock, iflags); + memcpy(&nvmewqeq->wcqe_cmpl, wcqep, + sizeof(*wcqep)); lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, - wcqep); + nvmewqeq); return; } continue; @@ -2036,7 +2040,8 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq, /* Flush all IOs */ list_del(&nvmewqeq->list); spin_unlock_irqrestore(&pring->ring_lock, iflags); - lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep); + memcpy(&nvmewqeq->wcqe_cmpl, wcqep, sizeof(*wcqep)); + lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, nvmewqeq); spin_lock_irqsave(&pring->ring_lock, iflags); } } @@ -2676,7 +2681,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, nvmewqe->retry = 1; nvmewqe->vport = phba->pport; nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT; - nvmewqe->iocb_flag |= LPFC_IO_NVME_LS; + nvmewqe->cmd_flag |= LPFC_IO_NVME_LS; /* Xmit NVMET response to remote NPORT <did> */ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, @@ -3031,7 +3036,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for FCP cmds @@ -3039,13 +3044,14 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, **/ static void lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; uint32_t result; unsigned long flags; bool released = false; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3100,7 +3106,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for FCP cmds @@ -3108,13 +3114,14 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, **/ static void lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; unsigned long flags; uint32_t result; bool released = false; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3181,7 +3188,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @wcqe: Pointer to driver response CQE object. + * @rspwqe: Pointer to driver response WQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for LS cmds @@ -3189,11 +3196,12 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, **/ static void lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *rspwqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; uint32_t result; + struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3317,7 +3325,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, abts_wqeq->context1 = ndlp; abts_wqeq->context2 = ctxp; abts_wqeq->context3 = NULL; - abts_wqeq->rsvd2 = 0; + abts_wqeq->num_bdes = 0; /* hba_wqidx should already be setup from command we are aborting */ abts_wqeq->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CR; abts_wqeq->iocb.ulpLe = 1; @@ -3446,7 +3454,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, } /* Outstanding abort is in progress */ - if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) { + if (abts_wqeq->cmd_flag & LPFC_DRIVER_ABORTED) { spin_unlock_irqrestore(&phba->hbalock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -3461,15 +3469,14 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, } /* Ready - mark outstanding as aborted by driver. */ - abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED; + abts_wqeq->cmd_flag |= LPFC_DRIVER_ABORTED; lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt); /* ABTS WQE must go to the same WQ as the WQE to be aborted */ abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx; - abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; - abts_wqeq->iocb_cmpl = NULL; - abts_wqeq->iocb_flag |= LPFC_IO_NVME; + abts_wqeq->cmd_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; + abts_wqeq->cmd_flag |= LPFC_IO_NVME; abts_wqeq->context2 = ctxp; abts_wqeq->vport = phba->pport; if (!ctxp->hdwq) @@ -3526,9 +3533,8 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba, spin_lock_irqsave(&phba->hbalock, flags); abts_wqeq = ctxp->wqeq; - abts_wqeq->wqe_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; - abts_wqeq->iocb_cmpl = NULL; - abts_wqeq->iocb_flag |= LPFC_IO_NVMET; + abts_wqeq->cmd_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; + abts_wqeq->cmd_flag |= LPFC_IO_NVMET; if (!ctxp->hdwq) ctxp->hdwq = &phba->sli4_hba.hdwq[abts_wqeq->hba_wqidx]; @@ -3612,9 +3618,8 @@ lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba, } spin_lock_irqsave(&phba->hbalock, flags); - abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; - abts_wqeq->iocb_cmpl = NULL; - abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS; + abts_wqeq->cmd_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; + abts_wqeq->cmd_flag |= LPFC_IO_NVME_LS; rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq); spin_unlock_irqrestore(&phba->hbalock, flags); if (rc == WQE_SUCCESS) { diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 5a3da38a9067..3c132604fd91 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -362,7 +362,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) kfree(psb); break; } - psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; + psb->cur_iocbq.cmd_flag |= LPFC_IO_FCP; psb->fcp_cmnd = psb->data; psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); @@ -468,7 +468,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) spin_lock(&qp->abts_io_buf_list_lock); list_for_each_entry_safe(psb, next_psb, &qp->lpfc_abts_io_buf_list, list) { - if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) + if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) continue; if (psb->rdata && psb->rdata->pnode && @@ -524,7 +524,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, list_del_init(&psb->list); psb->flags &= ~LPFC_SBUF_XBUSY; psb->status = IOSTAT_SUCCESS; - if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) { + if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) { qp->abts_nvme_io_bufs--; spin_unlock(&qp->abts_io_buf_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -571,7 +571,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, * for command completion wake up the thread. */ spin_lock_irqsave(&psb->buf_lock, iflag); - psb->cur_iocbq.iocb_flag &= + psb->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; if (psb->waitq) wake_up(psb->waitq); @@ -593,8 +593,8 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, for (i = 1; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; - if (!(iocbq->iocb_flag & LPFC_IO_FCP) || - (iocbq->iocb_flag & LPFC_IO_LIBDFC)) + if (!(iocbq->cmd_flag & LPFC_IO_FCP) || + (iocbq->cmd_flag & LPFC_IO_LIBDFC)) continue; if (iocbq->sli4_xritag != xri) continue; @@ -695,7 +695,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, /* Setup key fields in buffer that may have been changed * if other protocols used this buffer. */ - lpfc_cmd->cur_iocbq.iocb_flag = LPFC_IO_FCP; + lpfc_cmd->cur_iocbq.cmd_flag = LPFC_IO_FCP; lpfc_cmd->prot_seg_cnt = 0; lpfc_cmd->seg_cnt = 0; lpfc_cmd->timeout = 0; @@ -783,7 +783,7 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb) spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); psb->pCmd = NULL; - psb->cur_iocbq.iocb_flag = LPFC_IO_FCP; + psb->cur_iocbq.cmd_flag = LPFC_IO_FCP; list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put); spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); } @@ -931,7 +931,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) physaddr = sg_dma_address(sgel); if (phba->sli_rev == 3 && !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - !(iocbq->iocb_flag & DSS_SECURITY_OP) && + !(iocbq->cmd_flag & DSS_SECURITY_OP) && nseg <= LPFC_EXT_DATA_BDE_COUNT) { data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; data_bde->tus.f.bdeSize = sg_dma_len(sgel); @@ -959,7 +959,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) */ if (phba->sli_rev == 3 && !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - !(iocbq->iocb_flag & DSS_SECURITY_OP)) { + !(iocbq->cmd_flag & DSS_SECURITY_OP)) { if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { /* * The extended IOCB format can only fit 3 BDE or a BPL. @@ -2942,154 +2942,58 @@ out: * -1 - Internal error (bad profile, ...etc) */ static int -lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, - struct lpfc_wcqe_complete *wcqe) +lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + struct lpfc_iocbq *pIocbOut) { struct scsi_cmnd *cmd = lpfc_cmd->pCmd; + struct sli3_bg_fields *bgf; int ret = 0; - u32 status = bf_get(lpfc_wcqe_c_status, wcqe); + struct lpfc_wcqe_complete *wcqe; + u32 status; u32 bghm = 0; u32 bgstat = 0; u64 failing_sector = 0; - if (status == CQE_STATUS_DI_ERROR) { - if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ - bgstat |= BGS_GUARD_ERR_MASK; - if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */ - bgstat |= BGS_APPTAG_ERR_MASK; - if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */ - bgstat |= BGS_REFTAG_ERR_MASK; - - /* Check to see if there was any good data before the error */ - if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { - bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; - bghm = wcqe->total_data_placed; - } - - /* - * Set ALL the error bits to indicate we don't know what - * type of error it is. - */ - if (!bgstat) - bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | - BGS_GUARD_ERR_MASK); - } - - if (lpfc_bgs_get_guard_err(bgstat)) { - ret = 1; - - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); - set_host_byte(cmd, DID_ABORT); - phba->bg_guard_err_cnt++; - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, - "9059 BLKGRD: Guard Tag error in cmd" - " 0x%x lba 0x%llx blk cnt 0x%x " - "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], - (unsigned long long)scsi_get_lba(cmd), - scsi_logical_block_count(cmd), bgstat, bghm); - } - - if (lpfc_bgs_get_reftag_err(bgstat)) { - ret = 1; + if (phba->sli_rev == LPFC_SLI_REV4) { + wcqe = &pIocbOut->wcqe_cmpl; + status = bf_get(lpfc_wcqe_c_status, wcqe); - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); - set_host_byte(cmd, DID_ABORT); + if (status == CQE_STATUS_DI_ERROR) { + /* Guard Check failed */ + if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) + bgstat |= BGS_GUARD_ERR_MASK; - phba->bg_reftag_err_cnt++; - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, - "9060 BLKGRD: Ref Tag error in cmd" - " 0x%x lba 0x%llx blk cnt 0x%x " - "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], - (unsigned long long)scsi_get_lba(cmd), - scsi_logical_block_count(cmd), bgstat, bghm); - } + /* AppTag Check failed */ + if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) + bgstat |= BGS_APPTAG_ERR_MASK; - if (lpfc_bgs_get_apptag_err(bgstat)) { - ret = 1; + /* RefTag Check failed */ + if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) + bgstat |= BGS_REFTAG_ERR_MASK; - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); - set_host_byte(cmd, DID_ABORT); - - phba->bg_apptag_err_cnt++; - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, - "9062 BLKGRD: App Tag error in cmd" - " 0x%x lba 0x%llx blk cnt 0x%x " - "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], - (unsigned long long)scsi_get_lba(cmd), - scsi_logical_block_count(cmd), bgstat, bghm); - } - - if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { - /* - * setup sense data descriptor 0 per SPC-4 as an information - * field, and put the failing LBA in it. - * This code assumes there was also a guard/app/ref tag error - * indication. - */ - cmd->sense_buffer[7] = 0xc; /* Additional sense length */ - cmd->sense_buffer[8] = 0; /* Information descriptor type */ - cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */ - cmd->sense_buffer[10] = 0x80; /* Validity bit */ + /* Check to see if there was any good data before the + * error + */ + if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { + bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; + bghm = wcqe->total_data_placed; + } - /* bghm is a "on the wire" FC frame based count */ - switch (scsi_get_prot_op(cmd)) { - case SCSI_PROT_READ_INSERT: - case SCSI_PROT_WRITE_STRIP: - bghm /= cmd->device->sector_size; - break; - case SCSI_PROT_READ_STRIP: - case SCSI_PROT_WRITE_INSERT: - case SCSI_PROT_READ_PASS: - case SCSI_PROT_WRITE_PASS: - bghm /= (cmd->device->sector_size + - sizeof(struct scsi_dif_tuple)); - break; + /* + * Set ALL the error bits to indicate we don't know what + * type of error it is. + */ + if (!bgstat) + bgstat |= (BGS_REFTAG_ERR_MASK | + BGS_APPTAG_ERR_MASK | + BGS_GUARD_ERR_MASK); } - failing_sector = scsi_get_lba(cmd); - failing_sector += bghm; - - /* Descriptor Information */ - put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]); - } - - if (!ret) { - /* No error was reported - problem in FW? */ - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, - "9068 BLKGRD: Unknown error in cmd" - " 0x%x lba 0x%llx blk cnt 0x%x " - "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], - (unsigned long long)scsi_get_lba(cmd), - scsi_logical_block_count(cmd), bgstat, bghm); - - /* Calculate what type of error it was */ - lpfc_calc_bg_err(phba, lpfc_cmd); + } else { + bgf = &pIocbOut->iocb.unsli3.sli3_bg; + bghm = bgf->bghm; + bgstat = bgf->bgstat; } - return ret; -} - -/* - * This function checks for BlockGuard errors detected by - * the HBA. In case of errors, the ASC/ASCQ fields in the - * sense buffer will be set accordingly, paired with - * ILLEGAL_REQUEST to signal to the kernel that the HBA - * detected corruption. - * - * Returns: - * 0 - No error found - * 1 - BlockGuard error found - * -1 - Internal error (bad profile, ...etc) - */ -static int -lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, - struct lpfc_iocbq *pIocbOut) -{ - struct scsi_cmnd *cmd = lpfc_cmd->pCmd; - struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg; - int ret = 0; - uint32_t bghm = bgf->bghm; - uint32_t bgstat = bgf->bgstat; - uint64_t failing_sector = 0; if (lpfc_bgs_get_invalid_prof(bgstat)) { cmd->result = DID_ERROR << 16; @@ -3117,7 +3021,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, if (lpfc_bgs_get_guard_err(bgstat)) { ret = 1; - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); set_host_byte(cmd, DID_ABORT); phba->bg_guard_err_cnt++; @@ -3131,10 +3034,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, if (lpfc_bgs_get_reftag_err(bgstat)) { ret = 1; - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); set_host_byte(cmd, DID_ABORT); - phba->bg_reftag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9056 BLKGRD: Ref Tag error in cmd " @@ -3146,10 +3047,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, if (lpfc_bgs_get_apptag_err(bgstat)) { ret = 1; - scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); set_host_byte(cmd, DID_ABORT); - phba->bg_apptag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9061 BLKGRD: App Tag error in cmd " @@ -3434,7 +3333,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) */ if ((phba->cfg_fof) && ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->oas_enabled) { - lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->priority; @@ -3591,15 +3490,15 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, switch (scsi_get_prot_op(scsi_cmnd)) { case SCSI_PROT_WRITE_STRIP: case SCSI_PROT_READ_STRIP: - lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP; + lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_STRIP; break; case SCSI_PROT_WRITE_INSERT: case SCSI_PROT_READ_INSERT: - lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT; + lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_INSERT; break; case SCSI_PROT_WRITE_PASS: case SCSI_PROT_READ_PASS: - lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS; + lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_PASS; break; } @@ -3630,7 +3529,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, */ if ((phba->cfg_fof) && ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->oas_enabled) { - lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); /* Word 10 */ bf_set(wqe_oas, &wqe->generic.wqe_com, 1); @@ -3640,14 +3539,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, } /* Word 7. DIF Flags */ - if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_PASS) + if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_PASS) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); - else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_STRIP) + else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_STRIP) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); - else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_INSERT) + else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_INSERT) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); - lpfc_cmd->cur_iocbq.iocb_flag &= ~(LPFC_IO_DIF_PASS | + lpfc_cmd->cur_iocbq.cmd_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT); return 0; @@ -4173,7 +4072,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO * @phba: The hba for which this call is being executed. * @pwqeIn: The command WQE for the scsi cmnd. - * @wcqe: Pointer to driver response CQE object. + * @pwqeOut: Pointer to driver response WQE object. * * This routine assigns scsi command result by looking into response WQE * status field appropriately. This routine handles QUEUE FULL condition as @@ -4181,10 +4080,11 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, **/ static void lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, - struct lpfc_wcqe_complete *wcqe) + struct lpfc_iocbq *pwqeOut) { struct lpfc_io_buf *lpfc_cmd = (struct lpfc_io_buf *)pwqeIn->context1; + struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; struct lpfc_vport *vport = pwqeIn->vport; struct lpfc_rport_data *rdata; struct lpfc_nodelist *ndlp; @@ -4194,7 +4094,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, struct Scsi_Host *shost; u32 logit = LOG_FCP; u32 status, idx; - unsigned long iflags = 0; u32 lat; u8 wait_xb_clr = 0; @@ -4209,30 +4108,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, rdata = lpfc_cmd->rdata; ndlp = rdata->pnode; - if (bf_get(lpfc_wcqe_c_xb, wcqe)) { - /* TOREMOVE - currently this flag is checked during - * the release of lpfc_iocbq. Remove once we move - * to lpfc_wqe_job construct. - * - * This needs to be done outside buf_lock - */ - spin_lock_irqsave(&phba->hbalock, iflags); - lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } - - /* Guard against abort handler being called at same time */ - spin_lock(&lpfc_cmd->buf_lock); - /* Sanity check on return of outstanding command */ cmd = lpfc_cmd->pCmd; if (!cmd) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "9042 I/O completion: Not an active IO\n"); - spin_unlock(&lpfc_cmd->buf_lock); lpfc_release_scsi_buf(phba, lpfc_cmd); return; } + /* Guard against abort handler being called at same time */ + spin_lock(&lpfc_cmd->buf_lock); idx = lpfc_cmd->cur_iocbq.hba_wqidx; if (phba->sli4_hba.hdwq) phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; @@ -4407,12 +4292,14 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, * This is a response for a BG enabled * cmd. Parse BG error */ - lpfc_sli4_parse_bg_err(phba, lpfc_cmd, - wcqe); + lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); break; + } else { + lpfc_printf_vlog(vport, KERN_WARNING, + LOG_BG, + "9040 non-zero BGSTAT " + "on unprotected cmd\n"); } - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, - "9040 non-zero BGSTAT on unprotected cmd\n"); } lpfc_printf_vlog(vport, KERN_WARNING, logit, "9036 Local Reject FCP cmd x%x failed" @@ -4510,7 +4397,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, * wake up the thread. */ spin_lock(&lpfc_cmd->buf_lock); - lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); spin_unlock(&lpfc_cmd->buf_lock); @@ -4570,7 +4457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_cmd->status = pIocbOut->iocb.ulpStatus; /* pick up SLI4 exchange busy status from HBA */ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; - if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY) + if (pIocbOut->cmd_flag & LPFC_EXCHANGE_BUSY) lpfc_cmd->flags |= LPFC_SBUF_XBUSY; #ifdef CONFIG_SCSI_LPFC_DEBUG_FS @@ -4779,7 +4666,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * wake up the thread. */ spin_lock(&lpfc_cmd->buf_lock); - lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); spin_unlock(&lpfc_cmd->buf_lock); @@ -4857,8 +4744,8 @@ static int lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport *vport, piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f); piocbq->context1 = lpfc_cmd; - if (!piocbq->iocb_cmpl) - piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; + if (!piocbq->cmd_cmpl) + piocbq->cmd_cmpl = lpfc_scsi_cmd_iocb_cmpl; piocbq->iocb.ulpTimeout = tmo; piocbq->vport = vport; return 0; @@ -4971,7 +4858,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport, pwqeq->vport = vport; pwqeq->context1 = lpfc_cmd; pwqeq->hba_wqidx = lpfc_cmd->hdwq_no; - pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; + pwqeq->cmd_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; return 0; } @@ -5018,7 +4905,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, } /** - * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit + * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit * @vport: The virtual port for which this call is being executed. * @lpfc_cmd: Pointer to lpfc_io_buf data structure. * @lun: Logical unit number. @@ -5032,10 +4919,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, * 1 - Success **/ static int -lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, - struct lpfc_io_buf *lpfc_cmd, - uint64_t lun, - uint8_t task_mgmt_cmd) +lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + u64 lun, u8 task_mgmt_cmd) { struct lpfc_iocbq *piocbq; IOCB_t *piocb; @@ -5056,15 +4942,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); int_to_scsilun(lun, &fcp_cmnd->fcp_lun); fcp_cmnd->fcpCntl2 = task_mgmt_cmd; - if (vport->phba->sli_rev == 3 && - !(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) + if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); piocb->ulpCommand = CMD_FCP_ICMND64_CR; piocb->ulpContext = ndlp->nlp_rpi; - if (vport->phba->sli_rev == LPFC_SLI_REV4) { - piocb->ulpContext = - vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; - } piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0; piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); piocb->ulpPU = 0; @@ -5080,8 +4961,79 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, } else piocb->ulpTimeout = lpfc_cmd->timeout; - if (vport->phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); + return 1; +} + +/** + * lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit + * @vport: The virtual port for which this call is being executed. + * @lpfc_cmd: Pointer to lpfc_io_buf data structure. + * @lun: Logical unit number. + * @task_mgmt_cmd: SCSI task management command. + * + * This routine creates FCP information unit corresponding to @task_mgmt_cmd + * for device with SLI-4 interface spec. + * + * Return codes: + * 0 - Error + * 1 - Success + **/ +static int +lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + u64 lun, u8 task_mgmt_cmd) +{ + struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; + union lpfc_wqe128 *wqe = &pwqeq->wqe; + struct fcp_cmnd *fcp_cmnd; + struct lpfc_rport_data *rdata = lpfc_cmd->rdata; + struct lpfc_nodelist *ndlp = rdata->pnode; + + if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE) + return 0; + + pwqeq->vport = vport; + /* Initialize 64 bytes only */ + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* From the icmnd template, initialize words 4 - 11 */ + memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4], + sizeof(uint32_t) * 8); + + fcp_cmnd = lpfc_cmd->fcp_cmnd; + /* Clear out any old data in the FCP command area */ + memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); + int_to_scsilun(lun, &fcp_cmnd->fcp_lun); + fcp_cmnd->fcpCntl3 = 0; + fcp_cmnd->fcpCntl2 = task_mgmt_cmd; + + bf_set(payload_offset_len, &wqe->fcp_icmd, + sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); + bf_set(cmd_buff_len, &wqe->fcp_icmd, 0); + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, /* ulpContext */ + vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, + ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0)); + bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, + (ndlp->nlp_fcp_info & 0x0f)); + + /* ulpTimeout is only one byte */ + if (lpfc_cmd->timeout > 0xff) { + /* + * Do not timeout the command at the firmware level. + * The driver will provide the timeout mechanism. + */ + bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0); + } else { + bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout); + } + + lpfc_prep_embed_io(vport->phba, lpfc_cmd); + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag); + wqe->generic.wqe_com.abort_tag = pwqeq->iotag; + bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); + + lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); return 1; } @@ -5108,6 +5060,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3; + phba->lpfc_scsi_prep_task_mgmt_cmd = + lpfc_scsi_prep_task_mgmt_cmd_s3; break; case LPFC_PCI_DEV_OC: phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; @@ -5115,6 +5069,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4; + phba->lpfc_scsi_prep_task_mgmt_cmd = + lpfc_scsi_prep_task_mgmt_cmd_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -5593,6 +5549,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) { struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *cur_iocbq = NULL; struct lpfc_rport_data *rdata; struct lpfc_nodelist *ndlp; struct lpfc_io_buf *lpfc_cmd; @@ -5686,6 +5643,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) } lpfc_cmd->rx_cmd_start = start; + cur_iocbq = &lpfc_cmd->cur_iocbq; /* * Store the midlayer's command structure for the completion phase * and complete the command initialization. @@ -5693,7 +5651,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) lpfc_cmd->pCmd = cmnd; lpfc_cmd->rdata = rdata; lpfc_cmd->ndlp = ndlp; - lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; + cur_iocbq->cmd_cmpl = NULL; cmnd->host_scribble = (unsigned char *)lpfc_cmd; err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); @@ -5735,7 +5693,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) goto out_host_busy_free_buf; } - /* check the necessary and sufficient condition to support VMID */ if (lpfc_is_vmid_enabled(phba) && (ndlp->vmid_support || @@ -5748,20 +5705,19 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) if (uuid) { err = lpfc_vmid_get_appid(vport, uuid, cmnd, (union lpfc_vmid_io_tag *) - &lpfc_cmd->cur_iocbq.vmid_tag); + &cur_iocbq->vmid_tag); if (!err) - lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_VMID; + cur_iocbq->cmd_flag |= LPFC_IO_VMID; } } - atomic_inc(&ndlp->cmd_pending); + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); #endif /* Issue I/O to adapter */ - err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, - &lpfc_cmd->cur_iocbq, + err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq, SLI_IOCB_RET_IOCB); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS if (start) { @@ -5774,25 +5730,25 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) #endif if (err) { lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "3376 FCP could not issue IOCB err %x " - "FCP cmd x%x <%d/%llu> " - "sid: x%x did: x%x oxid: x%x " - "Data: x%x x%x x%x x%x\n", - err, cmnd->cmnd[0], - cmnd->device ? cmnd->device->id : 0xffff, - cmnd->device ? cmnd->device->lun : (u64)-1, - vport->fc_myDID, ndlp->nlp_DID, - phba->sli_rev == LPFC_SLI_REV4 ? - lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, - phba->sli_rev == LPFC_SLI_REV4 ? - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : - lpfc_cmd->cur_iocbq.iocb.ulpContext, - lpfc_cmd->cur_iocbq.iotag, - phba->sli_rev == LPFC_SLI_REV4 ? - bf_get(wqe_tmo, - &lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) : - lpfc_cmd->cur_iocbq.iocb.ulpTimeout, - (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); + "3376 FCP could not issue iocb err %x " + "FCP cmd x%x <%d/%llu> " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x x%x\n", + err, cmnd->cmnd[0], + cmnd->device ? cmnd->device->id : 0xffff, + cmnd->device ? cmnd->device->lun : (u64)-1, + vport->fc_myDID, ndlp->nlp_DID, + phba->sli_rev == LPFC_SLI_REV4 ? + cur_iocbq->sli4_xritag : 0xffff, + phba->sli_rev == LPFC_SLI_REV4 ? + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : + cur_iocbq->iocb.ulpContext, + cur_iocbq->iotag, + phba->sli_rev == LPFC_SLI_REV4 ? + bf_get(wqe_tmo, + &cur_iocbq->wqe.generic.wqe_com) : + cur_iocbq->iocb.ulpTimeout, + (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); goto out_host_busy_free_buf; } @@ -5888,6 +5844,7 @@ static int lpfc_abort_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocb; @@ -5899,7 +5856,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); - status = fc_block_scsi_eh(cmnd); + status = fc_block_rport(rport); if (status != 0 && status != SUCCESS) return status; @@ -5938,7 +5895,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) spin_lock(&pring_s4->ring_lock); } /* the command is in process of being cancelled */ - if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { + if (!(iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3169 SCSI Layer abort requested I/O has been " "cancelled by LLD.\n"); @@ -5961,7 +5918,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) BUG_ON(iocb->context1 != lpfc_cmd); /* abort issued in recovery is still in progress */ - if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) { + if (iocb->cmd_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3389 SCSI Layer I/O Abort Request is pending\n"); if (phba->sli_rev == LPFC_SLI_REV4) @@ -5972,15 +5929,13 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } lpfc_cmd->waitq = &waitq; - if (phba->sli_rev == LPFC_SLI_REV4) { + if (phba->sli_rev == LPFC_SLI_REV4) spin_unlock(&pring_s4->ring_lock); - ret_val = lpfc_sli4_issue_abort_iotag(phba, iocb, - lpfc_sli4_abort_fcp_cmpl); - } else { + else pring = &phba->sli.sli3_ring[LPFC_FCP_RING]; - ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb, - lpfc_sli_abort_fcp_cmpl); - } + + ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb, + lpfc_sli_abort_fcp_cmpl); /* Make sure HBA is alive */ lpfc_issue_hb_tmo(phba); @@ -6004,7 +5959,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) wait_for_cmpl: /* - * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait + * cmd_flag is set to LPFC_DRIVER_ABORTED before we wait * for abort to complete. */ wait_event_timeout(waitq, @@ -6141,7 +6096,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd) /** * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler * @vport: The virtual port for which this call is being executed. - * @cmnd: Pointer to scsi_cmnd data structure. + * @rport: Pointer to remote port * @tgt_id: Target ID of remote device. * @lun_id: Lun number for the TMF * @task_mgmt_cmd: type of TMF to send @@ -6154,7 +6109,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd) * 0x2002 - Success. **/ static int -lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, +lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, unsigned int tgt_id, uint64_t lun_id, uint8_t task_mgmt_cmd) { @@ -6167,21 +6122,21 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, int ret; int status; - rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + rdata = rport->dd_data; if (!rdata || !rdata->pnode) return FAILED; pnode = rdata->pnode; - lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL); + lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL); if (lpfc_cmd == NULL) return FAILED; lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; lpfc_cmd->rdata = rdata; - lpfc_cmd->pCmd = cmnd; + lpfc_cmd->pCmd = NULL; lpfc_cmd->ndlp = pnode; - status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, - task_mgmt_cmd); + status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, + task_mgmt_cmd); if (!status) { lpfc_release_scsi_buf(phba, lpfc_cmd); return FAILED; @@ -6193,38 +6148,41 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, lpfc_release_scsi_buf(phba, lpfc_cmd); return FAILED; } - iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; + iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl; + iocbq->vport = vport; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "0702 Issue %s to TGT %d LUN %llu " "rpi x%x nlp_flag x%x Data: x%x x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, - iocbq->iocb_flag); + iocbq->cmd_flag); status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, iocbq, iocbqrsp, lpfc_cmd->timeout); if ((status != IOCB_SUCCESS) || - (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { + (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) { if (status != IOCB_SUCCESS || - iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) + get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0727 TMF %s to TGT %d LUN %llu " - "failed (%d, %d) iocb_flag x%x\n", + "failed (%d, %d) cmd_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, - iocbqrsp->iocb.ulpStatus, - iocbqrsp->iocb.un.ulpWord[4], - iocbq->iocb_flag); + get_job_ulpstatus(phba, iocbqrsp), + get_job_word4(phba, iocbqrsp), + iocbq->cmd_flag); /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ if (status == IOCB_SUCCESS) { - if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) + if (get_job_ulpstatus(phba, iocbqrsp) == + IOSTAT_FCP_RSP_ERROR) /* Something in the FCP_RSP was invalid. * Check conditions */ ret = lpfc_check_fcp_rsp(vport, lpfc_cmd); else ret = FAILED; - } else if (status == IOCB_TIMEDOUT) { + } else if ((status == IOCB_TIMEDOUT) || + (status == IOCB_ABORTED)) { ret = TIMEOUT_ERROR; } else { ret = FAILED; @@ -6234,7 +6192,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, lpfc_sli_release_iocbq(phba, iocbqrsp); - if (ret != TIMEOUT_ERROR) + if (status != IOCB_TIMEDOUT) lpfc_release_scsi_buf(phba, lpfc_cmd); return ret; @@ -6243,7 +6201,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, /** * lpfc_chk_tgt_mapped - * @vport: The virtual port to check on - * @cmnd: Pointer to scsi_cmnd data structure. + * @rport: Pointer to fc_rport data structure. * * This routine delays until the scsi target (aka rport) for the * command exists (is present and logged in) or we declare it non-existent. @@ -6253,19 +6211,20 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, * 0x2002 - Success **/ static int -lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) +lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct fc_rport *rport) { struct lpfc_rport_data *rdata; - struct lpfc_nodelist *pnode; + struct lpfc_nodelist *pnode = NULL; unsigned long later; - rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + rdata = rport->dd_data; if (!rdata) { lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "0797 Tgt Map rport failure: rdata x%px\n", rdata); return FAILED; } pnode = rdata->pnode; + /* * If target is not in a MAPPED state, delay until * target is rediscovered or devloss timeout expires. @@ -6277,7 +6236,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) if (pnode->nlp_state == NLP_STE_MAPPED_NODE) return SUCCESS; schedule_timeout_uninterruptible(msecs_to_jiffies(500)); - rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + rdata = rport->dd_data; if (!rdata) return FAILED; pnode = rdata->pnode; @@ -6348,6 +6307,7 @@ static int lpfc_device_reset_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; @@ -6357,7 +6317,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) int status; u32 logit = LOG_FCP; - rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + rdata = rport->dd_data; if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0798 Device Reset rdata failure: rdata x%px\n", @@ -6365,11 +6325,11 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) return FAILED; } pnode = rdata->pnode; - status = fc_block_scsi_eh(cmnd); + status = fc_block_rport(rport); if (status != 0 && status != SUCCESS) return status; - status = lpfc_chk_tgt_mapped(vport, cmnd); + status = lpfc_chk_tgt_mapped(vport, rport); if (status == FAILED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0721 Device Reset rport failure: rdata x%px\n", rdata); @@ -6385,7 +6345,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, + status = lpfc_send_taskmgmt(vport, rport, tgt_id, lun_id, FCP_LUN_RESET); if (status != SUCCESS) logit = LOG_TRACE_EVENT; @@ -6422,6 +6382,7 @@ static int lpfc_target_reset_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; @@ -6434,7 +6395,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); - rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + rdata = rport->dd_data; if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0799 Target Reset rdata failure: rdata x%px\n", @@ -6442,11 +6403,11 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) return FAILED; } pnode = rdata->pnode; - status = fc_block_scsi_eh(cmnd); + status = fc_block_rport(rport); if (status != 0 && status != SUCCESS) return status; - status = lpfc_chk_tgt_mapped(vport, cmnd); + status = lpfc_chk_tgt_mapped(vport, rport); if (status == FAILED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0722 Target Reset rport failure: rdata x%px\n", rdata); @@ -6470,7 +6431,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, + status = lpfc_send_taskmgmt(vport, rport, tgt_id, lun_id, FCP_TARGET_RESET); if (status != SUCCESS) { logit = LOG_TRACE_EVENT; @@ -6529,95 +6490,6 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) } /** - * lpfc_bus_reset_handler - scsi_host_template eh_bus_reset_handler entry point - * @cmnd: Pointer to scsi_cmnd data structure. - * - * This routine does target reset to all targets on @cmnd->device->host. - * This emulates Parallel SCSI Bus Reset Semantics. - * - * Return code : - * 0x2003 - Error - * 0x2002 - Success - **/ -static int -lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) -{ - struct Scsi_Host *shost = cmnd->device->host; - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_nodelist *ndlp = NULL; - struct lpfc_scsi_event_header scsi_event; - int match; - int ret = SUCCESS, status, i; - u32 logit = LOG_FCP; - - scsi_event.event_type = FC_REG_SCSI_EVENT; - scsi_event.subcategory = LPFC_EVENT_BUSRESET; - scsi_event.lun = 0; - memcpy(scsi_event.wwpn, &vport->fc_portname, sizeof(struct lpfc_name)); - memcpy(scsi_event.wwnn, &vport->fc_nodename, sizeof(struct lpfc_name)); - - fc_host_post_vendor_event(shost, fc_get_event_number(), - sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - - status = fc_block_scsi_eh(cmnd); - if (status != 0 && status != SUCCESS) - return status; - - /* - * Since the driver manages a single bus device, reset all - * targets known to the driver. Should any target reset - * fail, this routine returns failure to the midlayer. - */ - for (i = 0; i < LPFC_MAX_TARGET; i++) { - /* Search for mapped node by target ID */ - match = 0; - spin_lock_irq(shost->host_lock); - list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - - if (vport->phba->cfg_fcp2_no_tgt_reset && - (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) - continue; - if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && - ndlp->nlp_sid == i && - ndlp->rport && - ndlp->nlp_type & NLP_FCP_TARGET) { - match = 1; - break; - } - } - spin_unlock_irq(shost->host_lock); - if (!match) - continue; - - status = lpfc_send_taskmgmt(vport, cmnd, - i, 0, FCP_TARGET_RESET); - - if (status != SUCCESS) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "0700 Bus Reset on target %d failed\n", - i); - ret = FAILED; - } - } - /* - * We have to clean up i/o as : they may be orphaned by the TMFs - * above; or if any of the TMFs failed, they may be in an - * indeterminate state. - * We will report success if all the i/o aborts successfully. - */ - - status = lpfc_reset_flush_io_context(vport, 0, 0, LPFC_CTX_HOST); - if (status != SUCCESS) - ret = FAILED; - if (ret == FAILED) - logit = LOG_TRACE_EVENT; - - lpfc_printf_vlog(vport, KERN_ERR, logit, - "0714 SCSI layer issued Bus Reset Data: x%x\n", ret); - return ret; -} - -/** * lpfc_host_reset_handler - scsi_host_template eh_host_reset_handler entry pt * @cmnd: Pointer to scsi_cmnd data structure. * @@ -7183,12 +7055,6 @@ lpfc_no_command(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) } static int -lpfc_no_handler(struct scsi_cmnd *cmnd) -{ - return FAILED; -} - -static int lpfc_no_slave(struct scsi_device *sdev) { return -ENODEV; @@ -7200,11 +7066,6 @@ struct scsi_host_template lpfc_template_nvme = { .proc_name = LPFC_DRIVER_NAME, .info = lpfc_info, .queuecommand = lpfc_no_command, - .eh_abort_handler = lpfc_no_handler, - .eh_device_reset_handler = lpfc_no_handler, - .eh_target_reset_handler = lpfc_no_handler, - .eh_bus_reset_handler = lpfc_no_handler, - .eh_host_reset_handler = lpfc_no_handler, .slave_alloc = lpfc_no_slave, .slave_configure = lpfc_no_slave, .scan_finished = lpfc_scan_finished, @@ -7228,7 +7089,6 @@ struct scsi_host_template lpfc_template = { .eh_abort_handler = lpfc_abort_handler, .eh_device_reset_handler = lpfc_device_reset_handler, .eh_target_reset_handler = lpfc_target_reset_handler, - .eh_bus_reset_handler = lpfc_bus_reset_handler, .eh_host_reset_handler = lpfc_host_reset_handler, .slave_alloc = lpfc_slave_alloc, .slave_configure = lpfc_slave_configure, diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 430abebf99f1..20d40957a385 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -70,8 +70,9 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, uint8_t *, uint32_t *); -static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *, - struct lpfc_iocbq *); +static struct lpfc_iocbq * +lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, + struct lpfc_iocbq *rspiocbq); static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, struct hbq_dmabuf *); static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, @@ -89,17 +90,14 @@ static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q); static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe); +static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, + struct lpfc_iocbq *pwqeq, + struct lpfc_sglq *sglq); union lpfc_wqe128 lpfc_iread_cmd_template; union lpfc_wqe128 lpfc_iwrite_cmd_template; union lpfc_wqe128 lpfc_icmnd_cmd_template; -static IOCB_t * -lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) -{ - return &iocbq->iocb; -} - /* Setup WQE templates for IOs */ void lpfc_wqe_cmd_template(void) { @@ -1251,24 +1249,19 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) struct lpfc_sglq *start_sglq = NULL; struct lpfc_io_buf *lpfc_cmd; struct lpfc_nodelist *ndlp; - struct lpfc_sli_ring *pring = NULL; int found = 0; + u8 cmnd; - if (piocbq->iocb_flag & LPFC_IO_NVME_LS) - pring = phba->sli4_hba.nvmels_wq->pring; - else - pring = lpfc_phba_elsring(phba); - - lockdep_assert_held(&pring->ring_lock); + cmnd = get_job_cmnd(phba, piocbq); - if (piocbq->iocb_flag & LPFC_IO_FCP) { + if (piocbq->cmd_flag & LPFC_IO_FCP) { lpfc_cmd = (struct lpfc_io_buf *) piocbq->context1; ndlp = lpfc_cmd->rdata->pnode; - } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && - !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) { + } else if ((cmnd == CMD_GEN_REQUEST64_CR) && + !(piocbq->cmd_flag & LPFC_IO_LIBDFC)) { ndlp = piocbq->context_un.ndlp; - } else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) { - if (piocbq->iocb_flag & LPFC_IO_LOOPBACK) + } else if (piocbq->cmd_flag & LPFC_IO_LIBDFC) { + if (piocbq->cmd_flag & LPFC_IO_LOOPBACK) ndlp = NULL; else ndlp = piocbq->context_un.ndlp; @@ -1391,7 +1384,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) if (sglq) { - if (iocbq->iocb_flag & LPFC_IO_NVMET) { + if (iocbq->cmd_flag & LPFC_IO_NVMET) { spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, iflag); sglq->state = SGL_FREED; @@ -1403,7 +1396,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) goto out; } - if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && + if ((iocbq->cmd_flag & LPFC_EXCHANGE_BUSY) && (!(unlikely(pci_channel_offline(phba->pcidev)))) && sglq->state != SGL_XRI_ABORTED) { spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, @@ -1440,7 +1433,7 @@ out: memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); iocbq->sli4_lxritag = NO_XRI; iocbq->sli4_xritag = NO_XRI; - iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | + iocbq->cmd_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | LPFC_IO_NVME_LS); list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); } @@ -1530,17 +1523,21 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, while (!list_empty(iocblist)) { list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); - if (piocb->wqe_cmpl) { - if (piocb->iocb_flag & LPFC_IO_NVME) + if (piocb->cmd_cmpl) { + if (piocb->cmd_flag & LPFC_IO_NVME) { lpfc_nvme_cancel_iocb(phba, piocb, ulpstatus, ulpWord4); - else - lpfc_sli_release_iocbq(phba, piocb); - - } else if (piocb->iocb_cmpl) { - piocb->iocb.ulpStatus = ulpstatus; - piocb->iocb.un.ulpWord[4] = ulpWord4; - (piocb->iocb_cmpl) (phba, piocb, piocb); + } else { + if (phba->sli_rev == LPFC_SLI_REV4) { + bf_set(lpfc_wcqe_c_status, + &piocb->wcqe_cmpl, ulpstatus); + piocb->wcqe_cmpl.parameter = ulpWord4; + } else { + piocb->iocb.ulpStatus = ulpstatus; + piocb->iocb.un.ulpWord[4] = ulpWord4; + } + (piocb->cmd_cmpl) (phba, piocb, piocb); + } } else { lpfc_sli_release_iocbq(phba, piocb); } @@ -1724,20 +1721,18 @@ static int lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb) { - if (phba->sli_rev == LPFC_SLI_REV4) - lockdep_assert_held(&pring->ring_lock); - else - lockdep_assert_held(&phba->hbalock); + u32 ulp_command = 0; BUG_ON(!piocb); + ulp_command = get_job_cmnd(phba, piocb); list_add_tail(&piocb->list, &pring->txcmplq); - piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ; + piocb->cmd_flag |= LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt++; - if ((unlikely(pring->ringno == LPFC_ELS_RING)) && - (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && - (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { + (ulp_command != CMD_ABORT_XRI_WQE) && + (ulp_command != CMD_ABORT_XRI_CN) && + (ulp_command != CMD_CLOSE_XRI_CN)) { BUG_ON(!piocb->vport); if (!(piocb->vport->load_flag & FC_UNLOADING)) mod_timer(&piocb->vport->els_tmofunc, @@ -1773,7 +1768,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. - * @cmf_cmpl: Pointer to completed WCQE. + * @rspiocb: Pointer to driver response iocb object. * * This routine will inform the driver of any BW adjustments we need * to make. These changes will be picked up during the next CMF @@ -1782,10 +1777,11 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) **/ static void lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_wcqe_complete *cmf_cmpl) + struct lpfc_iocbq *rspiocb) { union lpfc_wqe128 *wqe; uint32_t status, info; + struct lpfc_wcqe_complete *wcqe = &rspiocb->wcqe_cmpl; uint64_t bw, bwdif, slop; uint64_t pcent, bwpcent; int asig, afpin, sigcnt, fpincnt; @@ -1793,22 +1789,22 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, char *s; /* First check for error */ - status = bf_get(lpfc_wcqe_c_status, cmf_cmpl); + status = bf_get(lpfc_wcqe_c_status, wcqe); if (status) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "6211 CMF_SYNC_WQE Error " "req_tag x%x status x%x hwstatus x%x " "tdatap x%x parm x%x\n", - bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl), - bf_get(lpfc_wcqe_c_status, cmf_cmpl), - bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl), - cmf_cmpl->total_data_placed, - cmf_cmpl->parameter); + bf_get(lpfc_wcqe_c_request_tag, wcqe), + bf_get(lpfc_wcqe_c_status, wcqe), + bf_get(lpfc_wcqe_c_hw_status, wcqe), + wcqe->total_data_placed, + wcqe->parameter); goto out; } /* Gather congestion information on a successful cmpl */ - info = cmf_cmpl->parameter; + info = wcqe->parameter; phba->cmf_active_info = info; /* See if firmware info count is valid or has changed */ @@ -1817,15 +1813,15 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else phba->cmf_info_per_interval = info; - tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl); - cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl); + tdp = bf_get(lpfc_wcqe_c_cmf_bw, wcqe); + cg = bf_get(lpfc_wcqe_c_cmf_cg, wcqe); /* Get BW requirement from firmware */ bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE; if (!bw) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "6212 CMF_SYNC_WQE x%x: NULL bw\n", - bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl)); + bf_get(lpfc_wcqe_c_request_tag, wcqe)); goto out; } @@ -1999,14 +1995,13 @@ initpath: bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT); sync_buf->vport = phba->pport; - sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl; - sync_buf->iocb_cmpl = NULL; + sync_buf->cmd_cmpl = lpfc_cmf_sync_cmpl; sync_buf->context1 = NULL; sync_buf->context2 = NULL; sync_buf->context3 = NULL; sync_buf->sli4_xritag = NO_XRI; - sync_buf->iocb_flag |= LPFC_IO_CMF; + sync_buf->cmd_flag |= LPFC_IO_CMF; ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf); if (ret_val) lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, @@ -2173,7 +2168,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* * Set up an iotag */ - nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0; + nextiocb->iocb.ulpIoTag = (nextiocb->cmd_cmpl) ? nextiocb->iotag : 0; if (pring->ringno == LPFC_ELS_RING) { @@ -2194,9 +2189,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* * If there is no completion routine to call, we can release the * IOCB buffer back right now. For IOCBs, like QUE_RING_BUF, - * that have no rsp ring completion, iocb_cmpl MUST be NULL. + * that have no rsp ring completion, cmd_cmpl MUST be NULL. */ - if (nextiocb->iocb_cmpl) + if (nextiocb->cmd_cmpl) lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb); else __lpfc_sli_release_iocbq(phba, nextiocb); @@ -3359,6 +3354,56 @@ lpfc_complete_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, return 0; } +static void +lpfc_sli_prep_unsol_wqe(struct lpfc_hba *phba, + struct lpfc_iocbq *saveq) +{ + IOCB_t *irsp; + union lpfc_wqe128 *wqe; + u16 i = 0; + + irsp = &saveq->iocb; + wqe = &saveq->wqe; + + /* Fill wcqe with the IOCB status fields */ + bf_set(lpfc_wcqe_c_status, &saveq->wcqe_cmpl, irsp->ulpStatus); + saveq->wcqe_cmpl.word3 = irsp->ulpBdeCount; + saveq->wcqe_cmpl.parameter = irsp->un.ulpWord[4]; + saveq->wcqe_cmpl.total_data_placed = irsp->unsli3.rcvsli3.acc_len; + + /* Source ID */ + bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, irsp->un.rcvels.parmRo); + + /* rx-id of the response frame */ + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, irsp->ulpContext); + + /* ox-id of the frame */ + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + irsp->unsli3.rcvsli3.ox_id); + + /* DID */ + bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, + irsp->un.rcvels.remoteID); + + /* unsol data len */ + for (i = 0; i < irsp->ulpBdeCount; i++) { + struct lpfc_hbq_entry *hbqe = NULL; + + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { + if (i == 0) { + hbqe = (struct lpfc_hbq_entry *) + &irsp->un.ulpWord[0]; + saveq->wqe.gen_req.bde.tus.f.bdeSize = + hbqe->bde.tus.f.bdeSize; + } else if (i == 1) { + hbqe = (struct lpfc_hbq_entry *) + &irsp->unsli3.sli3Words[4]; + saveq->unsol_rcv_len = hbqe->bde.tus.f.bdeSize; + } + } + } +} + /** * lpfc_sli_process_unsol_iocb - Unsolicited iocb handler * @phba: Pointer to HBA context object. @@ -3379,11 +3424,13 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { IOCB_t * irsp; WORD5 * w5p; + dma_addr_t paddr; uint32_t Rctl, Type; struct lpfc_iocbq *iocbq; struct lpfc_dmabuf *dmzbuf; - irsp = &(saveq->iocb); + irsp = &saveq->iocb; + saveq->vport = phba->pport; if (irsp->ulpCommand == CMD_ASYNC_STATUS) { if (pring->lpfc_sli_rcv_async_status) @@ -3401,22 +3448,22 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } if ((irsp->ulpCommand == CMD_IOCB_RET_XRI64_CX) && - (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) { + (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) { if (irsp->ulpBdeCount > 0) { dmzbuf = lpfc_sli_get_buff(phba, pring, - irsp->un.ulpWord[3]); + irsp->un.ulpWord[3]); lpfc_in_buf_free(phba, dmzbuf); } if (irsp->ulpBdeCount > 1) { dmzbuf = lpfc_sli_get_buff(phba, pring, - irsp->unsli3.sli3Words[3]); + irsp->unsli3.sli3Words[3]); lpfc_in_buf_free(phba, dmzbuf); } if (irsp->ulpBdeCount > 2) { dmzbuf = lpfc_sli_get_buff(phba, pring, - irsp->unsli3.sli3Words[7]); + irsp->unsli3.sli3Words[7]); lpfc_in_buf_free(phba, dmzbuf); } @@ -3449,9 +3496,10 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, irsp->unsli3.sli3Words[7]); } list_for_each_entry(iocbq, &saveq->list, list) { - irsp = &(iocbq->iocb); + irsp = &iocbq->iocb; if (irsp->ulpBdeCount != 0) { - iocbq->context2 = lpfc_sli_get_buff(phba, pring, + iocbq->context2 = lpfc_sli_get_buff(phba, + pring, irsp->un.ulpWord[3]); if (!iocbq->context2) lpfc_printf_log(phba, @@ -3463,7 +3511,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, irsp->un.ulpWord[3]); } if (irsp->ulpBdeCount == 2) { - iocbq->context3 = lpfc_sli_get_buff(phba, pring, + iocbq->context3 = lpfc_sli_get_buff(phba, + pring, irsp->unsli3.sli3Words[7]); if (!iocbq->context3) lpfc_printf_log(phba, @@ -3476,7 +3525,20 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, irsp->unsli3.sli3Words[7]); } } + } else { + paddr = getPaddr(irsp->un.cont64[0].addrHigh, + irsp->un.cont64[0].addrLow); + saveq->context2 = lpfc_sli_ringpostbuf_get(phba, pring, + paddr); + if (irsp->ulpBdeCount == 2) { + paddr = getPaddr(irsp->un.cont64[1].addrHigh, + irsp->un.cont64[1].addrLow); + saveq->context3 = lpfc_sli_ringpostbuf_get(phba, + pring, + paddr); + } } + if (irsp->ulpBdeCount != 0 && (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX || irsp->ulpStatus == IOSTAT_INTERMED_RSP)) { @@ -3494,12 +3556,14 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (!found) list_add_tail(&saveq->clist, &pring->iocb_continue_saveq); + if (saveq->iocb.ulpStatus != IOSTAT_INTERMED_RSP) { list_del_init(&iocbq->clist); saveq = iocbq; - irsp = &(saveq->iocb); - } else + irsp = &saveq->iocb; + } else { return 0; + } } if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) || @@ -3522,6 +3586,19 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } } + if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && + (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX || + irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { + if (irsp->unsli3.rcvsli3.vpi == 0xffff) + saveq->vport = phba->pport; + else + saveq->vport = lpfc_find_vport_by_vpid(phba, + irsp->unsli3.rcvsli3.vpi); + } + + /* Prepare WQE with Unsol frame */ + lpfc_sli_prep_unsol_wqe(phba, saveq); + if (!lpfc_complete_unsol_iocb(phba, pring, saveq, Rctl, Type)) lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0313 Ring %d handler: unexpected Rctl x%x " @@ -3550,36 +3627,28 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, struct lpfc_iocbq *prspiocb) { struct lpfc_iocbq *cmd_iocb = NULL; - uint16_t iotag; - spinlock_t *temp_lock = NULL; - unsigned long iflag = 0; + u16 iotag; if (phba->sli_rev == LPFC_SLI_REV4) - temp_lock = &pring->ring_lock; + iotag = get_wqe_reqtag(prspiocb); else - temp_lock = &phba->hbalock; - - spin_lock_irqsave(temp_lock, iflag); - iotag = prspiocb->iocb.ulpIoTag; + iotag = prspiocb->iocb.ulpIoTag; if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; - if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { + if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { /* remove from txcmpl queue list */ list_del_init(&cmd_iocb->list); - cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; - spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; } } - spin_unlock_irqrestore(temp_lock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0317 iotag x%x is out of " - "range: max iotag x%x wd0 x%x\n", - iotag, phba->sli.last_iotag, - *(((uint32_t *) &prspiocb->iocb) + 7)); + "range: max iotag x%x\n", + iotag, phba->sli.last_iotag); return NULL; } @@ -3600,33 +3669,23 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint16_t iotag) { struct lpfc_iocbq *cmd_iocb = NULL; - spinlock_t *temp_lock = NULL; - unsigned long iflag = 0; - - if (phba->sli_rev == LPFC_SLI_REV4) - temp_lock = &pring->ring_lock; - else - temp_lock = &phba->hbalock; - spin_lock_irqsave(temp_lock, iflag); if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; - if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { + if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { /* remove from txcmpl queue list */ list_del_init(&cmd_iocb->list); - cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; - spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; } } - spin_unlock_irqrestore(temp_lock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0372 iotag x%x lookup error: max iotag (x%x) " - "iocb_flag x%x\n", + "cmd_flag x%x\n", iotag, phba->sli.last_iotag, - cmd_iocb ? cmd_iocb->iocb_flag : 0xffff); + cmd_iocb ? cmd_iocb->cmd_flag : 0xffff); return NULL; } @@ -3654,18 +3713,29 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *cmdiocbp; int rc = 1; unsigned long iflag; + u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag; cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); + + ulp_command = get_job_cmnd(phba, saveq); + ulp_status = get_job_ulpstatus(phba, saveq); + ulp_word4 = get_job_word4(phba, saveq); + ulp_context = get_job_ulpcontext(phba, saveq); + if (phba->sli_rev == LPFC_SLI_REV4) + iotag = get_wqe_reqtag(saveq); + else + iotag = saveq->iocb.ulpIoTag; + if (cmdiocbp) { - if (cmdiocbp->iocb_cmpl) { + ulp_command = get_job_cmnd(phba, cmdiocbp); + if (cmdiocbp->cmd_cmpl) { /* * If an ELS command failed send an event to mgmt * application. */ - if (saveq->iocb.ulpStatus && + if (ulp_status && (pring->ringno == LPFC_ELS_RING) && - (cmdiocbp->iocb.ulpCommand == - CMD_ELS_REQUEST64_CR)) + (ulp_command == CMD_ELS_REQUEST64_CR)) lpfc_send_els_failure_event(phba, cmdiocbp, saveq); @@ -3675,11 +3745,11 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ if (pring->ringno == LPFC_ELS_RING) { if ((phba->sli_rev < LPFC_SLI_REV4) && - (cmdiocbp->iocb_flag & + (cmdiocbp->cmd_flag & LPFC_DRIVER_ABORTED)) { spin_lock_irqsave(&phba->hbalock, iflag); - cmdiocbp->iocb_flag &= + cmdiocbp->cmd_flag &= ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -3694,12 +3764,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ spin_lock_irqsave(&phba->hbalock, iflag); - saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; + saveq->cmd_flag |= LPFC_DELAY_MEM_FREE; spin_unlock_irqrestore(&phba->hbalock, iflag); } if (phba->sli_rev == LPFC_SLI_REV4) { - if (saveq->iocb_flag & + if (saveq->cmd_flag & LPFC_EXCHANGE_BUSY) { /* Set cmdiocb flag for the * exchange busy so sgl (xri) @@ -3709,12 +3779,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ spin_lock_irqsave( &phba->hbalock, iflag); - cmdiocbp->iocb_flag |= + cmdiocbp->cmd_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore( &phba->hbalock, iflag); } - if (cmdiocbp->iocb_flag & + if (cmdiocbp->cmd_flag & LPFC_DRIVER_ABORTED) { /* * Clear LPFC_DRIVER_ABORTED @@ -3723,34 +3793,34 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ spin_lock_irqsave( &phba->hbalock, iflag); - cmdiocbp->iocb_flag &= + cmdiocbp->cmd_flag &= ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore( &phba->hbalock, iflag); - cmdiocbp->iocb.ulpStatus = - IOSTAT_LOCAL_REJECT; - cmdiocbp->iocb.un.ulpWord[4] = - IOERR_ABORT_REQUESTED; + set_job_ulpstatus(cmdiocbp, + IOSTAT_LOCAL_REJECT); + set_job_ulpword4(cmdiocbp, + IOERR_ABORT_REQUESTED); /* * For SLI4, irsiocb contains * NO_XRI in sli_xritag, it * shall not affect releasing * sgl (xri) process. */ - saveq->iocb.ulpStatus = - IOSTAT_LOCAL_REJECT; - saveq->iocb.un.ulpWord[4] = - IOERR_SLI_ABORTED; + set_job_ulpstatus(saveq, + IOSTAT_LOCAL_REJECT); + set_job_ulpword4(saveq, + IOERR_SLI_ABORTED); spin_lock_irqsave( &phba->hbalock, iflag); - saveq->iocb_flag |= + saveq->cmd_flag |= LPFC_DELAY_MEM_FREE; spin_unlock_irqrestore( &phba->hbalock, iflag); } } } - (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); + (cmdiocbp->cmd_cmpl) (phba, cmdiocbp, saveq); } else lpfc_sli_release_iocbq(phba, cmdiocbp); } else { @@ -3768,12 +3838,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, "0322 Ring %d handler: " "unexpected completion IoTag x%x " "Data: x%x x%x x%x x%x\n", - pring->ringno, - saveq->iocb.ulpIoTag, - saveq->iocb.ulpStatus, - saveq->iocb.un.ulpWord[4], - saveq->iocb.ulpCommand, - saveq->iocb.ulpContext); + pring->ringno, iotag, ulp_status, + ulp_word4, ulp_command, ulp_context); } } @@ -3992,11 +4058,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, spin_lock_irqsave(&phba->hbalock, iflag); if (unlikely(!cmdiocbq)) break; - if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) - cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; - if (cmdiocbq->iocb_cmpl) { + if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) + cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; + if (cmdiocbq->cmd_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, &rspiocbq); spin_lock_irqsave(&phba->hbalock, iflag); } @@ -4088,155 +4154,159 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *rspiocbp) { struct lpfc_iocbq *saveq; - struct lpfc_iocbq *cmdiocbp; + struct lpfc_iocbq *cmdiocb; struct lpfc_iocbq *next_iocb; - IOCB_t *irsp = NULL; + IOCB_t *irsp; uint32_t free_saveq; - uint8_t iocb_cmd_type; + u8 cmd_type; lpfc_iocb_type type; unsigned long iflag; + u32 ulp_status = get_job_ulpstatus(phba, rspiocbp); + u32 ulp_word4 = get_job_word4(phba, rspiocbp); + u32 ulp_command = get_job_cmnd(phba, rspiocbp); int rc; spin_lock_irqsave(&phba->hbalock, iflag); /* First add the response iocb to the countinueq list */ - list_add_tail(&rspiocbp->list, &(pring->iocb_continueq)); + list_add_tail(&rspiocbp->list, &pring->iocb_continueq); pring->iocb_continueq_cnt++; - /* Now, determine whether the list is completed for processing */ - irsp = &rspiocbp->iocb; - if (irsp->ulpLe) { - /* - * By default, the driver expects to free all resources - * associated with this iocb completion. - */ - free_saveq = 1; - saveq = list_get_first(&pring->iocb_continueq, - struct lpfc_iocbq, list); - irsp = &(saveq->iocb); - list_del_init(&pring->iocb_continueq); - pring->iocb_continueq_cnt = 0; + /* + * By default, the driver expects to free all resources + * associated with this iocb completion. + */ + free_saveq = 1; + saveq = list_get_first(&pring->iocb_continueq, + struct lpfc_iocbq, list); + list_del_init(&pring->iocb_continueq); + pring->iocb_continueq_cnt = 0; - pring->stats.iocb_rsp++; + pring->stats.iocb_rsp++; - /* - * If resource errors reported from HBA, reduce - * queuedepths of the SCSI device. - */ - if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == - IOERR_NO_RESOURCES)) { - spin_unlock_irqrestore(&phba->hbalock, iflag); - phba->lpfc_rampdown_queue_depth(phba); - spin_lock_irqsave(&phba->hbalock, iflag); - } + /* + * If resource errors reported from HBA, reduce + * queuedepths of the SCSI device. + */ + if (ulp_status == IOSTAT_LOCAL_REJECT && + ((ulp_word4 & IOERR_PARAM_MASK) == + IOERR_NO_RESOURCES)) { + spin_unlock_irqrestore(&phba->hbalock, iflag); + phba->lpfc_rampdown_queue_depth(phba); + spin_lock_irqsave(&phba->hbalock, iflag); + } - if (irsp->ulpStatus) { - /* Rsp ring <ringno> error: IOCB */ + if (ulp_status) { + /* Rsp ring <ringno> error: IOCB */ + if (phba->sli_rev < LPFC_SLI_REV4) { + irsp = &rspiocbp->iocb; + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0328 Rsp Ring %d error: ulp_status x%x " + "IOCB Data: " + "x%08x x%08x x%08x x%08x " + "x%08x x%08x x%08x x%08x " + "x%08x x%08x x%08x x%08x " + "x%08x x%08x x%08x x%08x\n", + pring->ringno, ulp_status, + get_job_ulpword(rspiocbp, 0), + get_job_ulpword(rspiocbp, 1), + get_job_ulpword(rspiocbp, 2), + get_job_ulpword(rspiocbp, 3), + get_job_ulpword(rspiocbp, 4), + get_job_ulpword(rspiocbp, 5), + *(((uint32_t *)irsp) + 6), + *(((uint32_t *)irsp) + 7), + *(((uint32_t *)irsp) + 8), + *(((uint32_t *)irsp) + 9), + *(((uint32_t *)irsp) + 10), + *(((uint32_t *)irsp) + 11), + *(((uint32_t *)irsp) + 12), + *(((uint32_t *)irsp) + 13), + *(((uint32_t *)irsp) + 14), + *(((uint32_t *)irsp) + 15)); + } else { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "0328 Rsp Ring %d error: " + "0321 Rsp Ring %d error: " "IOCB Data: " - "x%x x%x x%x x%x " - "x%x x%x x%x x%x " - "x%x x%x x%x x%x " "x%x x%x x%x x%x\n", pring->ringno, - irsp->un.ulpWord[0], - irsp->un.ulpWord[1], - irsp->un.ulpWord[2], - irsp->un.ulpWord[3], - irsp->un.ulpWord[4], - irsp->un.ulpWord[5], - *(((uint32_t *) irsp) + 6), - *(((uint32_t *) irsp) + 7), - *(((uint32_t *) irsp) + 8), - *(((uint32_t *) irsp) + 9), - *(((uint32_t *) irsp) + 10), - *(((uint32_t *) irsp) + 11), - *(((uint32_t *) irsp) + 12), - *(((uint32_t *) irsp) + 13), - *(((uint32_t *) irsp) + 14), - *(((uint32_t *) irsp) + 15)); + rspiocbp->wcqe_cmpl.word0, + rspiocbp->wcqe_cmpl.total_data_placed, + rspiocbp->wcqe_cmpl.parameter, + rspiocbp->wcqe_cmpl.word3); } + } - /* - * Fetch the IOCB command type and call the correct completion - * routine. Solicited and Unsolicited IOCBs on the ELS ring - * get freed back to the lpfc_iocb_list by the discovery - * kernel thread. - */ - iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; - type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); - switch (type) { - case LPFC_SOL_IOCB: - spin_unlock_irqrestore(&phba->hbalock, iflag); - rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); - spin_lock_irqsave(&phba->hbalock, iflag); - break; - - case LPFC_UNSOL_IOCB: - spin_unlock_irqrestore(&phba->hbalock, iflag); - rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); - spin_lock_irqsave(&phba->hbalock, iflag); - if (!rc) - free_saveq = 0; - break; - case LPFC_ABORT_IOCB: - cmdiocbp = NULL; - if (irsp->ulpCommand != CMD_XRI_ABORTED_CX) { + /* + * Fetch the iocb command type and call the correct completion + * routine. Solicited and Unsolicited IOCBs on the ELS ring + * get freed back to the lpfc_iocb_list by the discovery + * kernel thread. + */ + cmd_type = ulp_command & CMD_IOCB_MASK; + type = lpfc_sli_iocb_cmd_type(cmd_type); + switch (type) { + case LPFC_SOL_IOCB: + spin_unlock_irqrestore(&phba->hbalock, iflag); + rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); + spin_lock_irqsave(&phba->hbalock, iflag); + break; + case LPFC_UNSOL_IOCB: + spin_unlock_irqrestore(&phba->hbalock, iflag); + rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); + spin_lock_irqsave(&phba->hbalock, iflag); + if (!rc) + free_saveq = 0; + break; + case LPFC_ABORT_IOCB: + cmdiocb = NULL; + if (ulp_command != CMD_XRI_ABORTED_CX) + cmdiocb = lpfc_sli_iocbq_lookup(phba, pring, + saveq); + if (cmdiocb) { + /* Call the specified completion routine */ + if (cmdiocb->cmd_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, - saveq); + cmdiocb->cmd_cmpl(phba, cmdiocb, saveq); spin_lock_irqsave(&phba->hbalock, iflag); - } - if (cmdiocbp) { - /* Call the specified completion routine */ - if (cmdiocbp->iocb_cmpl) { - spin_unlock_irqrestore(&phba->hbalock, - iflag); - (cmdiocbp->iocb_cmpl)(phba, cmdiocbp, - saveq); - spin_lock_irqsave(&phba->hbalock, - iflag); - } else - __lpfc_sli_release_iocbq(phba, - cmdiocbp); - } - break; - - case LPFC_UNKNOWN_IOCB: - if (irsp->ulpCommand == CMD_ADAPTER_MSG) { - char adaptermsg[LPFC_MAX_ADPTMSG]; - memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); - memcpy(&adaptermsg[0], (uint8_t *)irsp, - MAX_MSG_DATA); - dev_warn(&((phba->pcidev)->dev), - "lpfc%d: %s\n", - phba->brd_no, adaptermsg); } else { - /* Unknown IOCB command */ - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0335 Unknown IOCB " - "command Data: x%x " - "x%x x%x x%x\n", - irsp->ulpCommand, - irsp->ulpStatus, - irsp->ulpIoTag, - irsp->ulpContext); + __lpfc_sli_release_iocbq(phba, cmdiocb); } - break; } + break; + case LPFC_UNKNOWN_IOCB: + if (ulp_command == CMD_ADAPTER_MSG) { + char adaptermsg[LPFC_MAX_ADPTMSG]; + + memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); + memcpy(&adaptermsg[0], (uint8_t *)&rspiocbp->wqe, + MAX_MSG_DATA); + dev_warn(&((phba->pcidev)->dev), + "lpfc%d: %s\n", + phba->brd_no, adaptermsg); + } else { + /* Unknown command */ + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0335 Unknown IOCB " + "command Data: x%x " + "x%x x%x x%x\n", + ulp_command, + ulp_status, + get_wqe_reqtag(rspiocbp), + get_job_ulpcontext(phba, rspiocbp)); + } + break; + } - if (free_saveq) { - list_for_each_entry_safe(rspiocbp, next_iocb, - &saveq->list, list) { - list_del_init(&rspiocbp->list); - __lpfc_sli_release_iocbq(phba, rspiocbp); - } - __lpfc_sli_release_iocbq(phba, saveq); + if (free_saveq) { + list_for_each_entry_safe(rspiocbp, next_iocb, + &saveq->list, list) { + list_del_init(&rspiocbp->list); + __lpfc_sli_release_iocbq(phba, rspiocbp); } - rspiocbp = NULL; + __lpfc_sli_release_iocbq(phba, saveq); } + rspiocbp = NULL; spin_unlock_irqrestore(&phba->hbalock, iflag); return rspiocbp; } @@ -4429,8 +4499,8 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba, irspiocbq = container_of(cq_event, struct lpfc_iocbq, cq_event); /* Translate ELS WCQE to response IOCBQ */ - irspiocbq = lpfc_sli4_els_wcqe_to_rspiocbq(phba, - irspiocbq); + irspiocbq = lpfc_sli4_els_preprocess_rspiocbq(phba, + irspiocbq); if (irspiocbq) lpfc_sli_sp_handle_rspiocb(phba, pring, irspiocbq); @@ -4573,7 +4643,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) list_splice_init(&pring->txq, &txq); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -4599,7 +4669,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) list_splice_init(&pring->txq, &txq); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -10098,7 +10168,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, lockdep_assert_held(&phba->hbalock); - if (piocb->iocb_cmpl && (!piocb->vport) && + if (piocb->cmd_cmpl && (!piocb->vport) && (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -10150,10 +10220,10 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, case CMD_QUE_RING_BUF64_CN: /* * For IOCBs, like QUE_RING_BUF, that have no rsp ring - * completion, iocb_cmpl MUST be 0. + * completion, cmd_cmpl MUST be 0. */ - if (piocb->iocb_cmpl) - piocb->iocb_cmpl = NULL; + if (piocb->cmd_cmpl) + piocb->cmd_cmpl = NULL; fallthrough; case CMD_CREATE_XRI_CR: case CMD_CLOSE_XRI_CN: @@ -10200,715 +10270,6 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, } /** - * lpfc_sli4_bpl2sgl - Convert the bpl/bde to a sgl. - * @phba: Pointer to HBA context object. - * @piocbq: Pointer to command iocb. - * @sglq: Pointer to the scatter gather queue object. - * - * This routine converts the bpl or bde that is in the IOCB - * to a sgl list for the sli4 hardware. The physical address - * of the bpl/bde is converted back to a virtual address. - * If the IOCB contains a BPL then the list of BDE's is - * converted to sli4_sge's. If the IOCB contains a single - * BDE then it is converted to a single sli_sge. - * The IOCB is still in cpu endianess so the contents of - * the bpl can be used without byte swapping. - * - * Returns valid XRI = Success, NO_XRI = Failure. -**/ -static uint16_t -lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, - struct lpfc_sglq *sglq) -{ - uint16_t xritag = NO_XRI; - struct ulp_bde64 *bpl = NULL; - struct ulp_bde64 bde; - struct sli4_sge *sgl = NULL; - struct lpfc_dmabuf *dmabuf; - IOCB_t *icmd; - int numBdes = 0; - int i = 0; - uint32_t offset = 0; /* accumulated offset in the sg request list */ - int inbound = 0; /* number of sg reply entries inbound from firmware */ - - if (!piocbq || !sglq) - return xritag; - - sgl = (struct sli4_sge *)sglq->sgl; - icmd = &piocbq->iocb; - if (icmd->ulpCommand == CMD_XMIT_BLS_RSP64_CX) - return sglq->sli4_xritag; - if (icmd->un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { - numBdes = icmd->un.genreq64.bdl.bdeSize / - sizeof(struct ulp_bde64); - /* The addrHigh and addrLow fields within the IOCB - * have not been byteswapped yet so there is no - * need to swap them back. - */ - if (piocbq->context3) - dmabuf = (struct lpfc_dmabuf *)piocbq->context3; - else - return xritag; - - bpl = (struct ulp_bde64 *)dmabuf->virt; - if (!bpl) - return xritag; - - for (i = 0; i < numBdes; i++) { - /* Should already be byte swapped. */ - sgl->addr_hi = bpl->addrHigh; - sgl->addr_lo = bpl->addrLow; - - sgl->word2 = le32_to_cpu(sgl->word2); - if ((i+1) == numBdes) - bf_set(lpfc_sli4_sge_last, sgl, 1); - else - bf_set(lpfc_sli4_sge_last, sgl, 0); - /* swap the size field back to the cpu so we - * can assign it to the sgl. - */ - bde.tus.w = le32_to_cpu(bpl->tus.w); - sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize); - /* The offsets in the sgl need to be accumulated - * separately for the request and reply lists. - * The request is always first, the reply follows. - */ - if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) { - /* add up the reply sg entries */ - if (bpl->tus.f.bdeFlags == BUFF_TYPE_BDE_64I) - inbound++; - /* first inbound? reset the offset */ - if (inbound == 1) - offset = 0; - bf_set(lpfc_sli4_sge_offset, sgl, offset); - bf_set(lpfc_sli4_sge_type, sgl, - LPFC_SGE_TYPE_DATA); - offset += bde.tus.f.bdeSize; - } - sgl->word2 = cpu_to_le32(sgl->word2); - bpl++; - sgl++; - } - } else if (icmd->un.genreq64.bdl.bdeFlags == BUFF_TYPE_BDE_64) { - /* The addrHigh and addrLow fields of the BDE have not - * been byteswapped yet so they need to be swapped - * before putting them in the sgl. - */ - sgl->addr_hi = - cpu_to_le32(icmd->un.genreq64.bdl.addrHigh); - sgl->addr_lo = - cpu_to_le32(icmd->un.genreq64.bdl.addrLow); - sgl->word2 = le32_to_cpu(sgl->word2); - bf_set(lpfc_sli4_sge_last, sgl, 1); - sgl->word2 = cpu_to_le32(sgl->word2); - sgl->sge_len = - cpu_to_le32(icmd->un.genreq64.bdl.bdeSize); - } - return sglq->sli4_xritag; -} - -/** - * lpfc_sli4_iocb2wqe - Convert the IOCB to a work queue entry. - * @phba: Pointer to HBA context object. - * @iocbq: Pointer to command iocb. - * @wqe: Pointer to the work queue entry. - * - * This routine converts the iocb command to its Work Queue Entry - * equivalent. The wqe pointer should not have any fields set when - * this routine is called because it will memcpy over them. - * This routine does not set the CQ_ID or the WQEC bits in the - * wqe. - * - * Returns: 0 = Success, IOCB_ERROR = Failure. - **/ -static int -lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, - union lpfc_wqe128 *wqe) -{ - uint32_t xmit_len = 0, total_len = 0; - uint8_t ct = 0; - uint32_t fip; - uint32_t abort_tag; - uint8_t command_type = ELS_COMMAND_NON_FIP; - uint8_t cmnd; - uint16_t xritag; - uint16_t abrt_iotag; - struct lpfc_iocbq *abrtiocbq; - struct ulp_bde64 *bpl = NULL; - uint32_t els_id = LPFC_ELS_ID_DEFAULT; - int numBdes, i; - struct ulp_bde64 bde; - struct lpfc_nodelist *ndlp; - uint32_t *pcmd; - uint32_t if_type; - - fip = phba->hba_flag & HBA_FIP_SUPPORT; - /* The fcp commands will set command type */ - if (iocbq->iocb_flag & LPFC_IO_FCP) - command_type = FCP_COMMAND; - else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)) - command_type = ELS_COMMAND_FIP; - else - command_type = ELS_COMMAND_NON_FIP; - - if (phba->fcp_embed_io) - memset(wqe, 0, sizeof(union lpfc_wqe128)); - /* Some of the fields are in the right position already */ - memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); - /* The ct field has moved so reset */ - wqe->generic.wqe_com.word7 = 0; - wqe->generic.wqe_com.word10 = 0; - - abort_tag = (uint32_t) iocbq->iotag; - xritag = iocbq->sli4_xritag; - /* words0-2 bpl convert bde */ - if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { - numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / - sizeof(struct ulp_bde64); - bpl = (struct ulp_bde64 *) - ((struct lpfc_dmabuf *)iocbq->context3)->virt; - if (!bpl) - return IOCB_ERROR; - - /* Should already be byte swapped. */ - wqe->generic.bde.addrHigh = le32_to_cpu(bpl->addrHigh); - wqe->generic.bde.addrLow = le32_to_cpu(bpl->addrLow); - /* swap the size field back to the cpu so we - * can assign it to the sgl. - */ - wqe->generic.bde.tus.w = le32_to_cpu(bpl->tus.w); - xmit_len = wqe->generic.bde.tus.f.bdeSize; - total_len = 0; - for (i = 0; i < numBdes; i++) { - bde.tus.w = le32_to_cpu(bpl[i].tus.w); - total_len += bde.tus.f.bdeSize; - } - } else - xmit_len = iocbq->iocb.un.fcpi64.bdl.bdeSize; - - iocbq->iocb.ulpIoTag = iocbq->iotag; - cmnd = iocbq->iocb.ulpCommand; - - switch (iocbq->iocb.ulpCommand) { - case CMD_ELS_REQUEST64_CR: - if (iocbq->iocb_flag & LPFC_IO_LIBDFC) - ndlp = iocbq->context_un.ndlp; - else - ndlp = (struct lpfc_nodelist *)iocbq->context1; - if (!iocbq->iocb.ulpLe) { - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "2007 Only Limited Edition cmd Format" - " supported 0x%x\n", - iocbq->iocb.ulpCommand); - return IOCB_ERROR; - } - - wqe->els_req.payload_len = xmit_len; - /* Els_reguest64 has a TMO */ - bf_set(wqe_tmo, &wqe->els_req.wqe_com, - iocbq->iocb.ulpTimeout); - /* Need a VF for word 4 set the vf bit*/ - bf_set(els_req64_vf, &wqe->els_req, 0); - /* And a VFID for word 12 */ - bf_set(els_req64_vfid, &wqe->els_req, 0); - ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); - bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, - iocbq->iocb.ulpContext); - bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); - bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); - /* CCP CCPE PV PRI in word10 were set in the memcpy */ - if (command_type == ELS_COMMAND_FIP) - els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) - >> LPFC_FIP_ELS_ID_SHIFT); - pcmd = (uint32_t *) (((struct lpfc_dmabuf *) - iocbq->context2)->virt); - if_type = bf_get(lpfc_sli_intf_if_type, - &phba->sli4_hba.sli_intf); - if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { - if (pcmd && (*pcmd == ELS_CMD_FLOGI || - *pcmd == ELS_CMD_SCR || - *pcmd == ELS_CMD_RDF || - *pcmd == ELS_CMD_EDC || - *pcmd == ELS_CMD_RSCN_XMT || - *pcmd == ELS_CMD_FDISC || - *pcmd == ELS_CMD_LOGO || - *pcmd == ELS_CMD_QFPA || - *pcmd == ELS_CMD_UVEM || - *pcmd == ELS_CMD_PLOGI)) { - bf_set(els_req64_sp, &wqe->els_req, 1); - bf_set(els_req64_sid, &wqe->els_req, - iocbq->vport->fc_myDID); - if ((*pcmd == ELS_CMD_FLOGI) && - !(phba->fc_topology == - LPFC_TOPOLOGY_LOOP)) - bf_set(els_req64_sid, &wqe->els_req, 0); - bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); - bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, - phba->vpi_ids[iocbq->vport->vpi]); - } else if (pcmd && iocbq->context1) { - bf_set(wqe_ct, &wqe->els_req.wqe_com, 0); - bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); - } - } - bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); - bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); - bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); - bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); - bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); - bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); - wqe->els_req.max_response_payload_len = total_len - xmit_len; - break; - case CMD_XMIT_SEQUENCE64_CX: - bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, - iocbq->iocb.un.ulpWord[3]); - bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, - iocbq->iocb.unsli3.rcvsli3.ox_id); - /* The entire sequence is transmitted for this IOCB */ - xmit_len = total_len; - cmnd = CMD_XMIT_SEQUENCE64_CR; - if (phba->link_flag & LS_LOOPBACK_MODE) - bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1); - fallthrough; - case CMD_XMIT_SEQUENCE64_CR: - /* word3 iocb=io_tag32 wqe=reserved */ - wqe->xmit_sequence.rsvd3 = 0; - /* word4 relative_offset memcpy */ - /* word5 r_ctl/df_ctl memcpy */ - bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0); - bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1); - bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com, - LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com, - LPFC_WQE_LENLOC_WORD12); - bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0); - wqe->xmit_sequence.xmit_len = xmit_len; - command_type = OTHER_COMMAND; - break; - case CMD_XMIT_BCAST64_CN: - /* word3 iocb=iotag32 wqe=seq_payload_len */ - wqe->xmit_bcast64.seq_payload_len = xmit_len; - /* word4 iocb=rsvd wqe=rsvd */ - /* word5 iocb=rctl/type/df_ctl wqe=rctl/type/df_ctl memcpy */ - /* word6 iocb=ctxt_tag/io_tag wqe=ctxt_tag/xri */ - bf_set(wqe_ct, &wqe->xmit_bcast64.wqe_com, - ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); - bf_set(wqe_dbde, &wqe->xmit_bcast64.wqe_com, 1); - bf_set(wqe_iod, &wqe->xmit_bcast64.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->xmit_bcast64.wqe_com, - LPFC_WQE_LENLOC_WORD3); - bf_set(wqe_ebde_cnt, &wqe->xmit_bcast64.wqe_com, 0); - break; - case CMD_FCP_IWRITE64_CR: - command_type = FCP_COMMAND_DATA_OUT; - /* word3 iocb=iotag wqe=payload_offset_len */ - /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ - bf_set(payload_offset_len, &wqe->fcp_iwrite, - xmit_len + sizeof(struct fcp_rsp)); - bf_set(cmd_buff_len, &wqe->fcp_iwrite, - 0); - /* word4 iocb=parameter wqe=total_xfer_length memcpy */ - /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ - bf_set(wqe_erp, &wqe->fcp_iwrite.wqe_com, - iocbq->iocb.ulpFCP2Rcvy); - bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS); - /* Always open the exchange */ - bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, - LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); - bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); - if (iocbq->iocb_flag & LPFC_IO_OAS) { - bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1); - bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); - if (iocbq->priority) { - bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com, - (iocbq->priority << 1)); - } else { - bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com, - (phba->cfg_XLanePriority << 1)); - } - } - /* Note, word 10 is already initialized to 0 */ - - /* Don't set PBDE for Perf hints, just lpfc_enable_pbde */ - if (phba->cfg_enable_pbde) - bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1); - else - bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0); - - if (phba->fcp_embed_io) { - struct lpfc_io_buf *lpfc_cmd; - struct sli4_sge *sgl; - struct fcp_cmnd *fcp_cmnd; - uint32_t *ptr; - - /* 128 byte wqe support here */ - - lpfc_cmd = iocbq->context1; - sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; - fcp_cmnd = lpfc_cmd->fcp_cmnd; - - /* Word 0-2 - FCP_CMND */ - wqe->generic.bde.tus.f.bdeFlags = - BUFF_TYPE_BDE_IMMED; - wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe->generic.bde.addrHigh = 0; - wqe->generic.bde.addrLow = 88; /* Word 22 */ - - bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); - - /* Word 22-29 FCP CMND Payload */ - ptr = &wqe->words[22]; - memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); - } - break; - case CMD_FCP_IREAD64_CR: - /* word3 iocb=iotag wqe=payload_offset_len */ - /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ - bf_set(payload_offset_len, &wqe->fcp_iread, - xmit_len + sizeof(struct fcp_rsp)); - bf_set(cmd_buff_len, &wqe->fcp_iread, - 0); - /* word4 iocb=parameter wqe=total_xfer_length memcpy */ - /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ - bf_set(wqe_erp, &wqe->fcp_iread.wqe_com, - iocbq->iocb.ulpFCP2Rcvy); - bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS); - /* Always open the exchange */ - bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); - bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, - LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); - bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); - if (iocbq->iocb_flag & LPFC_IO_OAS) { - bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1); - bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1); - if (iocbq->priority) { - bf_set(wqe_ccp, &wqe->fcp_iread.wqe_com, - (iocbq->priority << 1)); - } else { - bf_set(wqe_ccp, &wqe->fcp_iread.wqe_com, - (phba->cfg_XLanePriority << 1)); - } - } - /* Note, word 10 is already initialized to 0 */ - - /* Don't set PBDE for Perf hints, just lpfc_enable_pbde */ - if (phba->cfg_enable_pbde) - bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1); - else - bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0); - - if (phba->fcp_embed_io) { - struct lpfc_io_buf *lpfc_cmd; - struct sli4_sge *sgl; - struct fcp_cmnd *fcp_cmnd; - uint32_t *ptr; - - /* 128 byte wqe support here */ - - lpfc_cmd = iocbq->context1; - sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; - fcp_cmnd = lpfc_cmd->fcp_cmnd; - - /* Word 0-2 - FCP_CMND */ - wqe->generic.bde.tus.f.bdeFlags = - BUFF_TYPE_BDE_IMMED; - wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe->generic.bde.addrHigh = 0; - wqe->generic.bde.addrLow = 88; /* Word 22 */ - - bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); - - /* Word 22-29 FCP CMND Payload */ - ptr = &wqe->words[22]; - memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); - } - break; - case CMD_FCP_ICMND64_CR: - /* word3 iocb=iotag wqe=payload_offset_len */ - /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ - bf_set(payload_offset_len, &wqe->fcp_icmd, - xmit_len + sizeof(struct fcp_rsp)); - bf_set(cmd_buff_len, &wqe->fcp_icmd, - 0); - /* word3 iocb=IO_TAG wqe=reserved */ - bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); - /* Always open the exchange */ - bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, - LPFC_WQE_LENLOC_NONE); - bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, - iocbq->iocb.ulpFCP2Rcvy); - if (iocbq->iocb_flag & LPFC_IO_OAS) { - bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1); - if (iocbq->priority) { - bf_set(wqe_ccp, &wqe->fcp_icmd.wqe_com, - (iocbq->priority << 1)); - } else { - bf_set(wqe_ccp, &wqe->fcp_icmd.wqe_com, - (phba->cfg_XLanePriority << 1)); - } - } - /* Note, word 10 is already initialized to 0 */ - - if (phba->fcp_embed_io) { - struct lpfc_io_buf *lpfc_cmd; - struct sli4_sge *sgl; - struct fcp_cmnd *fcp_cmnd; - uint32_t *ptr; - - /* 128 byte wqe support here */ - - lpfc_cmd = iocbq->context1; - sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; - fcp_cmnd = lpfc_cmd->fcp_cmnd; - - /* Word 0-2 - FCP_CMND */ - wqe->generic.bde.tus.f.bdeFlags = - BUFF_TYPE_BDE_IMMED; - wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe->generic.bde.addrHigh = 0; - wqe->generic.bde.addrLow = 88; /* Word 22 */ - - bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); - - /* Word 22-29 FCP CMND Payload */ - ptr = &wqe->words[22]; - memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); - } - break; - case CMD_GEN_REQUEST64_CR: - /* For this command calculate the xmit length of the - * request bde. - */ - xmit_len = 0; - numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / - sizeof(struct ulp_bde64); - for (i = 0; i < numBdes; i++) { - bde.tus.w = le32_to_cpu(bpl[i].tus.w); - if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) - break; - xmit_len += bde.tus.f.bdeSize; - } - /* word3 iocb=IO_TAG wqe=request_payload_len */ - wqe->gen_req.request_payload_len = xmit_len; - /* word4 iocb=parameter wqe=relative_offset memcpy */ - /* word5 [rctl, type, df_ctl, la] copied in memcpy */ - /* word6 context tag copied in memcpy */ - if (iocbq->iocb.ulpCt_h || iocbq->iocb.ulpCt_l) { - ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "2015 Invalid CT %x command 0x%x\n", - ct, iocbq->iocb.ulpCommand); - return IOCB_ERROR; - } - bf_set(wqe_ct, &wqe->gen_req.wqe_com, 0); - bf_set(wqe_tmo, &wqe->gen_req.wqe_com, iocbq->iocb.ulpTimeout); - bf_set(wqe_pu, &wqe->gen_req.wqe_com, iocbq->iocb.ulpPU); - bf_set(wqe_dbde, &wqe->gen_req.wqe_com, 1); - bf_set(wqe_iod, &wqe->gen_req.wqe_com, LPFC_WQE_IOD_READ); - bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); - bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); - wqe->gen_req.max_response_payload_len = total_len - xmit_len; - command_type = OTHER_COMMAND; - break; - case CMD_XMIT_ELS_RSP64_CX: - ndlp = (struct lpfc_nodelist *)iocbq->context1; - /* words0-2 BDE memcpy */ - /* word3 iocb=iotag32 wqe=response_payload_len */ - wqe->xmit_els_rsp.response_payload_len = xmit_len; - /* word4 */ - wqe->xmit_els_rsp.word4 = 0; - /* word5 iocb=rsvd wge=did */ - bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, - iocbq->iocb.un.xseq64.xmit_els_remoteID); - - if_type = bf_get(lpfc_sli_intf_if_type, - &phba->sli4_hba.sli_intf); - if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { - if (iocbq->vport->fc_flag & FC_PT2PT) { - bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); - bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, - iocbq->vport->fc_myDID); - if (iocbq->vport->fc_myDID == Fabric_DID) { - bf_set(wqe_els_did, - &wqe->xmit_els_rsp.wqe_dest, 0); - } - } - } - bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, - ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); - bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU); - bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, - iocbq->iocb.unsli3.rcvsli3.ox_id); - if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) - bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, - phba->vpi_ids[iocbq->vport->vpi]); - bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); - bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, - LPFC_WQE_LENLOC_WORD3); - bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); - bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); - if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { - bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); - bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, - iocbq->vport->fc_myDID); - bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1); - bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, - phba->vpi_ids[phba->pport->vpi]); - } - command_type = OTHER_COMMAND; - break; - case CMD_CLOSE_XRI_CN: - case CMD_ABORT_XRI_CN: - case CMD_ABORT_XRI_CX: - /* words 0-2 memcpy should be 0 rserved */ - /* port will send abts */ - abrt_iotag = iocbq->iocb.un.acxri.abortContextTag; - if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) { - abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag]; - fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK; - } else - fip = 0; - - if ((iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN) || fip) - /* - * The link is down, or the command was ELS_FIP - * so the fw does not need to send abts - * on the wire. - */ - bf_set(abort_cmd_ia, &wqe->abort_cmd, 1); - else - bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); - bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); - /* word5 iocb=CONTEXT_TAG|IO_TAG wqe=reserved */ - wqe->abort_cmd.rsrvd5 = 0; - bf_set(wqe_ct, &wqe->abort_cmd.wqe_com, - ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); - abort_tag = iocbq->iocb.un.acxri.abortIoTag; - /* - * The abort handler will send us CMD_ABORT_XRI_CN or - * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX - */ - bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); - bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, - LPFC_WQE_LENLOC_NONE); - cmnd = CMD_ABORT_XRI_CX; - command_type = OTHER_COMMAND; - xritag = 0; - break; - case CMD_XMIT_BLS_RSP64_CX: - ndlp = (struct lpfc_nodelist *)iocbq->context1; - /* As BLS ABTS RSP WQE is very different from other WQEs, - * we re-construct this WQE here based on information in - * iocbq from scratch. - */ - memset(wqe, 0, sizeof(*wqe)); - /* OX_ID is invariable to who sent ABTS to CT exchange */ - bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp, - bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_rsp)); - if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_rsp) == - LPFC_ABTS_UNSOL_INT) { - /* ABTS sent by initiator to CT exchange, the - * RX_ID field will be filled with the newly - * allocated responder XRI. - */ - bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, - iocbq->sli4_xritag); - } else { - /* ABTS sent by responder to CT exchange, the - * RX_ID field will be filled with the responder - * RX_ID from ABTS. - */ - bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, - bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_rsp)); - } - bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); - bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); - - /* Use CT=VPI */ - bf_set(wqe_els_did, &wqe->xmit_bls_rsp.wqe_dest, - ndlp->nlp_DID); - bf_set(xmit_bls_rsp64_temprpi, &wqe->xmit_bls_rsp, - iocbq->iocb.ulpContext); - bf_set(wqe_ct, &wqe->xmit_bls_rsp.wqe_com, 1); - bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, - phba->vpi_ids[phba->pport->vpi]); - bf_set(wqe_qosd, &wqe->xmit_bls_rsp.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com, - LPFC_WQE_LENLOC_NONE); - /* Overwrite the pre-set comnd type with OTHER_COMMAND */ - command_type = OTHER_COMMAND; - if (iocbq->iocb.un.xseq64.w5.hcsw.Rctl == FC_RCTL_BA_RJT) { - bf_set(xmit_bls_rsp64_rjt_vspec, &wqe->xmit_bls_rsp, - bf_get(lpfc_vndr_code, &iocbq->iocb.un.bls_rsp)); - bf_set(xmit_bls_rsp64_rjt_expc, &wqe->xmit_bls_rsp, - bf_get(lpfc_rsn_expln, &iocbq->iocb.un.bls_rsp)); - bf_set(xmit_bls_rsp64_rjt_rsnc, &wqe->xmit_bls_rsp, - bf_get(lpfc_rsn_code, &iocbq->iocb.un.bls_rsp)); - } - - break; - case CMD_SEND_FRAME: - bf_set(wqe_cmnd, &wqe->generic.wqe_com, CMD_SEND_FRAME); - bf_set(wqe_sof, &wqe->generic.wqe_com, 0x2E); /* SOF byte */ - bf_set(wqe_eof, &wqe->generic.wqe_com, 0x41); /* EOF byte */ - bf_set(wqe_lenloc, &wqe->generic.wqe_com, 1); - bf_set(wqe_xbl, &wqe->generic.wqe_com, 1); - bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); - bf_set(wqe_xc, &wqe->generic.wqe_com, 1); - bf_set(wqe_cmd_type, &wqe->generic.wqe_com, 0xA); - bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); - bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); - return 0; - case CMD_XRI_ABORTED_CX: - case CMD_CREATE_XRI_CR: /* Do we expect to use this? */ - case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */ - case CMD_FCP_TSEND64_CX: /* Target mode send xfer-ready */ - case CMD_FCP_TRSP64_CX: /* Target mode rcv */ - case CMD_FCP_AUTO_TRSP_CX: /* Auto target rsp */ - default: - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "2014 Invalid command 0x%x\n", - iocbq->iocb.ulpCommand); - return IOCB_ERROR; - } - - if (iocbq->iocb_flag & LPFC_IO_DIF_PASS) - bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); - else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP) - bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); - else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT) - bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); - iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | - LPFC_IO_DIF_INSERT); - bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); - bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); - wqe->generic.wqe_com.abort_tag = abort_tag; - bf_set(wqe_cmd_type, &wqe->generic.wqe_com, command_type); - bf_set(wqe_cmnd, &wqe->generic.wqe_com, cmnd); - bf_set(wqe_class, &wqe->generic.wqe_com, iocbq->iocb.ulpClass); - bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - return 0; -} - -/** * __lpfc_sli_issue_fcp_io_s3 - SLI3 device for sending fcp io iocb * @phba: Pointer to HBA context object. * @ring_number: SLI ring number to issue wqe on. @@ -10957,7 +10318,17 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, int rc; struct lpfc_io_buf *lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; - union lpfc_wqe128 *wqe = &piocb->wqe; + + lpfc_prep_embed_io(phba, lpfc_cmd); + rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); + return rc; +} + +void +lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) +{ + struct lpfc_iocbq *piocb = &lpfc_cmd->cur_iocbq; + union lpfc_wqe128 *wqe = &lpfc_cmd->cur_iocbq.wqe; struct sli4_sge *sgl; /* 128 byte wqe support here */ @@ -10995,7 +10366,7 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, } /* add the VMID tags as per switch response */ - if (unlikely(piocb->iocb_flag & LPFC_IO_VMID)) { + if (unlikely(piocb->cmd_flag & LPFC_IO_VMID)) { if (phba->pport->vmid_priority_tagging) { bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com, @@ -11006,8 +10377,6 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, wqe->words[31] = piocb->vmid_tag.app_id; } } - rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); - return rc; } /** @@ -11029,13 +10398,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - union lpfc_wqe128 wqe; + union lpfc_wqe128 *wqe; struct lpfc_queue *wq; struct lpfc_sli_ring *pring; + u32 ulp_command = get_job_cmnd(phba, piocb); /* Get the WQ */ - if ((piocb->iocb_flag & LPFC_IO_FCP) || - (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { + if ((piocb->cmd_flag & LPFC_IO_FCP) || + (piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq; } else { wq = phba->sli4_hba.els_wq; @@ -11049,34 +10419,24 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, */ lockdep_assert_held(&pring->ring_lock); - + wqe = &piocb->wqe; if (piocb->sli4_xritag == NO_XRI) { - if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || - piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) + if (ulp_command == CMD_ABORT_XRI_CX) sglq = NULL; else { - if (!list_empty(&pring->txq)) { + sglq = __lpfc_sli_get_els_sglq(phba, piocb); + if (!sglq) { if (!(flag & SLI_IOCB_RET_IOCB)) { __lpfc_sli_ringtx_put(phba, - pring, piocb); + pring, + piocb); return IOCB_SUCCESS; } else { return IOCB_BUSY; } - } else { - sglq = __lpfc_sli_get_els_sglq(phba, piocb); - if (!sglq) { - if (!(flag & SLI_IOCB_RET_IOCB)) { - __lpfc_sli_ringtx_put(phba, - pring, - piocb); - return IOCB_SUCCESS; - } else - return IOCB_BUSY; - } } } - } else if (piocb->iocb_flag & LPFC_IO_FCP) { + } else if (piocb->cmd_flag & LPFC_IO_FCP) { /* These IO's already have an XRI and a mapped sgl. */ sglq = NULL; } @@ -11093,15 +10453,26 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, if (sglq) { piocb->sli4_lxritag = sglq->sli4_lxritag; piocb->sli4_xritag = sglq->sli4_xritag; - if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) + + /* ABTS sent by initiator to CT exchange, the + * RX_ID field will be filled with the newly + * allocated responder XRI. + */ + if (ulp_command == CMD_XMIT_BLS_RSP64_CX && + piocb->abort_bls == LPFC_ABTS_UNSOL_INT) + bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, + piocb->sli4_xritag); + + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, + piocb->sli4_xritag); + + if (lpfc_wqe_bpl2sgl(phba, piocb, sglq) == NO_XRI) return IOCB_ERROR; } - if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) + if (lpfc_sli4_wq_put(wq, wqe)) return IOCB_ERROR; - if (lpfc_sli4_wq_put(wq, &wqe)) - return IOCB_ERROR; lpfc_sli_ringtxcmpl_put(phba, pring, piocb); return 0; @@ -11144,6 +10515,390 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, return phba->__lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); } +static void +__lpfc_sli_prep_els_req_rsp_s3(struct lpfc_iocbq *cmdiocbq, + struct lpfc_vport *vport, + struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, + u32 elscmd, u8 tmo, u8 expect_rsp) +{ + struct lpfc_hba *phba = vport->phba; + IOCB_t *cmd; + + cmd = &cmdiocbq->iocb; + memset(cmd, 0, sizeof(*cmd)); + + cmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); + cmd->un.elsreq64.bdl.addrLow = putPaddrLow(bmp->phys); + cmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; + + if (expect_rsp) { + cmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); + cmd->un.elsreq64.remoteID = did; /* DID */ + cmd->ulpCommand = CMD_ELS_REQUEST64_CR; + cmd->ulpTimeout = tmo; + } else { + cmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64); + cmd->un.genreq64.xmit_els_remoteID = did; /* DID */ + cmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; + } + cmd->ulpBdeCount = 1; + cmd->ulpLe = 1; + cmd->ulpClass = CLASS3; + + /* If we have NPIV enabled, we want to send ELS traffic by VPI. */ + if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { + if (expect_rsp) { + cmd->un.elsreq64.myID = vport->fc_myDID; + + /* For ELS_REQUEST64_CR, use the VPI by default */ + cmd->ulpContext = phba->vpi_ids[vport->vpi]; + } + + cmd->ulpCt_h = 0; + /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ + if (elscmd == ELS_CMD_ECHO) + cmd->ulpCt_l = 0; /* context = invalid RPI */ + else + cmd->ulpCt_l = 1; /* context = VPI */ + } +} + +static void +__lpfc_sli_prep_els_req_rsp_s4(struct lpfc_iocbq *cmdiocbq, + struct lpfc_vport *vport, + struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, + u32 elscmd, u8 tmo, u8 expect_rsp) +{ + struct lpfc_hba *phba = vport->phba; + union lpfc_wqe128 *wqe; + struct ulp_bde64_le *bde; + + wqe = &cmdiocbq->wqe; + memset(wqe, 0, sizeof(*wqe)); + + /* Word 0 - 2 BDE */ + bde = (struct ulp_bde64_le *)&wqe->generic.bde; + bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys)); + bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys)); + bde->type_size = cpu_to_le32(cmd_size); + bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64); + + if (expect_rsp) { + bf_set(wqe_cmnd, &wqe->els_req.wqe_com, CMD_ELS_REQUEST64_CR); + + /* Transfer length */ + wqe->els_req.payload_len = cmd_size; + wqe->els_req.max_response_payload_len = FCELSSIZE; + + /* DID */ + bf_set(wqe_els_did, &wqe->els_req.wqe_dest, did); + } else { + /* DID */ + bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, did); + + /* Transfer length */ + wqe->xmit_els_rsp.response_payload_len = cmd_size; + + bf_set(wqe_cmnd, &wqe->xmit_els_rsp.wqe_com, + CMD_XMIT_ELS_RSP64_CX); + } + + bf_set(wqe_tmo, &wqe->generic.wqe_com, tmo); + bf_set(wqe_reqtag, &wqe->generic.wqe_com, cmdiocbq->iotag); + bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3); + + /* If we have NPIV enabled, we want to send ELS traffic by VPI. + * For SLI4, since the driver controls VPIs we also want to include + * all ELS pt2pt protocol traffic as well. + */ + if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) || + (vport->fc_flag & FC_PT2PT)) { + if (expect_rsp) { + bf_set(els_req64_sid, &wqe->els_req, vport->fc_myDID); + + /* For ELS_REQUEST64_CR, use the VPI by default */ + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->vpi_ids[vport->vpi]); + } + + /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ + if (elscmd == ELS_CMD_ECHO) + bf_set(wqe_ct, &wqe->generic.wqe_com, 0); + else + bf_set(wqe_ct, &wqe->generic.wqe_com, 1); + } +} + +void +lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + u16 cmd_size, u32 did, u32 elscmd, u8 tmo, + u8 expect_rsp) +{ + phba->__lpfc_sli_prep_els_req_rsp(cmdiocbq, vport, bmp, cmd_size, did, + elscmd, tmo, expect_rsp); +} + +static void +__lpfc_sli_prep_gen_req_s3(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, + u16 rpi, u32 num_entry, u8 tmo) +{ + IOCB_t *cmd; + + cmd = &cmdiocbq->iocb; + memset(cmd, 0, sizeof(*cmd)); + + cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); + cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); + cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; + cmd->un.genreq64.bdl.bdeSize = num_entry * sizeof(struct ulp_bde64); + + cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL; + cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT; + cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); + + cmd->ulpContext = rpi; + cmd->ulpClass = CLASS3; + cmd->ulpCommand = CMD_GEN_REQUEST64_CR; + cmd->ulpBdeCount = 1; + cmd->ulpLe = 1; + cmd->ulpOwner = OWN_CHIP; + cmd->ulpTimeout = tmo; +} + +static void +__lpfc_sli_prep_gen_req_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, + u16 rpi, u32 num_entry, u8 tmo) +{ + union lpfc_wqe128 *cmdwqe; + struct ulp_bde64_le *bde, *bpl; + u32 xmit_len = 0, total_len = 0, size, type, i; + + cmdwqe = &cmdiocbq->wqe; + memset(cmdwqe, 0, sizeof(*cmdwqe)); + + /* Calculate total_len and xmit_len */ + bpl = (struct ulp_bde64_le *)bmp->virt; + for (i = 0; i < num_entry; i++) { + size = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_SIZE_MASK; + total_len += size; + } + for (i = 0; i < num_entry; i++) { + size = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_SIZE_MASK; + type = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_TYPE_MASK; + if (type != ULP_BDE64_TYPE_BDE_64) + break; + xmit_len += size; + } + + /* Words 0 - 2 */ + bde = (struct ulp_bde64_le *)&cmdwqe->generic.bde; + bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys)); + bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys)); + bde->type_size = cpu_to_le32(xmit_len); + bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BLP_64); + + /* Word 3 */ + cmdwqe->gen_req.request_payload_len = xmit_len; + + /* Word 5 */ + bf_set(wqe_type, &cmdwqe->gen_req.wge_ctl, FC_TYPE_CT); + bf_set(wqe_rctl, &cmdwqe->gen_req.wge_ctl, FC_RCTL_DD_UNSOL_CTL); + bf_set(wqe_si, &cmdwqe->gen_req.wge_ctl, 1); + bf_set(wqe_la, &cmdwqe->gen_req.wge_ctl, 1); + + /* Word 6 */ + bf_set(wqe_ctxt_tag, &cmdwqe->gen_req.wqe_com, rpi); + + /* Word 7 */ + bf_set(wqe_tmo, &cmdwqe->gen_req.wqe_com, tmo); + bf_set(wqe_class, &cmdwqe->gen_req.wqe_com, CLASS3); + bf_set(wqe_cmnd, &cmdwqe->gen_req.wqe_com, CMD_GEN_REQUEST64_CR); + bf_set(wqe_ct, &cmdwqe->gen_req.wqe_com, SLI4_CT_RPI); + + /* Word 12 */ + cmdwqe->gen_req.max_response_payload_len = total_len - xmit_len; +} + +void +lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, u8 tmo) +{ + phba->__lpfc_sli_prep_gen_req(cmdiocbq, bmp, rpi, num_entry, tmo); +} + +static void +__lpfc_sli_prep_xmit_seq64_s3(struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, + u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd) +{ + IOCB_t *icmd; + + icmd = &cmdiocbq->iocb; + memset(icmd, 0, sizeof(*icmd)); + + icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys); + icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys); + icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; + icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64)); + icmd->un.xseq64.w5.hcsw.Fctl = LA; + if (last_seq) + icmd->un.xseq64.w5.hcsw.Fctl |= LS; + icmd->un.xseq64.w5.hcsw.Dfctl = 0; + icmd->un.xseq64.w5.hcsw.Rctl = rctl; + icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT; + + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + + switch (cr_cx_cmd) { + case CMD_XMIT_SEQUENCE64_CR: + icmd->ulpContext = rpi; + icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR; + break; + case CMD_XMIT_SEQUENCE64_CX: + icmd->ulpContext = ox_id; + icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; + break; + default: + break; + } +} + +static void +__lpfc_sli_prep_xmit_seq64_s4(struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, + u32 full_size, u8 rctl, u8 last_seq, u8 cr_cx_cmd) +{ + union lpfc_wqe128 *wqe; + struct ulp_bde64 *bpl; + struct ulp_bde64_le *bde; + + wqe = &cmdiocbq->wqe; + memset(wqe, 0, sizeof(*wqe)); + + /* Words 0 - 2 */ + bpl = (struct ulp_bde64 *)bmp->virt; + if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) { + wqe->xmit_sequence.bde.addrHigh = bpl->addrHigh; + wqe->xmit_sequence.bde.addrLow = bpl->addrLow; + wqe->xmit_sequence.bde.tus.w = bpl->tus.w; + } else { + bde = (struct ulp_bde64_le *)&wqe->xmit_sequence.bde; + bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys)); + bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys)); + bde->type_size = cpu_to_le32(bpl->tus.f.bdeSize); + bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64); + } + + /* Word 5 */ + bf_set(wqe_ls, &wqe->xmit_sequence.wge_ctl, last_seq); + bf_set(wqe_la, &wqe->xmit_sequence.wge_ctl, 1); + bf_set(wqe_dfctl, &wqe->xmit_sequence.wge_ctl, 0); + bf_set(wqe_rctl, &wqe->xmit_sequence.wge_ctl, rctl); + bf_set(wqe_type, &wqe->xmit_sequence.wge_ctl, FC_TYPE_CT); + + /* Word 6 */ + bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, rpi); + + bf_set(wqe_cmnd, &wqe->xmit_sequence.wqe_com, + CMD_XMIT_SEQUENCE64_WQE); + + /* Word 7 */ + bf_set(wqe_class, &wqe->xmit_sequence.wqe_com, CLASS3); + + /* Word 9 */ + bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ox_id); + + /* Word 12 */ + if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) + wqe->xmit_sequence.xmit_len = full_size; + else + wqe->xmit_sequence.xmit_len = + wqe->xmit_sequence.bde.tus.f.bdeSize; +} + +void +lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, + u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd) +{ + phba->__lpfc_sli_prep_xmit_seq64(cmdiocbq, bmp, rpi, ox_id, num_entry, + rctl, last_seq, cr_cx_cmd); +} + +static void +__lpfc_sli_prep_abort_xri_s3(struct lpfc_iocbq *cmdiocbq, u16 ulp_context, + u16 iotag, u8 ulp_class, u16 cqid, bool ia) +{ + IOCB_t *icmd = NULL; + + icmd = &cmdiocbq->iocb; + memset(icmd, 0, sizeof(*icmd)); + + /* Word 5 */ + icmd->un.acxri.abortContextTag = ulp_context; + icmd->un.acxri.abortIoTag = iotag; + + if (ia) { + /* Word 7 */ + icmd->ulpCommand = CMD_CLOSE_XRI_CN; + } else { + /* Word 3 */ + icmd->un.acxri.abortType = ABORT_TYPE_ABTS; + + /* Word 7 */ + icmd->ulpClass = ulp_class; + icmd->ulpCommand = CMD_ABORT_XRI_CN; + } + + /* Word 7 */ + icmd->ulpLe = 1; +} + +static void +__lpfc_sli_prep_abort_xri_s4(struct lpfc_iocbq *cmdiocbq, u16 ulp_context, + u16 iotag, u8 ulp_class, u16 cqid, bool ia) +{ + union lpfc_wqe128 *wqe; + + wqe = &cmdiocbq->wqe; + memset(wqe, 0, sizeof(*wqe)); + + /* Word 3 */ + bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); + if (ia) + bf_set(abort_cmd_ia, &wqe->abort_cmd, 1); + else + bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_WQE); + + /* Word 8 */ + wqe->abort_cmd.wqe_com.abort_tag = ulp_context; + + /* Word 9 */ + bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, iotag); + + /* Word 10 */ + bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); + + /* Word 11 */ + bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, cqid); + bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND); +} + +void +lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, + u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid, + bool ia) +{ + phba->__lpfc_sli_prep_abort_xri(cmdiocbq, ulp_context, iotag, ulp_class, + cqid, ia); +} + /** * lpfc_sli_api_table_setup - Set up sli api function jump table * @phba: The hba struct for which this call is being executed. @@ -11162,11 +10917,19 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s3; phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s3; phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s3; + phba->__lpfc_sli_prep_els_req_rsp = __lpfc_sli_prep_els_req_rsp_s3; + phba->__lpfc_sli_prep_gen_req = __lpfc_sli_prep_gen_req_s3; + phba->__lpfc_sli_prep_xmit_seq64 = __lpfc_sli_prep_xmit_seq64_s3; + phba->__lpfc_sli_prep_abort_xri = __lpfc_sli_prep_abort_xri_s3; break; case LPFC_PCI_DEV_OC: phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s4; phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s4; phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s4; + phba->__lpfc_sli_prep_els_req_rsp = __lpfc_sli_prep_els_req_rsp_s4; + phba->__lpfc_sli_prep_gen_req = __lpfc_sli_prep_gen_req_s4; + phba->__lpfc_sli_prep_xmit_seq64 = __lpfc_sli_prep_xmit_seq64_s4; + phba->__lpfc_sli_prep_abort_xri = __lpfc_sli_prep_abort_xri_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -11174,7 +10937,6 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) dev_grp); return -ENODEV; } - phba->lpfc_get_iocb_from_iocbq = lpfc_get_iocb_from_iocbq; return 0; } @@ -11193,14 +10955,14 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) { struct lpfc_io_buf *lpfc_cmd; - if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { + if (piocb->cmd_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { if (unlikely(!phba->sli4_hba.hdwq)) return NULL; /* * for abort iocb hba_wqidx should already * be setup based on what work queue we used. */ - if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { + if (!(piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; piocb->hba_wqidx = lpfc_cmd->hdwq_no; } @@ -11236,6 +10998,8 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, int rc; if (phba->sli_rev == LPFC_SLI_REV4) { + lpfc_sli_prep_wqe(phba, piocb); + eq = phba->sli4_hba.hdwq[piocb->hba_wqidx].hba_eq; pring = lpfc_sli4_calc_ring(phba, piocb); @@ -11372,8 +11136,8 @@ lpfc_sli_abts_err_handler(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "3095 Event Context not found, no " "action on vpi %d rpi %d status 0x%x, reason 0x%x\n", - iocbq->iocb.ulpContext, iocbq->iocb.ulpStatus, - vpi, rpi); + vpi, rpi, iocbq->iocb.ulpStatus, + iocbq->iocb.ulpContext); } /* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port. @@ -12221,47 +11985,33 @@ static void lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { - IOCB_t *irsp = &rspiocb->iocb; - uint16_t abort_iotag, abort_context; - struct lpfc_iocbq *abort_iocb = NULL; - - if (irsp->ulpStatus) { + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); + u8 cmnd = get_job_cmnd(phba, cmdiocb); + if (ulp_status) { /* * Assume that the port already completed and returned, or * will return the iocb. Just Log the message. */ - abort_context = cmdiocb->iocb.un.acxri.abortContextTag; - abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag; - - spin_lock_irq(&phba->hbalock); if (phba->sli_rev < LPFC_SLI_REV4) { - if (irsp->ulpCommand == CMD_ABORT_XRI_CX && - irsp->ulpStatus == IOSTAT_LOCAL_REJECT && - irsp->un.ulpWord[4] == IOERR_ABORT_REQUESTED) { - spin_unlock_irq(&phba->hbalock); + if (cmnd == CMD_ABORT_XRI_CX && + ulp_status == IOSTAT_LOCAL_REJECT && + ulp_word4 == IOERR_ABORT_REQUESTED) { goto release_iocb; } - if (abort_iotag != 0 && - abort_iotag <= phba->sli.last_iotag) - abort_iocb = - phba->sli.iocbq_lookup[abort_iotag]; - } else - /* For sli4 the abort_tag is the XRI, - * so the abort routine puts the iotag of the iocb - * being aborted in the context field of the abort - * IOCB. - */ - abort_iocb = phba->sli.iocbq_lookup[abort_context]; + } lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI, "0327 Cannot abort els iocb x%px " - "with tag %x context %x, abort status %x, " - "abort code %x\n", - abort_iocb, abort_iotag, abort_context, - irsp->ulpStatus, irsp->un.ulpWord[4]); + "with io cmd xri %x abort tag : x%x, " + "abort status %x abort code %x\n", + cmdiocb, get_job_abtsiotag(phba, cmdiocb), + (phba->sli_rev == LPFC_SLI_REV4) ? + get_wqe_reqtag(cmdiocb) : + cmdiocb->iocb.un.acxri.abortContextTag, + ulp_status, ulp_word4); - spin_unlock_irq(&phba->hbalock); } release_iocb: lpfc_sli_release_iocbq(phba, cmdiocb); @@ -12284,19 +12034,31 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_nodelist *ndlp = NULL; - IOCB_t *irsp = &rspiocb->iocb; + IOCB_t *irsp; + u32 ulp_command, ulp_status, ulp_word4, iotag; + + ulp_command = get_job_cmnd(phba, cmdiocb); + ulp_status = get_job_ulpstatus(phba, rspiocb); + ulp_word4 = get_job_word4(phba, rspiocb); + + if (phba->sli_rev == LPFC_SLI_REV4) { + iotag = get_wqe_reqtag(cmdiocb); + } else { + irsp = &rspiocb->iocb; + iotag = irsp->ulpIoTag; + } /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "0139 Ignoring ELS cmd code x%x completion Data: " "x%x x%x x%x\n", - irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout); + ulp_command, ulp_status, ulp_word4, iotag); + /* * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp * if exchange is busy. */ - if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) { + if (ulp_command == CMD_GEN_REQUEST64_CR) { ndlp = cmdiocb->context_un.ndlp; lpfc_ct_free_iocb(phba, cmdiocb); } else { @@ -12328,28 +12090,29 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_iocbq *abtsiocbp; - IOCB_t *icmd = NULL; - IOCB_t *iabt = NULL; int retval = IOCB_ERROR; unsigned long iflags; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = NULL; + u32 ulp_command = get_job_cmnd(phba, cmdiocb); + u16 ulp_context, iotag; + bool ia; /* * There are certain command types we don't want to abort. And we * don't want to abort commands that are already in the process of * being aborted. */ - icmd = &cmdiocb->iocb; - if (icmd->ulpCommand == CMD_ABORT_XRI_CN || - icmd->ulpCommand == CMD_CLOSE_XRI_CN || - cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) + if (ulp_command == CMD_ABORT_XRI_WQE || + ulp_command == CMD_ABORT_XRI_CN || + ulp_command == CMD_CLOSE_XRI_CN || + cmdiocb->cmd_flag & LPFC_DRIVER_ABORTED) return IOCB_ABORTING; if (!pring) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; return retval; } @@ -12359,10 +12122,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ if ((vport->load_flag & FC_UNLOADING) && pring->ringno == LPFC_ELS_RING) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; return retval; } @@ -12374,43 +12137,46 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* This signals the response to set the correct status * before calling the completion handler */ - cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; + cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; - iabt = &abtsiocbp->iocb; - iabt->un.acxri.abortType = ABORT_TYPE_ABTS; - iabt->un.acxri.abortContextTag = icmd->ulpContext; if (phba->sli_rev == LPFC_SLI_REV4) { - iabt->un.acxri.abortIoTag = cmdiocb->sli4_xritag; - if (pring->ringno == LPFC_ELS_RING) - iabt->un.acxri.abortContextTag = cmdiocb->iotag; + ulp_context = cmdiocb->sli4_xritag; + iotag = abtsiocbp->iotag; } else { - iabt->un.acxri.abortIoTag = icmd->ulpIoTag; + iotag = cmdiocb->iocb.ulpIoTag; if (pring->ringno == LPFC_ELS_RING) { ndlp = (struct lpfc_nodelist *)(cmdiocb->context1); - iabt->un.acxri.abortContextTag = ndlp->nlp_rpi; + ulp_context = ndlp->nlp_rpi; + } else { + ulp_context = cmdiocb->iocb.ulpContext; } } - iabt->ulpLe = 1; - iabt->ulpClass = icmd->ulpClass; - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; - if (cmdiocb->iocb_flag & LPFC_IO_FCP) - abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); - if (cmdiocb->iocb_flag & LPFC_IO_FOF) - abtsiocbp->iocb_flag |= LPFC_IO_FOF; if (phba->link_state < LPFC_LINK_UP || (phba->sli_rev == LPFC_SLI_REV4 && phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN)) - iabt->ulpCommand = CMD_CLOSE_XRI_CN; + ia = true; else - iabt->ulpCommand = CMD_ABORT_XRI_CN; + ia = false; + + lpfc_sli_prep_abort_xri(phba, abtsiocbp, ulp_context, iotag, + cmdiocb->iocb.ulpClass, + LPFC_WQE_CQ_ID_DEFAULT, ia); + + abtsiocbp->vport = vport; + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; + if (cmdiocb->cmd_flag & LPFC_IO_FCP) + abtsiocbp->cmd_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); + + if (cmdiocb->cmd_flag & LPFC_IO_FOF) + abtsiocbp->cmd_flag |= LPFC_IO_FOF; if (cmpl) - abtsiocbp->iocb_cmpl = cmpl; + abtsiocbp->cmd_cmpl = cmpl; else - abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; + abtsiocbp->cmd_cmpl = lpfc_sli_abort_els_cmpl; abtsiocbp->vport = vport; if (phba->sli_rev == LPFC_SLI_REV4) { @@ -12430,14 +12196,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, abort_iotag_exit: lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0339 Abort xri x%x, original iotag x%x, " - "abort cmd iotag x%x retval x%x\n", - iabt->un.acxri.abortIoTag, - iabt->un.acxri.abortContextTag, - abtsiocbp->iotag, retval); - + "0339 Abort IO XRI x%x, Original iotag x%x, " + "abort tag x%x Cmdjob : x%px Abortjob : x%px " + "retval x%x\n", + ulp_context, (phba->sli_rev == LPFC_SLI_REV4) ? + cmdiocb->iotag : iotag, iotag, cmdiocb, abtsiocbp, + retval); if (retval) { - cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; __lpfc_sli_release_iocbq(phba, abtsiocbp); } @@ -12495,7 +12261,7 @@ static int lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport) { - IOCB_t *icmd = NULL; + u8 ulp_command; /* No null ptr vports */ if (!iocbq || iocbq->vport != vport) @@ -12504,12 +12270,13 @@ lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, /* iocb must be for FCP IO, already exists on the TX cmpl queue, * can't be premarked as driver aborted, nor be an ABORT iocb itself */ - icmd = &iocbq->iocb; - if (!(iocbq->iocb_flag & LPFC_IO_FCP) || - !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || - (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || - (icmd->ulpCommand == CMD_ABORT_XRI_CN || - icmd->ulpCommand == CMD_CLOSE_XRI_CN)) + ulp_command = get_job_cmnd(vport->phba, iocbq); + if (!(iocbq->cmd_flag & LPFC_IO_FCP) || + !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ) || + (iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || + (ulp_command == CMD_ABORT_XRI_CN || + ulp_command == CMD_CLOSE_XRI_CN || + ulp_command == CMD_ABORT_XRI_WQE)) return -EINVAL; return 0; @@ -12601,9 +12368,9 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocbq; - IOCB_t *icmd = NULL; int sum, i; unsigned long iflags; + u8 ulp_command; spin_lock_irqsave(&phba->hbalock, iflags); for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { @@ -12611,14 +12378,15 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, if (!iocbq || iocbq->vport != vport) continue; - if (!(iocbq->iocb_flag & LPFC_IO_FCP) || - !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) + if (!(iocbq->cmd_flag & LPFC_IO_FCP) || + !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) continue; /* Include counting outstanding aborts */ - icmd = &iocbq->iocb; - if (icmd->ulpCommand == CMD_ABORT_XRI_CN || - icmd->ulpCommand == CMD_CLOSE_XRI_CN) { + ulp_command = get_job_cmnd(phba, iocbq); + if (ulp_command == CMD_ABORT_XRI_CN || + ulp_command == CMD_CLOSE_XRI_CN || + ulp_command == CMD_ABORT_XRI_WQE) { sum++; continue; } @@ -12633,33 +12401,6 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, } /** - * lpfc_sli4_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs - * @phba: Pointer to HBA context object - * @cmdiocb: Pointer to command iocb object. - * @wcqe: pointer to the complete wcqe - * - * This function is called when an aborted FCP iocb completes. This - * function is called by the ring event handler with no lock held. - * This function frees the iocb. It is called for sli-4 adapters. - **/ -void -lpfc_sli4_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_wcqe_complete *wcqe) -{ - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "3017 ABORT_XRI_CN completing on rpi x%x " - "original iotag x%x, abort cmd iotag x%x " - "status 0x%x, reason 0x%x\n", - cmdiocb->iocb.un.acxri.abortContextTag, - cmdiocb->iocb.un.acxri.abortIoTag, - cmdiocb->iotag, - (bf_get(lpfc_wcqe_c_status, wcqe) - & LPFC_IOCB_STATUS_MASK), - wcqe->parameter); - lpfc_sli_release_iocbq(phba, cmdiocb); -} - -/** * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs * @phba: Pointer to HBA context object * @cmdiocb: Pointer to command iocb object. @@ -12674,13 +12415,15 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "3096 ABORT_XRI_CN completing on rpi x%x " + "3096 ABORT_XRI_CX completing on rpi x%x " "original iotag x%x, abort cmd iotag x%x " "status 0x%x, reason 0x%x\n", + (phba->sli_rev == LPFC_SLI_REV4) ? + cmdiocb->sli4_xritag : cmdiocb->iocb.un.acxri.abortContextTag, - cmdiocb->iocb.un.acxri.abortIoTag, - cmdiocb->iotag, rspiocb->iocb.ulpStatus, - rspiocb->iocb.un.ulpWord[4]); + get_job_abtsiotag(phba, cmdiocb), + cmdiocb->iotag, get_job_ulpstatus(phba, rspiocb), + get_job_word4(phba, rspiocb)); lpfc_sli_release_iocbq(phba, cmdiocb); return; } @@ -12721,7 +12464,6 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, int errcnt = 0, ret_val = 0; unsigned long iflags; int i; - void *fcp_cmpl = NULL; /* all I/Os are in process of being flushed */ if (phba->hba_flag & HBA_IOQ_FLUSH) @@ -12740,13 +12482,11 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, spin_lock_irqsave(&phba->hbalock, iflags); if (phba->sli_rev == LPFC_SLI_REV3) { pring = &phba->sli.sli3_ring[LPFC_FCP_RING]; - fcp_cmpl = lpfc_sli_abort_fcp_cmpl; } else if (phba->sli_rev == LPFC_SLI_REV4) { pring = lpfc_sli4_calc_ring(phba, iocbq); - fcp_cmpl = lpfc_sli4_abort_fcp_cmpl; } ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocbq, - fcp_cmpl); + lpfc_sli_abort_fcp_cmpl); spin_unlock_irqrestore(&phba->hbalock, iflags); if (ret_val != IOCB_SUCCESS) errcnt++; @@ -12788,12 +12528,13 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, struct lpfc_hba *phba = vport->phba; struct lpfc_io_buf *lpfc_cmd; struct lpfc_iocbq *abtsiocbq; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = NULL; struct lpfc_iocbq *iocbq; - IOCB_t *icmd; int sum, i, ret_val; unsigned long iflags; struct lpfc_sli_ring *pring_s4 = NULL; + u16 ulp_context, iotag, cqid = LPFC_WQE_CQ_ID_DEFAULT; + bool ia; spin_lock_irqsave(&phba->hbalock, iflags); @@ -12838,8 +12579,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, * If the iocbq is already being aborted, don't take a second * action, but do count it. */ - if ((iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || - !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { + if ((iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || + !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { if (phba->sli_rev == LPFC_SLI_REV4) spin_unlock(&pring_s4->ring_lock); spin_unlock(&lpfc_cmd->buf_lock); @@ -12855,41 +12596,49 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, continue; } - icmd = &iocbq->iocb; - abtsiocbq->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; - abtsiocbq->iocb.un.acxri.abortContextTag = icmd->ulpContext; - if (phba->sli_rev == LPFC_SLI_REV4) - abtsiocbq->iocb.un.acxri.abortIoTag = - iocbq->sli4_xritag; - else - abtsiocbq->iocb.un.acxri.abortIoTag = icmd->ulpIoTag; - abtsiocbq->iocb.ulpLe = 1; - abtsiocbq->iocb.ulpClass = icmd->ulpClass; - abtsiocbq->vport = vport; - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocbq->hba_wqidx = iocbq->hba_wqidx; - if (iocbq->iocb_flag & LPFC_IO_FCP) - abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; - if (iocbq->iocb_flag & LPFC_IO_FOF) - abtsiocbq->iocb_flag |= LPFC_IO_FOF; + if (phba->sli_rev == LPFC_SLI_REV4) { + iotag = abtsiocbq->iotag; + ulp_context = iocbq->sli4_xritag; + cqid = lpfc_cmd->hdwq->io_cq_map; + } else { + iotag = iocbq->iocb.ulpIoTag; + if (pring->ringno == LPFC_ELS_RING) { + ndlp = (struct lpfc_nodelist *)(iocbq->context1); + ulp_context = ndlp->nlp_rpi; + } else { + ulp_context = iocbq->iocb.ulpContext; + } + } ndlp = lpfc_cmd->rdata->pnode; if (lpfc_is_link_up(phba) && (ndlp && ndlp->nlp_state == NLP_STE_MAPPED_NODE)) - abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN; + ia = false; else - abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN; + ia = true; + + lpfc_sli_prep_abort_xri(phba, abtsiocbq, ulp_context, iotag, + iocbq->iocb.ulpClass, cqid, + ia); + + abtsiocbq->vport = vport; + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocbq->hba_wqidx = iocbq->hba_wqidx; + if (iocbq->cmd_flag & LPFC_IO_FCP) + abtsiocbq->cmd_flag |= LPFC_USE_FCPWQIDX; + if (iocbq->cmd_flag & LPFC_IO_FOF) + abtsiocbq->cmd_flag |= LPFC_IO_FOF; /* Setup callback routine and issue the command. */ - abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; + abtsiocbq->cmd_cmpl = lpfc_sli_abort_fcp_cmpl; /* * Indicate the IO is being aborted by the driver and set * the caller's flag into the aborted IO. */ - iocbq->iocb_flag |= LPFC_DRIVER_ABORTED; + iocbq->cmd_flag |= LPFC_DRIVER_ABORTED; if (phba->sli_rev == LPFC_SLI_REV4) { ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, @@ -12936,9 +12685,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, wait_queue_head_t *pdone_q; unsigned long iflags; struct lpfc_io_buf *lpfc_cmd; + size_t offset = offsetof(struct lpfc_iocbq, wqe); spin_lock_irqsave(&phba->hbalock, iflags); - if (cmdiocbq->iocb_flag & LPFC_IO_WAKE_TMO) { + if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) { /* * A time out has occurred for the iocb. If a time out @@ -12947,26 +12697,27 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, */ spin_unlock_irqrestore(&phba->hbalock, iflags); - cmdiocbq->iocb_cmpl = cmdiocbq->wait_iocb_cmpl; - cmdiocbq->wait_iocb_cmpl = NULL; - if (cmdiocbq->iocb_cmpl) - (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, NULL); + cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl; + cmdiocbq->wait_cmd_cmpl = NULL; + if (cmdiocbq->cmd_cmpl) + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, NULL); else lpfc_sli_release_iocbq(phba, cmdiocbq); return; } - cmdiocbq->iocb_flag |= LPFC_IO_WAKE; + /* Copy the contents of the local rspiocb into the caller's buffer. */ + cmdiocbq->cmd_flag |= LPFC_IO_WAKE; if (cmdiocbq->context2 && rspiocbq) - memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, - &rspiocbq->iocb, sizeof(IOCB_t)); + memcpy((char *)cmdiocbq->context2 + offset, + (char *)rspiocbq + offset, sizeof(*rspiocbq) - offset); /* Set the exchange busy flag for task management commands */ - if ((cmdiocbq->iocb_flag & LPFC_IO_FCP) && - !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) { + if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && + !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf, cur_iocbq); - if (rspiocbq && (rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY)) + if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY)) lpfc_cmd->flags |= LPFC_SBUF_XBUSY; else lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; @@ -12985,7 +12736,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, * @piocbq: Pointer to command iocb. * @flag: Flag to test. * - * This routine grabs the hbalock and then test the iocb_flag to + * This routine grabs the hbalock and then test the cmd_flag to * see if the passed in flag is set. * Returns: * 1 if flag is set. @@ -12999,7 +12750,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, int ret; spin_lock_irqsave(&phba->hbalock, iflags); - ret = piocbq->iocb_flag & flag; + ret = piocbq->cmd_flag & flag; spin_unlock_irqrestore(&phba->hbalock, iflags); return ret; @@ -13014,14 +12765,14 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, * @timeout: Timeout in number of seconds. * * This function issues the iocb to firmware and waits for the - * iocb to complete. The iocb_cmpl field of the shall be used + * iocb to complete. The cmd_cmpl field of the shall be used * to handle iocbs which time out. If the field is NULL, the * function shall free the iocbq structure. If more clean up is * needed, the caller is expected to provide a completion function * that will provide the needed clean up. If the iocb command is * not completed within timeout seconds, the function will either - * free the iocbq structure (if iocb_cmpl == NULL) or execute the - * completion function set in the iocb_cmpl field and then return + * free the iocbq structure (if cmd_cmpl == NULL) or execute the + * completion function set in the cmd_cmpl field and then return * a status of IOCB_TIMEDOUT. The caller should not free the iocb * resources if this function returns IOCB_TIMEDOUT. * The function waits for the iocb completion using an @@ -13033,7 +12784,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, * This function assumes that the iocb completions occur while * this function sleep. So, this function cannot be called from * the thread which process iocb completion for this ring. - * This function clears the iocb_flag of the iocb object before + * This function clears the cmd_flag of the iocb object before * issuing the iocb and the iocb completion handler sets this * flag and wakes this thread when the iocb completes. * The contents of the response iocb will be copied to prspiocbq @@ -13059,9 +12810,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, unsigned long iflags; bool iocb_completed = true; - if (phba->sli_rev >= LPFC_SLI_REV4) + if (phba->sli_rev >= LPFC_SLI_REV4) { + lpfc_sli_prep_wqe(phba, piocb); + pring = lpfc_sli4_calc_ring(phba, piocb); - else + } else pring = &phba->sli.sli3_ring[ring_number]; /* * If the caller has provided a response iocbq buffer, then context2 @@ -13073,10 +12826,10 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, piocb->context2 = prspiocbq; } - piocb->wait_iocb_cmpl = piocb->iocb_cmpl; - piocb->iocb_cmpl = lpfc_sli_wake_iocb_wait; + piocb->wait_cmd_cmpl = piocb->cmd_cmpl; + piocb->cmd_cmpl = lpfc_sli_wake_iocb_wait; piocb->context_un.wait_queue = &done_q; - piocb->iocb_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO); + piocb->cmd_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO); if (phba->cfg_poll & DISABLE_FCP_RING_INT) { if (lpfc_readl(phba->HCregaddr, &creg_val)) @@ -13094,7 +12847,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), timeout_req); spin_lock_irqsave(&phba->hbalock, iflags); - if (!(piocb->iocb_flag & LPFC_IO_WAKE)) { + if (!(piocb->cmd_flag & LPFC_IO_WAKE)) { /* * IOCB timed out. Inform the wake iocb wait @@ -13102,7 +12855,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, */ iocb_completed = false; - piocb->iocb_flag |= LPFC_IO_WAKE_TMO; + piocb->cmd_flag |= LPFC_IO_WAKE_TMO; } spin_unlock_irqrestore(&phba->hbalock, iflags); if (iocb_completed) { @@ -13157,7 +12910,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, piocb->context2 = NULL; piocb->context_un.wait_queue = NULL; - piocb->iocb_cmpl = NULL; + piocb->cmd_cmpl = NULL; return retval; } @@ -14098,123 +13851,7 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) } /** - * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn - * @phba: pointer to lpfc hba data structure - * @pIocbIn: pointer to the rspiocbq - * @pIocbOut: pointer to the cmdiocbq - * @wcqe: pointer to the complete wcqe - * - * This routine transfers the fields of a command iocbq to a response iocbq - * by copying all the IOCB fields from command iocbq and transferring the - * completion status information from the complete wcqe. - **/ -static void -lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, - struct lpfc_iocbq *pIocbIn, - struct lpfc_iocbq *pIocbOut, - struct lpfc_wcqe_complete *wcqe) -{ - int numBdes, i; - unsigned long iflags; - uint32_t status, max_response; - struct lpfc_dmabuf *dmabuf; - struct ulp_bde64 *bpl, bde; - size_t offset = offsetof(struct lpfc_iocbq, iocb); - - memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, - sizeof(struct lpfc_iocbq) - offset); - /* Map WCQE parameters into irspiocb parameters */ - status = bf_get(lpfc_wcqe_c_status, wcqe); - pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK); - if (pIocbOut->iocb_flag & LPFC_IO_FCP) - if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) - pIocbIn->iocb.un.fcpi.fcpi_parm = - pIocbOut->iocb.un.fcpi.fcpi_parm - - wcqe->total_data_placed; - else - pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; - else { - pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; - switch (pIocbOut->iocb.ulpCommand) { - case CMD_ELS_REQUEST64_CR: - dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; - bpl = (struct ulp_bde64 *)dmabuf->virt; - bde.tus.w = le32_to_cpu(bpl[1].tus.w); - max_response = bde.tus.f.bdeSize; - break; - case CMD_GEN_REQUEST64_CR: - max_response = 0; - if (!pIocbOut->context3) - break; - numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/ - sizeof(struct ulp_bde64); - dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; - bpl = (struct ulp_bde64 *)dmabuf->virt; - for (i = 0; i < numBdes; i++) { - bde.tus.w = le32_to_cpu(bpl[i].tus.w); - if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) - max_response += bde.tus.f.bdeSize; - } - break; - default: - max_response = wcqe->total_data_placed; - break; - } - if (max_response < wcqe->total_data_placed) - pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response; - else - pIocbIn->iocb.un.genreq64.bdl.bdeSize = - wcqe->total_data_placed; - } - - /* Convert BG errors for completion status */ - if (status == CQE_STATUS_DI_ERROR) { - pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; - - if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) - pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED; - else - pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED; - - pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0; - if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ - pIocbIn->iocb.unsli3.sli3_bg.bgstat |= - BGS_GUARD_ERR_MASK; - if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */ - pIocbIn->iocb.unsli3.sli3_bg.bgstat |= - BGS_APPTAG_ERR_MASK; - if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */ - pIocbIn->iocb.unsli3.sli3_bg.bgstat |= - BGS_REFTAG_ERR_MASK; - - /* Check to see if there was any good data before the error */ - if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { - pIocbIn->iocb.unsli3.sli3_bg.bgstat |= - BGS_HI_WATER_MARK_PRESENT_MASK; - pIocbIn->iocb.unsli3.sli3_bg.bghm = - wcqe->total_data_placed; - } - - /* - * Set ALL the error bits to indicate we don't know what - * type of error it is. - */ - if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat) - pIocbIn->iocb.unsli3.sli3_bg.bgstat |= - (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | - BGS_GUARD_ERR_MASK); - } - - /* Pick up HBA exchange busy condition */ - if (bf_get(lpfc_wcqe_c_xb, wcqe)) { - spin_lock_irqsave(&phba->hbalock, iflags); - pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } -} - -/** - * lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe + * lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe * @phba: Pointer to HBA context object. * @irspiocbq: Pointer to work-queue completion queue entry. * @@ -14225,8 +13862,8 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, * Return: Pointer to the receive IOCBQ, NULL otherwise. **/ static struct lpfc_iocbq * -lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, - struct lpfc_iocbq *irspiocbq) +lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, + struct lpfc_iocbq *irspiocbq) { struct lpfc_sli_ring *pring; struct lpfc_iocbq *cmdiocbq; @@ -14238,11 +13875,13 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, return NULL; wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl; + spin_lock_irqsave(&pring->ring_lock, iflags); pring->stats.iocb_event++; /* Look up the ELS command IOCB and create pseudo response IOCB */ cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, bf_get(lpfc_wcqe_c_request_tag, wcqe)); if (unlikely(!cmdiocbq)) { + spin_unlock_irqrestore(&pring->ring_lock, iflags); lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0386 ELS complete with no corresponding " "cmdiocb: 0x%x 0x%x 0x%x 0x%x\n", @@ -14252,13 +13891,18 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, return NULL; } - spin_lock_irqsave(&pring->ring_lock, iflags); + memcpy(&irspiocbq->wqe, &cmdiocbq->wqe, sizeof(union lpfc_wqe128)); + memcpy(&irspiocbq->wcqe_cmpl, wcqe, sizeof(*wcqe)); + /* Put the iocb back on the txcmplq */ lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq); spin_unlock_irqrestore(&pring->ring_lock, iflags); - /* Fake the irspiocbq and copy necessary response information */ - lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe); + if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + spin_lock_irqsave(&phba->hbalock, iflags); + cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore(&phba->hbalock, iflags); + } return irspiocbq; } @@ -15059,7 +14703,6 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, { struct lpfc_sli_ring *pring = cq->pring; struct lpfc_iocbq *cmdiocbq; - struct lpfc_iocbq irspiocbq; unsigned long iflags; /* Check for response status */ @@ -15085,9 +14728,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, /* Look up the FCP command IOCB and create pseudo response IOCB */ spin_lock_irqsave(&pring->ring_lock, iflags); pring->stats.iocb_event++; - spin_unlock_irqrestore(&pring->ring_lock, iflags); cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, bf_get(lpfc_wcqe_c_request_tag, wcqe)); + spin_unlock_irqrestore(&pring->ring_lock, iflags); if (unlikely(!cmdiocbq)) { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0374 FCP complete with no corresponding " @@ -15098,39 +14741,31 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, #ifdef CONFIG_SCSI_LPFC_DEBUG_FS cmdiocbq->isr_timestamp = cq->isr_timestamp; #endif - if (cmdiocbq->iocb_cmpl == NULL) { - if (cmdiocbq->wqe_cmpl) { - /* For FCP the flag is cleared in wqe_cmpl */ - if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) && - cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } + if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + spin_lock_irqsave(&phba->hbalock, iflags); + cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore(&phba->hbalock, iflags); + } - /* Pass the cmd_iocb and the wcqe to the upper layer */ - (cmdiocbq->wqe_cmpl)(phba, cmdiocbq, wcqe); - return; + if (cmdiocbq->cmd_cmpl) { + /* For FCP the flag is cleared in cmd_cmpl */ + if (!(cmdiocbq->cmd_flag & LPFC_IO_FCP) && + cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) { + spin_lock_irqsave(&phba->hbalock, iflags); + cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; + spin_unlock_irqrestore(&phba->hbalock, iflags); } + + /* Pass the cmd_iocb and the wcqe to the upper layer */ + memcpy(&cmdiocbq->wcqe_cmpl, wcqe, + sizeof(struct lpfc_wcqe_complete)); + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, cmdiocbq); + } else { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0375 FCP cmdiocb not callback function " "iotag: (%d)\n", bf_get(lpfc_wcqe_c_request_tag, wcqe)); - return; } - - /* Only SLI4 non-IO commands stil use IOCB */ - /* Fake the irspiocb and copy necessary response information */ - lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); - - if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } - - /* Pass the cmd_iocb and the rsp state to the upper layer */ - (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); } /** @@ -18858,8 +18493,8 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus) lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3154 BLS ABORT RSP failed, data: x%x/x%x\n", - rsp_iocbq->iocb.ulpStatus, - rsp_iocbq->iocb.un.ulpWord[4]); + get_job_ulpstatus(phba, rsp_iocbq), + get_job_word4(phba, rsp_iocbq)); } /** @@ -18901,7 +18536,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp; uint16_t oxid, rxid, xri, lxri; uint32_t sid, fctl; - IOCB_t *icmd; + union lpfc_wqe128 *icmd; int rc; if (!lpfc_is_link_up(phba)) @@ -18929,22 +18564,11 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, if (!ctiocb) return; + icmd = &ctiocb->wqe; + /* Extract the F_CTL field from FC_HDR */ fctl = sli4_fctl_from_fc_hdr(fc_hdr); - icmd = &ctiocb->iocb; - icmd->un.xseq64.bdl.bdeSize = 0; - icmd->un.xseq64.bdl.ulpIoTag32 = 0; - icmd->un.xseq64.w5.hcsw.Dfctl = 0; - icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_ACC; - icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_BLS; - - /* Fill in the rest of iocb fields */ - icmd->ulpCommand = CMD_XMIT_BLS_RSP64_CX; - icmd->ulpBdeCount = 0; - icmd->ulpLe = 1; - icmd->ulpClass = CLASS3; - icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; ctiocb->context1 = lpfc_nlp_get(ndlp); if (!ctiocb->context1) { lpfc_sli_release_iocbq(phba, ctiocb); @@ -18952,9 +18576,10 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, } ctiocb->vport = phba->pport; - ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; + ctiocb->cmd_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; ctiocb->sli4_lxritag = NO_XRI; ctiocb->sli4_xritag = NO_XRI; + ctiocb->abort_rctl = FC_RCTL_BA_ACC; if (fctl & FC_FC_EX_CTX) /* Exchange responder sent the abort so we @@ -18974,10 +18599,12 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, */ if ((fctl & FC_FC_EX_CTX) && (lxri > lpfc_sli4_get_iocb_cnt(phba))) { - icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; - bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); - bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); - bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE); + ctiocb->abort_rctl = FC_RCTL_BA_RJT; + bf_set(xmit_bls_rsp64_rjt_vspec, &icmd->xmit_bls_rsp, 0); + bf_set(xmit_bls_rsp64_rjt_expc, &icmd->xmit_bls_rsp, + FC_BA_RJT_INV_XID); + bf_set(xmit_bls_rsp64_rjt_rsnc, &icmd->xmit_bls_rsp, + FC_BA_RJT_UNABLE); } /* If BA_ABTS failed to abort a partially assembled receive sequence, @@ -18985,10 +18612,12 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, * the IOCB for a BA_RJT. */ if (aborted == false) { - icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; - bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); - bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); - bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE); + ctiocb->abort_rctl = FC_RCTL_BA_RJT; + bf_set(xmit_bls_rsp64_rjt_vspec, &icmd->xmit_bls_rsp, 0); + bf_set(xmit_bls_rsp64_rjt_expc, &icmd->xmit_bls_rsp, + FC_BA_RJT_INV_XID); + bf_set(xmit_bls_rsp64_rjt_rsnc, &icmd->xmit_bls_rsp, + FC_BA_RJT_UNABLE); } if (fctl & FC_FC_EX_CTX) { @@ -18996,28 +18625,40 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, * of BA_ACC will use OX_ID from ABTS for the XRI_TAG * field and RX_ID from ABTS for RX_ID field. */ - bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_RSP); + ctiocb->abort_bls = LPFC_ABTS_UNSOL_RSP; + bf_set(xmit_bls_rsp64_rxid, &icmd->xmit_bls_rsp, rxid); } else { /* ABTS sent by initiator to CT exchange, construction * of BA_ACC will need to allocate a new XRI as for the * XRI_TAG field. */ - bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_INT); + ctiocb->abort_bls = LPFC_ABTS_UNSOL_INT; } - bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, rxid); - bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid); + + /* OX_ID is invariable to who sent ABTS to CT exchange */ + bf_set(xmit_bls_rsp64_oxid, &icmd->xmit_bls_rsp, oxid); + bf_set(xmit_bls_rsp64_oxid, &icmd->xmit_bls_rsp, rxid); + + /* Use CT=VPI */ + bf_set(wqe_els_did, &icmd->xmit_bls_rsp.wqe_dest, + ndlp->nlp_DID); + bf_set(xmit_bls_rsp64_temprpi, &icmd->xmit_bls_rsp, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + bf_set(wqe_cmnd, &icmd->generic.wqe_com, CMD_XMIT_BLS_RSP64_CX); + /* Xmit CT abts response on exchange <xid> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n", - icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state); + ctiocb->abort_rctl, oxid, phba->link_state); + lpfc_sli_prep_wqe(phba, ctiocb); rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); if (rc == IOCB_ERROR) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2925 Failed to issue CT ABTS RSP x%x on " "xri x%x, Data x%x\n", - icmd->un.xseq64.w5.hcsw.Rctl, oxid, + ctiocb->abort_rctl, oxid, phba->link_state); lpfc_nlp_put(ndlp); ctiocb->context1 = NULL; @@ -19140,7 +18781,6 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) struct fc_frame_header *fc_hdr; uint32_t sid; uint32_t len, tot_len; - struct ulp_bde64 *pbde; fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; /* remove from receive buffer list */ @@ -19153,40 +18793,40 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) first_iocbq = lpfc_sli_get_iocbq(vport->phba); if (first_iocbq) { /* Initialize the first IOCB. */ - first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0; - first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; + first_iocbq->wcqe_cmpl.total_data_placed = 0; + bf_set(lpfc_wcqe_c_status, &first_iocbq->wcqe_cmpl, + IOSTAT_SUCCESS); first_iocbq->vport = vport; /* Check FC Header to see what TYPE of frame we are rcv'ing */ if (sli4_type_from_fc_hdr(fc_hdr) == FC_TYPE_ELS) { - first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_ELS64_CX; - first_iocbq->iocb.un.rcvels.parmRo = - sli4_did_from_fc_hdr(fc_hdr); - first_iocbq->iocb.ulpPU = PARM_NPIV_DID; - } else - first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; - first_iocbq->iocb.ulpContext = NO_XRI; - first_iocbq->iocb.unsli3.rcvsli3.ox_id = - be16_to_cpu(fc_hdr->fh_ox_id); - /* iocbq is prepped for internal consumption. Physical vpi. */ - first_iocbq->iocb.unsli3.rcvsli3.vpi = - vport->phba->vpi_ids[vport->vpi]; - /* put the first buffer into the first IOCBq */ + bf_set(els_rsp64_sid, &first_iocbq->wqe.xmit_els_rsp, + sli4_did_from_fc_hdr(fc_hdr)); + } + + bf_set(wqe_ctxt_tag, &first_iocbq->wqe.xmit_els_rsp.wqe_com, + NO_XRI); + bf_set(wqe_rcvoxid, &first_iocbq->wqe.xmit_els_rsp.wqe_com, + be16_to_cpu(fc_hdr->fh_ox_id)); + + /* put the first buffer into the first iocb */ tot_len = bf_get(lpfc_rcqe_length, - &seq_dmabuf->cq_event.cqe.rcqe_cmpl); + &seq_dmabuf->cq_event.cqe.rcqe_cmpl); first_iocbq->context2 = &seq_dmabuf->dbuf; first_iocbq->context3 = NULL; - first_iocbq->iocb.ulpBdeCount = 1; + /* Keep track of the BDE count */ + first_iocbq->wcqe_cmpl.word3 = 1; + if (tot_len > LPFC_DATA_BUF_SIZE) - first_iocbq->iocb.un.cont64[0].tus.f.bdeSize = - LPFC_DATA_BUF_SIZE; + first_iocbq->wqe.gen_req.bde.tus.f.bdeSize = + LPFC_DATA_BUF_SIZE; else - first_iocbq->iocb.un.cont64[0].tus.f.bdeSize = tot_len; - - first_iocbq->iocb.un.rcvels.remoteID = sid; + first_iocbq->wqe.gen_req.bde.tus.f.bdeSize = tot_len; - first_iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len; + first_iocbq->wcqe_cmpl.total_data_placed = tot_len; + bf_set(wqe_els_did, &first_iocbq->wqe.xmit_els_rsp.wqe_dest, + sid); } iocbq = first_iocbq; /* @@ -19200,28 +18840,23 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) } if (!iocbq->context3) { iocbq->context3 = d_buf; - iocbq->iocb.ulpBdeCount++; + iocbq->wcqe_cmpl.word3++; /* We need to get the size out of the right CQE */ hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); len = bf_get(lpfc_rcqe_length, &hbq_buf->cq_event.cqe.rcqe_cmpl); - pbde = (struct ulp_bde64 *) - &iocbq->iocb.unsli3.sli3Words[4]; - if (len > LPFC_DATA_BUF_SIZE) - pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE; - else - pbde->tus.f.bdeSize = len; - - iocbq->iocb.unsli3.rcvsli3.acc_len += len; + iocbq->unsol_rcv_len = len; + iocbq->wcqe_cmpl.total_data_placed += len; tot_len += len; } else { iocbq = lpfc_sli_get_iocbq(vport->phba); if (!iocbq) { if (first_iocbq) { - first_iocbq->iocb.ulpStatus = - IOSTAT_FCP_RSP_ERROR; - first_iocbq->iocb.un.ulpWord[4] = - IOERR_NO_RESOURCES; + bf_set(lpfc_wcqe_c_status, + &first_iocbq->wcqe_cmpl, + IOSTAT_SUCCESS); + first_iocbq->wcqe_cmpl.parameter = + IOERR_NO_RESOURCES; } lpfc_in_buf_free(vport->phba, d_buf); continue; @@ -19232,17 +18867,19 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) &hbq_buf->cq_event.cqe.rcqe_cmpl); iocbq->context2 = d_buf; iocbq->context3 = NULL; - iocbq->iocb.ulpBdeCount = 1; + iocbq->wcqe_cmpl.word3 = 1; + if (len > LPFC_DATA_BUF_SIZE) - iocbq->iocb.un.cont64[0].tus.f.bdeSize = - LPFC_DATA_BUF_SIZE; + iocbq->wqe.xmit_els_rsp.bde.tus.f.bdeSize = + LPFC_DATA_BUF_SIZE; else - iocbq->iocb.un.cont64[0].tus.f.bdeSize = len; + iocbq->wqe.xmit_els_rsp.bde.tus.f.bdeSize = + len; tot_len += len; - iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len; - - iocbq->iocb.un.rcvels.remoteID = sid; + iocbq->wcqe_cmpl.total_data_placed = tot_len; + bf_set(wqe_els_did, &iocbq->wqe.xmit_els_rsp.wqe_dest, + sid); list_add_tail(&iocbq->list, &first_iocbq->list); } } @@ -19310,7 +18947,7 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, struct fc_frame_header *fc_hdr; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocbq = NULL; - union lpfc_wqe *wqe; + union lpfc_wqe128 *pwqe; struct lpfc_dmabuf *pcmd = NULL; uint32_t frame_len; int rc; @@ -19345,34 +18982,46 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, /* copyin the payload */ memcpy(pcmd->virt, dmabuf->dbuf.virt, frame_len); - /* fill in BDE's for command */ - iocbq->iocb.un.xseq64.bdl.addrHigh = putPaddrHigh(pcmd->phys); - iocbq->iocb.un.xseq64.bdl.addrLow = putPaddrLow(pcmd->phys); - iocbq->iocb.un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDE_64; - iocbq->iocb.un.xseq64.bdl.bdeSize = frame_len; - iocbq->context2 = pcmd; iocbq->vport = vport; - iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; - iocbq->iocb_flag |= LPFC_USE_FCPWQIDX; + iocbq->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; + iocbq->cmd_flag |= LPFC_USE_FCPWQIDX; + iocbq->num_bdes = 0; + + pwqe = &iocbq->wqe; + /* fill in BDE's for command */ + pwqe->gen_req.bde.addrHigh = putPaddrHigh(pcmd->phys); + pwqe->gen_req.bde.addrLow = putPaddrLow(pcmd->phys); + pwqe->gen_req.bde.tus.f.bdeSize = frame_len; + pwqe->gen_req.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + + pwqe->send_frame.frame_len = frame_len; + pwqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((__be32 *)fc_hdr)); + pwqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((__be32 *)fc_hdr + 1)); + pwqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((__be32 *)fc_hdr + 2)); + pwqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((__be32 *)fc_hdr + 3)); + pwqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((__be32 *)fc_hdr + 4)); + pwqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((__be32 *)fc_hdr + 5)); + + pwqe->generic.wqe_com.word7 = 0; + pwqe->generic.wqe_com.word10 = 0; + + bf_set(wqe_cmnd, &pwqe->generic.wqe_com, CMD_SEND_FRAME); + bf_set(wqe_sof, &pwqe->generic.wqe_com, 0x2E); /* SOF byte */ + bf_set(wqe_eof, &pwqe->generic.wqe_com, 0x41); /* EOF byte */ + bf_set(wqe_lenloc, &pwqe->generic.wqe_com, 1); + bf_set(wqe_xbl, &pwqe->generic.wqe_com, 1); + bf_set(wqe_dbde, &pwqe->generic.wqe_com, 1); + bf_set(wqe_xc, &pwqe->generic.wqe_com, 1); + bf_set(wqe_cmd_type, &pwqe->generic.wqe_com, 0xA); + bf_set(wqe_cqid, &pwqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_xri_tag, &pwqe->generic.wqe_com, iocbq->sli4_xritag); + bf_set(wqe_reqtag, &pwqe->generic.wqe_com, iocbq->iotag); + bf_set(wqe_class, &pwqe->generic.wqe_com, CLASS3); + pwqe->generic.wqe_com.abort_tag = iocbq->iotag; + + iocbq->cmd_cmpl = lpfc_sli4_mds_loopback_cmpl; - /* - * Setup rest of the iocb as though it were a WQE - * Build the SEND_FRAME WQE - */ - wqe = (union lpfc_wqe *)&iocbq->iocb; - - wqe->send_frame.frame_len = frame_len; - wqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((uint32_t *)fc_hdr)); - wqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((uint32_t *)fc_hdr + 1)); - wqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((uint32_t *)fc_hdr + 2)); - wqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((uint32_t *)fc_hdr + 3)); - wqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((uint32_t *)fc_hdr + 4)); - wqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((uint32_t *)fc_hdr + 5)); - - iocbq->iocb.ulpCommand = CMD_SEND_FRAME; - iocbq->iocb.ulpLe = 1; - iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0); if (rc == IOCB_ERROR) goto exit; @@ -21087,10 +20736,9 @@ lpfc_drain_txq(struct lpfc_hba *phba) struct lpfc_iocbq *piocbq = NULL; unsigned long iflags = 0; char *fail_msg = NULL; - struct lpfc_sglq *sglq; - union lpfc_wqe128 wqe; uint32_t txq_cnt = 0; struct lpfc_queue *wq; + int ret = 0; if (phba->link_flag & LS_MDS_LOOPBACK) { /* MDS WQE are posted only to first WQ*/ @@ -21129,44 +20777,33 @@ lpfc_drain_txq(struct lpfc_hba *phba) txq_cnt); break; } - sglq = __lpfc_sli_get_els_sglq(phba, piocbq); - if (!sglq) { - __lpfc_sli_ringtx_put(phba, pring, piocbq); - spin_unlock_irqrestore(&pring->ring_lock, iflags); - break; - } txq_cnt--; - /* The xri and iocb resources secured, - * attempt to issue request - */ - piocbq->sli4_lxritag = sglq->sli4_lxritag; - piocbq->sli4_xritag = sglq->sli4_xritag; - if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) - fail_msg = "to convert bpl to sgl"; - else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) - fail_msg = "to convert iocb to wqe"; - else if (lpfc_sli4_wq_put(wq, &wqe)) - fail_msg = " - Wq is full"; - else - lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); + ret = __lpfc_sli_issue_iocb(phba, pring->ringno, piocbq, 0); + if (ret && ret != IOCB_BUSY) { + fail_msg = " - Cannot send IO "; + piocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; + } if (fail_msg) { + piocbq->cmd_flag |= LPFC_DRIVER_ABORTED; /* Failed means we can't issue and need to cancel */ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2822 IOCB failed %s iotag 0x%x " - "xri 0x%x\n", - fail_msg, - piocbq->iotag, piocbq->sli4_xritag); + "xri 0x%x %d flg x%x\n", + fail_msg, piocbq->iotag, + piocbq->sli4_xritag, ret, + piocbq->cmd_flag); list_add_tail(&piocbq->list, &completions); fail_msg = NULL; } spin_unlock_irqrestore(&pring->ring_lock, iflags); + if (txq_cnt == 0 || ret == IOCB_BUSY) + break; } - /* Cancel all the IOCBs that cannot be issued */ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, - IOERR_SLI_ABORTED); + IOERR_SLI_ABORTED); return txq_cnt; } @@ -21214,7 +20851,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, cmd = bf_get(wqe_cmnd, &wqe->generic.wqe_com); if (cmd == CMD_XMIT_BLS_RSP64_WQE) return sglq->sli4_xritag; - numBdes = pwqeq->rsvd2; + numBdes = pwqeq->num_bdes; if (numBdes) { /* The addrHigh and addrLow fields within the WQE * have not been byteswapped yet so there is no @@ -21315,7 +20952,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, uint32_t ret = 0; /* NVME_LS and NVME_LS ABTS requests. */ - if (pwqe->iocb_flag & LPFC_IO_NVME_LS) { + if (pwqe->cmd_flag & LPFC_IO_NVME_LS) { pring = phba->sli4_hba.nvmels_wq->pring; lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags, qp, wq_access); @@ -21346,7 +20983,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, } /* NVME_FCREQ and NVME_ABTS requests */ - if (pwqe->iocb_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { + if (pwqe->cmd_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ wq = qp->io_wq; pring = wq->pring; @@ -21368,7 +21005,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, } /* NVMET requests */ - if (pwqe->iocb_flag & LPFC_IO_NVMET) { + if (pwqe->cmd_flag & LPFC_IO_NVMET) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ wq = qp->io_wq; pring = wq->pring; @@ -21434,7 +21071,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return WQE_NORESOURCE; /* Indicate the IO is being aborted by the driver. */ - cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; + cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; abtswqe = &abtsiocb->wqe; memset(abtswqe, 0, sizeof(*abtswqe)); @@ -21453,15 +21090,15 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocb->hba_wqidx = cmdiocb->hba_wqidx; - abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; - if (cmdiocb->iocb_flag & LPFC_IO_FCP) - abtsiocb->iocb_flag |= LPFC_IO_FCP; - if (cmdiocb->iocb_flag & LPFC_IO_NVME) - abtsiocb->iocb_flag |= LPFC_IO_NVME; - if (cmdiocb->iocb_flag & LPFC_IO_FOF) - abtsiocb->iocb_flag |= LPFC_IO_FOF; + abtsiocb->cmd_flag |= LPFC_USE_FCPWQIDX; + if (cmdiocb->cmd_flag & LPFC_IO_FCP) + abtsiocb->cmd_flag |= LPFC_IO_FCP; + if (cmdiocb->cmd_flag & LPFC_IO_NVME) + abtsiocb->cmd_flag |= LPFC_IO_NVME; + if (cmdiocb->cmd_flag & LPFC_IO_FOF) + abtsiocb->cmd_flag |= LPFC_IO_FOF; abtsiocb->vport = vport; - abtsiocb->wqe_cmpl = cmpl; + abtsiocb->cmd_cmpl = cmpl; lpfc_cmd = container_of(cmdiocb, struct lpfc_io_buf, cur_iocbq); retval = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, abtsiocb); @@ -21472,7 +21109,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, xritag, cmdiocb->iotag, abtsiocb->iotag, retval); if (retval) { - cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; __lpfc_sli_release_iocbq(phba, abtsiocb); } @@ -21834,8 +21471,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, /* MUST zero fields if buffer is reused by another protocol */ lpfc_ncmd->nvmeCmd = NULL; - lpfc_ncmd->cur_iocbq.wqe_cmpl = NULL; - lpfc_ncmd->cur_iocbq.iocb_cmpl = NULL; + lpfc_ncmd->cur_iocbq.cmd_cmpl = NULL; if (phba->cfg_xpsgl && !phba->nvmet_support && !list_empty(&lpfc_ncmd->dma_sgl_xtra_list)) @@ -22549,3 +22185,192 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags); } + +/** + * lpfc_sli_prep_wqe - Prepare WQE for the command to be posted + * @phba: phba object + * @job: job entry of the command to be posted. + * + * Fill the common fields of the wqe for each of the command. + * + * Return codes: + * None + **/ +void +lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job) +{ + u8 cmnd; + u32 *pcmd; + u32 if_type = 0; + u32 fip, abort_tag; + struct lpfc_nodelist *ndlp = NULL; + union lpfc_wqe128 *wqe = &job->wqe; + struct lpfc_dmabuf *context2; + u32 els_id = LPFC_ELS_ID_DEFAULT; + u8 command_type = ELS_COMMAND_NON_FIP; + + fip = phba->hba_flag & HBA_FIP_SUPPORT; + /* The fcp commands will set command type */ + if (job->cmd_flag & LPFC_IO_FCP) + command_type = FCP_COMMAND; + else if (fip && (job->cmd_flag & LPFC_FIP_ELS_ID_MASK)) + command_type = ELS_COMMAND_FIP; + else + command_type = ELS_COMMAND_NON_FIP; + + abort_tag = job->iotag; + cmnd = bf_get(wqe_cmnd, &wqe->els_req.wqe_com); + + switch (cmnd) { + case CMD_ELS_REQUEST64_WQE: + if (job->cmd_flag & LPFC_IO_LIBDFC) + ndlp = job->context_un.ndlp; + else + ndlp = (struct lpfc_nodelist *)job->context1; + + /* CCP CCPE PV PRI in word10 were set in the memcpy */ + if (command_type == ELS_COMMAND_FIP) + els_id = ((job->cmd_flag & LPFC_FIP_ELS_ID_MASK) + >> LPFC_FIP_ELS_ID_SHIFT); + + if_type = bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf); + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { + context2 = (struct lpfc_dmabuf *)job->context2; + pcmd = (u32 *)context2->virt; + if (pcmd && (*pcmd == ELS_CMD_FLOGI || + *pcmd == ELS_CMD_SCR || + *pcmd == ELS_CMD_RDF || + *pcmd == ELS_CMD_EDC || + *pcmd == ELS_CMD_RSCN_XMT || + *pcmd == ELS_CMD_FDISC || + *pcmd == ELS_CMD_LOGO || + *pcmd == ELS_CMD_QFPA || + *pcmd == ELS_CMD_UVEM || + *pcmd == ELS_CMD_PLOGI)) { + bf_set(els_req64_sp, &wqe->els_req, 1); + bf_set(els_req64_sid, &wqe->els_req, + job->vport->fc_myDID); + + if ((*pcmd == ELS_CMD_FLOGI) && + !(phba->fc_topology == + LPFC_TOPOLOGY_LOOP)) + bf_set(els_req64_sid, &wqe->els_req, 0); + + bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->vpi_ids[job->vport->vpi]); + } else if (pcmd) { + bf_set(wqe_ct, &wqe->els_req.wqe_com, 0); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + } + } + + bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + + bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); + bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); + break; + case CMD_XMIT_ELS_RSP64_WQE: + ndlp = (struct lpfc_nodelist *)job->context1; + + /* word4 */ + wqe->xmit_els_rsp.word4 = 0; + + if_type = bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf); + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { + if (job->vport->fc_flag & FC_PT2PT) { + bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); + bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, + job->vport->fc_myDID); + if (job->vport->fc_myDID == Fabric_DID) { + bf_set(wqe_els_did, + &wqe->xmit_els_rsp.wqe_dest, 0); + } + } + } + + bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, + LPFC_WQE_LENLOC_WORD3); + bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); + + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); + bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, + job->vport->fc_myDID); + bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1); + } + + if (phba->sli_rev == LPFC_SLI_REV4) { + bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + + if (bf_get(wqe_ct, &wqe->xmit_els_rsp.wqe_com)) + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, + phba->vpi_ids[job->vport->vpi]); + } + command_type = OTHER_COMMAND; + break; + case CMD_GEN_REQUEST64_WQE: + /* Word 10 */ + bf_set(wqe_dbde, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->gen_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); + command_type = OTHER_COMMAND; + break; + case CMD_XMIT_SEQUENCE64_WQE: + if (phba->link_flag & LS_LOOPBACK_MODE) + bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1); + + wqe->xmit_sequence.rsvd3 = 0; + bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0); + bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_LENLOC_WORD12); + bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0); + command_type = OTHER_COMMAND; + break; + case CMD_XMIT_BLS_RSP64_WQE: + bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); + bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); + bf_set(wqe_ct, &wqe->xmit_bls_rsp.wqe_com, 1); + bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, + phba->vpi_ids[phba->pport->vpi]); + bf_set(wqe_qosd, &wqe->xmit_bls_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com, + LPFC_WQE_LENLOC_NONE); + /* Overwrite the pre-set comnd type with OTHER_COMMAND */ + command_type = OTHER_COMMAND; + break; + case CMD_FCP_ICMND64_WQE: /* task mgmt commands */ + case CMD_ABORT_XRI_WQE: /* abort iotag */ + case CMD_SEND_FRAME: /* mds loopback */ + /* cases already formatted for sli4 wqe - no chgs necessary */ + return; + default: + dump_stack(); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "6207 Invalid command 0x%x\n", + cmnd); + break; + } + + wqe->generic.wqe_com.abort_tag = abort_tag; + bf_set(wqe_reqtag, &wqe->generic.wqe_com, job->iotag); + bf_set(wqe_cmd_type, &wqe->generic.wqe_com, command_type); + bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); +} diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 5161ccacea3e..663cc90a8798 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -35,7 +35,7 @@ typedef enum _lpfc_ctx_cmd { LPFC_CTX_HOST } lpfc_ctx_cmd; -union lpfc_vmid_iocb_tag { +union lpfc_vmid_tag { uint32_t app_id; uint8_t cs_ctl_vmid; struct lpfc_vmid_context *vmid_context; /* UVEM context information */ @@ -69,16 +69,21 @@ struct lpfc_iocbq { uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ uint16_t hba_wqidx; /* index to HBA work queue */ struct lpfc_cq_event cq_event; - struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ uint64_t isr_timestamp; union lpfc_wqe128 wqe; /* SLI-4 */ IOCB_t iocb; /* SLI-3 */ + struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ - uint8_t rsvd2; + u32 unsol_rcv_len; /* Receive len in usol path */ + + uint8_t num_bdes; + uint8_t abort_bls; /* ABTS by initiator or responder */ + u8 abort_rctl; /* ACC or RJT flag */ uint8_t priority; /* OAS priority */ uint8_t retry; /* retry counter for IOCB cmd - if needed */ - uint32_t iocb_flag; + + u32 cmd_flag; #define LPFC_IO_LIBDFC 1 /* libdfc iocb */ #define LPFC_IO_WAKE 2 /* Synchronous I/O completed */ #define LPFC_IO_WAKE_TMO LPFC_IO_WAKE /* Synchronous I/O timed out */ @@ -123,15 +128,13 @@ struct lpfc_iocbq { struct lpfc_node_rrq *rrq; } context_un; - union lpfc_vmid_iocb_tag vmid_tag; - void (*fabric_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_iocbq *); - void (*wait_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_iocbq *); - void (*iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_iocbq *); - void (*wqe_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_wcqe_complete *); + union lpfc_vmid_tag vmid_tag; + void (*fabric_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, + struct lpfc_iocbq *rsp); + void (*wait_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, + struct lpfc_iocbq *rsp); + void (*cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, + struct lpfc_iocbq *rsp); }; #define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */ diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 5962cf508842..e0c25699f4b8 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 2e9348a6897c..e52f37e5d896 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.0.0.4" +#define LPFC_DRIVER_VERSION "14.2.0.0" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ @@ -32,6 +32,6 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright (C) 2017-2021 Broadcom. All Rights " \ +#define LPFC_COPYRIGHT "Copyright (C) 2017-2022 Broadcom. All Rights " \ "Reserved. The term \"Broadcom\" refers to Broadcom Inc. " \ "and/or its subsidiaries." |