[SCSI] lpfc 8.3.29: SLI related fixes

SLI related fixes:

- Fix REG_RPI fails on SLI4 HBA putting NPort into NPR state (126230)
- Fix ELS FDISC failing with local reject / invalid RPI. (126350)
- Fix reset port when reset is needed during fw_dump (125807)
- Fix unbounded firmware revision string from port cause panic (126560)
- Fix driver behavior when receiving an ADISC (126654)
- Fix driver not returning when bad ndlp found in abts error event
  handling (126209)
- Add more driver logs in area of SLI4 port error attention and reset
  recovery (126813, 124466)
- Fix failure in handling large CQ/EQ identifiers in an IOV
  environment (126856)
- Fix for driver using duplicate RPIs after lancer port reset (126723)
- Clear vport->fc_myDID in lpfc_els_issue_fdisc to guarentee a
  zero SID (126779, 126897)
- Fix for SLI4 Port delivery for BLS ABORT ACC (126289)

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
James Smart 2012-01-18 16:24:06 -05:00 committed by James Bottomley
parent 3ef6d24cd9
commit 6b5151fd7b
11 changed files with 207 additions and 34 deletions

View File

@ -353,7 +353,7 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
uint32_t if_type; uint32_t if_type;
uint8_t sli_family; uint8_t sli_family;
char fwrev[32]; char fwrev[FW_REV_STR_SIZE];
int len; int len;
lpfc_decode_firmware_rev(phba, fwrev, 1); lpfc_decode_firmware_rev(phba, fwrev, 1);
@ -922,11 +922,15 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
rc = lpfc_sli4_pdev_status_reg_wait(phba); rc = lpfc_sli4_pdev_status_reg_wait(phba);
if (rc == -EPERM) { if (rc == -EPERM) {
/* no privilage for reset, restore if needed */ /* no privilage for reset */
if (before_fc_flag & FC_OFFLINE_MODE) lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
goto out; "3150 No privilage to perform the requested "
"access: x%x\n", reg_val);
} else if (rc == -EIO) { } else if (rc == -EIO) {
/* reset failed, there is nothing more we can do */ /* reset failed, there is nothing more we can do */
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3153 Fail to perform the requested "
"access: x%x\n", reg_val);
return rc; return rc;
} }

View File

@ -3980,7 +3980,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES: case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"3106 Handled SLI_CONFIG " "3106 Handled SLI_CONFIG "
"subsys_fcoe, opcode:x%x\n", "subsys_comn, opcode:x%x\n",
opcode); opcode);
rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
nemb_mse, dmabuf); nemb_mse, dmabuf);
@ -3988,7 +3988,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
default: default:
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"3107 Reject SLI_CONFIG " "3107 Reject SLI_CONFIG "
"subsys_fcoe, opcode:x%x\n", "subsys_comn, opcode:x%x\n",
opcode); opcode);
rc = -EPERM; rc = -EPERM;
break; break;

View File

@ -462,3 +462,4 @@ int lpfc_issue_unreg_vfi(struct lpfc_vport *);
int lpfc_selective_reset(struct lpfc_hba *); int lpfc_selective_reset(struct lpfc_hba *);
int lpfc_sli4_read_config(struct lpfc_hba *phba); int lpfc_sli4_read_config(struct lpfc_hba *phba);
int lpfc_scsi_buf_update(struct lpfc_hba *phba); int lpfc_scsi_buf_update(struct lpfc_hba *phba);
void lpfc_sli4_node_prep(struct lpfc_hba *phba);

View File

@ -1076,7 +1076,7 @@ int
lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
size_t size) size_t size)
{ {
char fwrev[16]; char fwrev[FW_REV_STR_SIZE];
int n; int n;
lpfc_decode_firmware_rev(vport->phba, fwrev, 0); lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
@ -1834,7 +1834,7 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
uint8_t *fwname; uint8_t *fwname;
if (phba->sli_rev == LPFC_SLI_REV4) if (phba->sli_rev == LPFC_SLI_REV4)
sprintf(fwrevision, "%s", vp->rev.opFwName); snprintf(fwrevision, FW_REV_STR_SIZE, "%s", vp->rev.opFwName);
else if (vp->rev.rBit) { else if (vp->rev.rBit) {
if (psli->sli_flag & LPFC_SLI_ACTIVE) if (psli->sli_flag & LPFC_SLI_ACTIVE)
rev = vp->rev.sli2FwRev; rev = vp->rev.sli2FwRev;

View File

@ -7172,7 +7172,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out; goto out;
/* FDISC failed */ /* FDISC failed */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"0126 FDISC failed. (%d/%d)\n", "0126 FDISC failed. (x%x/x%x)\n",
irsp->ulpStatus, irsp->un.ulpWord[4]); irsp->ulpStatus, irsp->un.ulpWord[4]);
goto fdisc_failed; goto fdisc_failed;
} }
@ -7283,6 +7283,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
int rc; int rc;
vport->port_state = LPFC_FDISC; vport->port_state = LPFC_FDISC;
vport->fc_myDID = 0;
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
ELS_CMD_FDISC); ELS_CMD_FDISC);

View File

@ -70,6 +70,7 @@
/* vendor ID used in SCSI netlink calls */ /* vendor ID used in SCSI netlink calls */
#define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX) #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX)
#define FW_REV_STR_SIZE 32
/* Common Transport structures and definitions */ /* Common Transport structures and definitions */
union CtRevisionId { union CtRevisionId {

View File

@ -715,12 +715,20 @@ struct lpfc_register {
#define lpfc_eqcq_doorbell_eqci_SHIFT 9 #define lpfc_eqcq_doorbell_eqci_SHIFT 9
#define lpfc_eqcq_doorbell_eqci_MASK 0x0001 #define lpfc_eqcq_doorbell_eqci_MASK 0x0001
#define lpfc_eqcq_doorbell_eqci_WORD word0 #define lpfc_eqcq_doorbell_eqci_WORD word0
#define lpfc_eqcq_doorbell_cqid_SHIFT 0 #define lpfc_eqcq_doorbell_cqid_lo_SHIFT 0
#define lpfc_eqcq_doorbell_cqid_MASK 0x03FF #define lpfc_eqcq_doorbell_cqid_lo_MASK 0x03FF
#define lpfc_eqcq_doorbell_cqid_WORD word0 #define lpfc_eqcq_doorbell_cqid_lo_WORD word0
#define lpfc_eqcq_doorbell_eqid_SHIFT 0 #define lpfc_eqcq_doorbell_cqid_hi_SHIFT 11
#define lpfc_eqcq_doorbell_eqid_MASK 0x01FF #define lpfc_eqcq_doorbell_cqid_hi_MASK 0x001F
#define lpfc_eqcq_doorbell_eqid_WORD word0 #define lpfc_eqcq_doorbell_cqid_hi_WORD word0
#define lpfc_eqcq_doorbell_eqid_lo_SHIFT 0
#define lpfc_eqcq_doorbell_eqid_lo_MASK 0x01FF
#define lpfc_eqcq_doorbell_eqid_lo_WORD word0
#define lpfc_eqcq_doorbell_eqid_hi_SHIFT 11
#define lpfc_eqcq_doorbell_eqid_hi_MASK 0x001F
#define lpfc_eqcq_doorbell_eqid_hi_WORD word0
#define LPFC_CQID_HI_FIELD_SHIFT 10
#define LPFC_EQID_HI_FIELD_SHIFT 9
#define LPFC_BMBX 0x0160 #define LPFC_BMBX 0x0160
#define lpfc_bmbx_addr_SHIFT 2 #define lpfc_bmbx_addr_SHIFT 2
@ -3313,7 +3321,11 @@ struct xmit_bls_rsp64_wqe {
uint32_t rsrvd4; uint32_t rsrvd4;
struct wqe_did wqe_dest; struct wqe_did wqe_dest;
struct wqe_common wqe_com; /* words 6-11 */ struct wqe_common wqe_com; /* words 6-11 */
uint32_t rsvd_12_15[4]; uint32_t word12;
#define xmit_bls_rsp64_temprpi_SHIFT 0
#define xmit_bls_rsp64_temprpi_MASK 0x0000ffff
#define xmit_bls_rsp64_temprpi_WORD word12
uint32_t rsvd_13_15[3];
}; };
struct wqe_rctl_dfctl { struct wqe_rctl_dfctl {

View File

@ -1475,8 +1475,12 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
phba->sli4_hba.u.if_type2.STATUSregaddr, phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0); &portstat_reg.word0);
/* consider PCI bus read error as pci_channel_offline */ /* consider PCI bus read error as pci_channel_offline */
if (pci_rd_rc1 == -EIO) if (pci_rd_rc1 == -EIO) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3151 PCI bus read access failure: x%x\n",
readl(phba->sli4_hba.u.if_type2.STATUSregaddr));
return; return;
}
reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr); reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
@ -1526,6 +1530,9 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
} }
/* fall through for not able to recover */ /* fall through for not able to recover */
} }
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3152 Unrecoverable error, bring the port "
"offline\n");
lpfc_sli4_offline_eratt(phba); lpfc_sli4_offline_eratt(phba);
break; break;
case LPFC_SLI_INTF_IF_TYPE_1: case LPFC_SLI_INTF_IF_TYPE_1:
@ -2513,6 +2520,42 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
} }
} }
/**
* lpfc_sli4_node_prep - Assign RPIs for active nodes.
* @phba: pointer to lpfc hba data structure.
*
* Allocate RPIs for all active remote nodes. This is needed whenever
* an SLI4 adapter is reset and the driver is not unloading. Its purpose
* is to fixup the temporary rpi assignments.
**/
void
lpfc_sli4_node_prep(struct lpfc_hba *phba)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
struct lpfc_vport **vports;
int i;
if (phba->sli_rev != LPFC_SLI_REV4)
return;
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) {
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
if (vports[i]->load_flag & FC_UNLOADING)
continue;
list_for_each_entry_safe(ndlp, next_ndlp,
&vports[i]->fc_nodes,
nlp_listp) {
if (NLP_CHK_NODE_ACT(ndlp))
ndlp->nlp_rpi =
lpfc_sli4_alloc_rpi(phba);
}
}
}
lpfc_destroy_vport_work_array(phba, vports);
}
/** /**
* lpfc_online - Initialize and bring a HBA online * lpfc_online - Initialize and bring a HBA online
* @phba: pointer to lpfc hba data structure. * @phba: pointer to lpfc hba data structure.
@ -2654,6 +2697,15 @@ lpfc_offline_prep(struct lpfc_hba * phba)
} }
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC; ndlp->nlp_flag &= ~NLP_NPR_ADISC;
/*
* Whenever an SLI4 port goes offline, free the
* RPI. A new RPI when the adapter port comes
* back online.
*/
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
lpfc_unreg_rpi(vports[i], ndlp); lpfc_unreg_rpi(vports[i], ndlp);
} }
@ -7224,19 +7276,17 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
} }
if (bf_get(lpfc_sliport_status_rn, &reg_data))
reset_again++;
if (bf_get(lpfc_sliport_status_rdy, &reg_data)) if (bf_get(lpfc_sliport_status_rdy, &reg_data))
break; break;
if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
reset_again++;
break;
}
} }
/* /*
* If the port responds to the init request with * If the port responds to the init request with
* reset needed, delay for a bit and restart the loop. * reset needed, delay for a bit and restart the loop.
*/ */
if (reset_again) { if (reset_again && (rdy_chk < 1000)) {
msleep(10); msleep(10);
reset_again = 0; reset_again = 0;
continue; continue;
@ -9059,7 +9109,7 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
int int
lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
{ {
char fwrev[32]; char fwrev[FW_REV_STR_SIZE];
struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data; struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data;
struct list_head dma_buffer_list; struct list_head dma_buffer_list;
int i, rc = 0; int i, rc = 0;

View File

@ -48,6 +48,10 @@ static int
lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_name *nn, struct lpfc_name *pn) struct lpfc_name *nn, struct lpfc_name *pn)
{ {
/* First, we MUST have a RPI registered */
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
return 0;
/* Compare the ADISC rsp WWNN / WWPN matches our internal node /* Compare the ADISC rsp WWNN / WWPN matches our internal node
* table entry for that node. * table entry for that node.
*/ */
@ -385,6 +389,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!mbox) if (!mbox)
goto out; goto out;
/* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_unreg_rpi(vport, ndlp);
rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID, rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
(uint8_t *) sp, mbox, ndlp->nlp_rpi); (uint8_t *) sp, mbox, ndlp->nlp_rpi);
if (rc) { if (rc) {
@ -445,11 +453,42 @@ out:
return 0; return 0;
} }
/**
* lpfc_mbx_cmpl_resume_rpi - Resume RPI completion routine
* @phba: pointer to lpfc hba data structure.
* @mboxq: pointer to mailbox object
*
* This routine is invoked to issue a completion to a rcv'ed
* ADISC or PDISC after the paused RPI has been resumed.
**/
static void
lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport;
struct lpfc_iocbq *elsiocb;
struct lpfc_nodelist *ndlp;
uint32_t cmd;
elsiocb = (struct lpfc_iocbq *)mboxq->context1;
ndlp = (struct lpfc_nodelist *) mboxq->context2;
vport = mboxq->vport;
cmd = elsiocb->drvrTimeout;
if (cmd == ELS_CMD_ADISC) {
lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);
} else {
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,
ndlp, NULL);
}
kfree(elsiocb);
}
static int static int
lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb) struct lpfc_iocbq *cmdiocb)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *elsiocb;
struct lpfc_dmabuf *pcmd; struct lpfc_dmabuf *pcmd;
struct serv_parm *sp; struct serv_parm *sp;
struct lpfc_name *pnn, *ppn; struct lpfc_name *pnn, *ppn;
@ -475,12 +514,43 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd = &cmdiocb->iocb; icmd = &cmdiocb->iocb;
if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) { if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
/*
* As soon as we send ACC, the remote NPort can
* start sending us data. Thus, for SLI4 we must
* resume the RPI before the ACC goes out.
*/
if (vport->phba->sli_rev == LPFC_SLI_REV4) {
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));
/* Save the ELS cmd */
elsiocb->drvrTimeout = cmd;
lpfc_sli4_resume_rpi(ndlp,
lpfc_mbx_cmpl_resume_rpi, elsiocb);
goto out;
}
}
if (cmd == ELS_CMD_ADISC) { if (cmd == ELS_CMD_ADISC) {
lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
} else { } else {
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
NULL); ndlp, NULL);
} }
out:
/* If we are authenticated, move to the proper state */
if (ndlp->nlp_type & NLP_FCP_TARGET)
lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
else
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
return 1; return 1;
} }
/* Reject this request because invalid parameters */ /* Reject this request because invalid parameters */
@ -1229,7 +1299,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
} }
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
rc = lpfc_sli4_resume_rpi(ndlp); rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);
if (rc) { if (rc) {
/* Stay in state and retry. */ /* Stay in state and retry. */
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;

View File

@ -293,7 +293,9 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm)
} }
bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released); bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released);
bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_EVENT); bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_EVENT);
bf_set(lpfc_eqcq_doorbell_eqid, &doorbell, q->queue_id); bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell,
(q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT));
bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id);
writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr);
/* PCI read to flush PCI pipeline on re-arming for INTx mode */ /* PCI read to flush PCI pipeline on re-arming for INTx mode */
if ((q->phba->intr_type == INTx) && (arm == LPFC_QUEUE_REARM)) if ((q->phba->intr_type == INTx) && (arm == LPFC_QUEUE_REARM))
@ -372,7 +374,9 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm)
bf_set(lpfc_eqcq_doorbell_arm, &doorbell, 1); bf_set(lpfc_eqcq_doorbell_arm, &doorbell, 1);
bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released); bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released);
bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_COMPLETION); bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_COMPLETION);
bf_set(lpfc_eqcq_doorbell_cqid, &doorbell, q->queue_id); bf_set(lpfc_eqcq_doorbell_cqid_hi, &doorbell,
(q->queue_id >> LPFC_CQID_HI_FIELD_SHIFT));
bf_set(lpfc_eqcq_doorbell_cqid_lo, &doorbell, q->queue_id);
writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr);
return released; return released;
} }
@ -5596,6 +5600,8 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
phba->sli4_hba.rpi_ids[i] = base + i; phba->sli4_hba.rpi_ids[i] = base + i;
lpfc_sli4_node_prep(phba);
/* VPIs. */ /* VPIs. */
count = phba->sli4_hba.max_cfg_param.max_vpi; count = phba->sli4_hba.max_cfg_param.max_vpi;
base = phba->sli4_hba.max_cfg_param.vpi_base; base = phba->sli4_hba.max_cfg_param.vpi_base;
@ -7555,6 +7561,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
sgl = (struct sli4_sge *)sglq->sgl; sgl = (struct sli4_sge *)sglq->sgl;
icmd = &piocbq->iocb; 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) { if (icmd->un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) {
numBdes = icmd->un.genreq64.bdl.bdeSize / numBdes = icmd->un.genreq64.bdl.bdeSize /
sizeof(struct ulp_bde64); sizeof(struct ulp_bde64);
@ -7756,6 +7764,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
if (pcmd && (*pcmd == ELS_CMD_FLOGI || if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
*pcmd == ELS_CMD_SCR || *pcmd == ELS_CMD_SCR ||
*pcmd == ELS_CMD_FDISC ||
*pcmd == ELS_CMD_PLOGI)) { *pcmd == ELS_CMD_PLOGI)) {
bf_set(els_req64_sp, &wqe->els_req, 1); bf_set(els_req64_sp, &wqe->els_req, 1);
bf_set(els_req64_sid, &wqe->els_req, bf_set(els_req64_sid, &wqe->els_req,
@ -7982,6 +7991,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
xritag = 0; xritag = 0;
break; break;
case CMD_XMIT_BLS_RSP64_CX: case CMD_XMIT_BLS_RSP64_CX:
ndlp = (struct lpfc_nodelist *)iocbq->context1;
/* As BLS ABTS RSP WQE is very different from other WQEs, /* As BLS ABTS RSP WQE is very different from other WQEs,
* we re-construct this WQE here based on information in * we re-construct this WQE here based on information in
* iocbq from scratch. * iocbq from scratch.
@ -8008,8 +8018,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
} }
bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); 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_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com,
/* 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); 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_qosd, &wqe->xmit_bls_rsp.wqe_com, 1);
bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com, bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com,
LPFC_WQE_LENLOC_NONE); LPFC_WQE_LENLOC_NONE);
@ -8073,8 +8090,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
if (piocb->sli4_xritag == NO_XRI) { if (piocb->sli4_xritag == NO_XRI) {
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN || piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
piocb->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX)
sglq = NULL; sglq = NULL;
else { else {
if (pring->txq_cnt) { if (pring->txq_cnt) {
@ -8384,10 +8400,13 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
{ {
struct lpfc_vport *vport; struct lpfc_vport *vport;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"3115 Node Context not found, driver " "3115 Node Context not found, driver "
"ignoring abts err event\n"); "ignoring abts err event\n");
return;
}
vport = ndlp->vport; vport = ndlp->vport;
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"3116 Port generated FCP XRI ABORT event on " "3116 Port generated FCP XRI ABORT event on "
@ -14042,6 +14061,13 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
{ {
if (cmd_iocbq) if (cmd_iocbq)
lpfc_sli_release_iocbq(phba, cmd_iocbq); lpfc_sli_release_iocbq(phba, cmd_iocbq);
/* Failure means BLS ABORT RSP did not get delivered to remote node*/
if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus)
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3154 BLS ABORT RSP failed, data: x%x/x%x\n",
rsp_iocbq->iocb.ulpStatus,
rsp_iocbq->iocb.un.ulpWord[4]);
} }
/** /**
@ -14748,7 +14774,8 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba)
* provided rpi via a bitmask. * provided rpi via a bitmask.
**/ **/
int int
lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp) lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
void (*cmpl)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *arg)
{ {
LPFC_MBOXQ_t *mboxq; LPFC_MBOXQ_t *mboxq;
struct lpfc_hba *phba = ndlp->phba; struct lpfc_hba *phba = ndlp->phba;
@ -14761,6 +14788,12 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp)
/* Post all rpi memory regions to the port. */ /* Post all rpi memory regions to the port. */
lpfc_resume_rpi(mboxq, ndlp); lpfc_resume_rpi(mboxq, ndlp);
if (cmpl) {
mboxq->mbox_cmpl = cmpl;
mboxq->context1 = arg;
mboxq->context2 = ndlp;
}
mboxq->vport = ndlp->vport;
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, lpfc_printf_log(phba, KERN_ERR, LOG_SLI,

View File

@ -633,7 +633,8 @@ void lpfc_sli4_free_rpi(struct lpfc_hba *, int);
void lpfc_sli4_remove_rpis(struct lpfc_hba *); void lpfc_sli4_remove_rpis(struct lpfc_hba *);
void lpfc_sli4_async_event_proc(struct lpfc_hba *); void lpfc_sli4_async_event_proc(struct lpfc_hba *);
void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *); void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
int lpfc_sli4_resume_rpi(struct lpfc_nodelist *); int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *); void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *);
void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *); void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *);
void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *, void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,