[SCSI] lpfc 8.3.5: fix VPI registration, error clean up and add support for vlink events
This patch includes the following fixes and new features: - Fix mask size for CT field in WQE - Fix VPI base not used when unregistering VPI on port 1. - Fix UNREG_VPI mailbox command to unreg the correct VPI - Fixed Check for aborted els command - Fix error when trying to load driver with wrong firmware on FCoE HBA. - Fix bug with probe_one routines not putting the Scsi_Host back upon error - Add support for Clear Virtual Link Async Events - Add support for unsolicited CT exchange sequence abort - Add 0x0714 OCeXXXXX PCI ID Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
4d9ab994e2
commit
6669f9bb90
11 changed files with 498 additions and 47 deletions
|
@ -144,6 +144,8 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
|
|||
|
||||
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
void lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
|
||||
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
|
||||
void lpfc_fdmi_tmo(unsigned long);
|
||||
|
@ -188,7 +190,7 @@ int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
|
|||
void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
|
||||
void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
|
||||
void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_unreg_vfi(struct lpfcMboxq *, struct lpfc_vport *);
|
||||
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
|
||||
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
|
||||
|
@ -361,6 +363,7 @@ void lpfc_stop_port(struct lpfc_hba *);
|
|||
void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t);
|
||||
int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
|
||||
void lpfc_start_fdiscs(struct lpfc_hba *phba);
|
||||
struct lpfc_vport *lpfc_find_vport_by_vpid(struct lpfc_hba *, uint16_t);
|
||||
|
||||
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
||||
#define HBA_EVENT_RSCN 5
|
||||
|
|
|
@ -87,7 +87,6 @@ void
|
|||
lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
struct lpfc_iocbq *piocbq)
|
||||
{
|
||||
|
||||
struct lpfc_dmabuf *mp = NULL;
|
||||
IOCB_t *icmd = &piocbq->iocb;
|
||||
int i;
|
||||
|
@ -160,6 +159,39 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_ct_abort_unsol_event - Default handle for sli4 unsol abort
|
||||
* @phba: Pointer to HBA context object.
|
||||
* @pring: Pointer to the driver internal I/O ring.
|
||||
* @piocbq: Pointer to the IOCBQ.
|
||||
*
|
||||
* This function serves as the default handler for the sli4 unsolicited
|
||||
* abort event. It shall be invoked when there is no application interface
|
||||
* registered unsolicited abort handler. This handler does nothing but
|
||||
* just simply releases the dma buffer used by the unsol abort event.
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *phba,
|
||||
struct lpfc_sli_ring *pring,
|
||||
struct lpfc_iocbq *piocbq)
|
||||
{
|
||||
IOCB_t *icmd = &piocbq->iocb;
|
||||
struct lpfc_dmabuf *bdeBuf;
|
||||
uint32_t size;
|
||||
|
||||
/* Forward abort event to any process registered to receive ct event */
|
||||
lpfc_bsg_ct_unsol_event(phba, pring, piocbq);
|
||||
|
||||
/* If there is no BDE associated with IOCB, there is nothing to do */
|
||||
if (icmd->ulpBdeCount == 0)
|
||||
return;
|
||||
bdeBuf = piocbq->context2;
|
||||
piocbq->context2 = NULL;
|
||||
size = icmd->un.cont64[0].tus.f.bdeSize;
|
||||
lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
|
||||
lpfc_in_buf_free(phba, bdeBuf);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
|
||||
{
|
||||
|
|
|
@ -2712,12 +2712,16 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
!lpfc_error_lost_link(irsp)) {
|
||||
/* FLOGI retry policy */
|
||||
retry = 1;
|
||||
maxretry = 48;
|
||||
if (cmdiocb->retry >= 32)
|
||||
/* retry forever */
|
||||
maxretry = 0;
|
||||
if (cmdiocb->retry >= 100)
|
||||
delay = 5000;
|
||||
else if (cmdiocb->retry >= 32)
|
||||
delay = 1000;
|
||||
}
|
||||
|
||||
if ((++cmdiocb->retry) >= maxretry) {
|
||||
cmdiocb->retry++;
|
||||
if (maxretry && (cmdiocb->retry >= maxretry)) {
|
||||
phba->fc_stat.elsRetryExceeded++;
|
||||
retry = 0;
|
||||
}
|
||||
|
@ -5671,7 +5675,7 @@ dropit:
|
|||
* NULL - No vport with the matching @vpi found
|
||||
* Otherwise - Address to the vport with the matching @vpi.
|
||||
**/
|
||||
static struct lpfc_vport *
|
||||
struct lpfc_vport *
|
||||
lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
|
||||
{
|
||||
struct lpfc_vport *vport;
|
||||
|
|
|
@ -4474,7 +4474,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba)
|
|||
return;
|
||||
}
|
||||
|
||||
lpfc_unreg_vfi(mbox, phba->pport->vfi);
|
||||
lpfc_unreg_vfi(mbox, phba->pport);
|
||||
mbox->vport = phba->pport;
|
||||
mbox->mbox_cmpl = lpfc_unregister_vfi_cmpl;
|
||||
|
||||
|
|
|
@ -1183,6 +1183,7 @@ typedef struct {
|
|||
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
|
||||
#define PCI_VENDOR_ID_SERVERENGINE 0x19a2
|
||||
#define PCI_DEVICE_ID_TIGERSHARK 0x0704
|
||||
#define PCI_DEVICE_ID_TS_BE3 0x0714
|
||||
|
||||
#define JEDEC_ID_ADDRESS 0x0080001c
|
||||
#define FIREFLY_JEDEC_ID 0x1ACC
|
||||
|
@ -1444,6 +1445,7 @@ typedef struct { /* FireFly BIU registers */
|
|||
#define CMD_ABORT_MXRI64_CN 0x8C
|
||||
#define CMD_RCV_ELS_REQ64_CX 0x8D
|
||||
#define CMD_XMIT_ELS_RSP64_CX 0x95
|
||||
#define CMD_XMIT_BLS_RSP64_CX 0x97
|
||||
#define CMD_FCP_IWRITE64_CR 0x98
|
||||
#define CMD_FCP_IWRITE64_CX 0x99
|
||||
#define CMD_FCP_IREAD64_CR 0x9A
|
||||
|
@ -2326,7 +2328,13 @@ typedef struct {
|
|||
/* Structure for MB Command UNREG_VPI (0x97) */
|
||||
typedef struct {
|
||||
uint32_t rsvd1;
|
||||
uint32_t rsvd2;
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint16_t rsvd2;
|
||||
uint16_t sli4_vpi;
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
uint16_t sli4_vpi;
|
||||
uint16_t rsvd2;
|
||||
#endif
|
||||
uint32_t rsvd3;
|
||||
uint32_t rsvd4;
|
||||
uint32_t rsvd5;
|
||||
|
|
|
@ -425,7 +425,7 @@ struct lpfc_wqe_generic{
|
|||
#define lpfc_wqe_gen_status_MASK 0x0000000F
|
||||
#define lpfc_wqe_gen_status_WORD word7
|
||||
#define lpfc_wqe_gen_ct_SHIFT 2
|
||||
#define lpfc_wqe_gen_ct_MASK 0x00000007
|
||||
#define lpfc_wqe_gen_ct_MASK 0x00000003
|
||||
#define lpfc_wqe_gen_ct_WORD word7
|
||||
uint32_t abort_tag;
|
||||
uint32_t word9;
|
||||
|
@ -760,6 +760,7 @@ struct mbox_header {
|
|||
#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
|
||||
#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
|
||||
#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
|
||||
#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
|
||||
#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
|
||||
|
||||
/* FCoE Opcodes */
|
||||
|
@ -1273,6 +1274,51 @@ struct lpfc_mbx_del_fcf_tbl_entry {
|
|||
#define lpfc_mbx_del_fcf_tbl_index_WORD word10
|
||||
};
|
||||
|
||||
struct lpfc_mbx_query_fw_cfg {
|
||||
struct mbox_header header;
|
||||
uint32_t config_number;
|
||||
uint32_t asic_rev;
|
||||
uint32_t phys_port;
|
||||
uint32_t function_mode;
|
||||
/* firmware Function Mode */
|
||||
#define lpfc_function_mode_toe_SHIFT 0
|
||||
#define lpfc_function_mode_toe_MASK 0x00000001
|
||||
#define lpfc_function_mode_toe_WORD function_mode
|
||||
#define lpfc_function_mode_nic_SHIFT 1
|
||||
#define lpfc_function_mode_nic_MASK 0x00000001
|
||||
#define lpfc_function_mode_nic_WORD function_mode
|
||||
#define lpfc_function_mode_rdma_SHIFT 2
|
||||
#define lpfc_function_mode_rdma_MASK 0x00000001
|
||||
#define lpfc_function_mode_rdma_WORD function_mode
|
||||
#define lpfc_function_mode_vm_SHIFT 3
|
||||
#define lpfc_function_mode_vm_MASK 0x00000001
|
||||
#define lpfc_function_mode_vm_WORD function_mode
|
||||
#define lpfc_function_mode_iscsi_i_SHIFT 4
|
||||
#define lpfc_function_mode_iscsi_i_MASK 0x00000001
|
||||
#define lpfc_function_mode_iscsi_i_WORD function_mode
|
||||
#define lpfc_function_mode_iscsi_t_SHIFT 5
|
||||
#define lpfc_function_mode_iscsi_t_MASK 0x00000001
|
||||
#define lpfc_function_mode_iscsi_t_WORD function_mode
|
||||
#define lpfc_function_mode_fcoe_i_SHIFT 6
|
||||
#define lpfc_function_mode_fcoe_i_MASK 0x00000001
|
||||
#define lpfc_function_mode_fcoe_i_WORD function_mode
|
||||
#define lpfc_function_mode_fcoe_t_SHIFT 7
|
||||
#define lpfc_function_mode_fcoe_t_MASK 0x00000001
|
||||
#define lpfc_function_mode_fcoe_t_WORD function_mode
|
||||
#define lpfc_function_mode_dal_SHIFT 8
|
||||
#define lpfc_function_mode_dal_MASK 0x00000001
|
||||
#define lpfc_function_mode_dal_WORD function_mode
|
||||
#define lpfc_function_mode_lro_SHIFT 9
|
||||
#define lpfc_function_mode_lro_MASK 0x00000001
|
||||
#define lpfc_function_mode_lro_WORD function_mode9
|
||||
#define lpfc_function_mode_flex10_SHIFT 10
|
||||
#define lpfc_function_mode_flex10_MASK 0x00000001
|
||||
#define lpfc_function_mode_flex10_WORD function_mode
|
||||
#define lpfc_function_mode_ncsi_SHIFT 11
|
||||
#define lpfc_function_mode_ncsi_MASK 0x00000001
|
||||
#define lpfc_function_mode_ncsi_WORD function_mode
|
||||
};
|
||||
|
||||
/* Status field for embedded SLI_CONFIG mailbox command */
|
||||
#define STATUS_SUCCESS 0x0
|
||||
#define STATUS_FAILED 0x1
|
||||
|
@ -1804,6 +1850,7 @@ struct lpfc_mqe {
|
|||
struct lpfc_mbx_read_config rd_config;
|
||||
struct lpfc_mbx_request_features req_ftrs;
|
||||
struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
|
||||
struct lpfc_mbx_query_fw_cfg query_fw_cfg;
|
||||
struct lpfc_mbx_nop nop;
|
||||
} un;
|
||||
};
|
||||
|
@ -1885,7 +1932,7 @@ struct lpfc_acqe_link {
|
|||
};
|
||||
|
||||
struct lpfc_acqe_fcoe {
|
||||
uint32_t fcf_index;
|
||||
uint32_t index;
|
||||
uint32_t word1;
|
||||
#define lpfc_acqe_fcoe_fcf_count_SHIFT 0
|
||||
#define lpfc_acqe_fcoe_fcf_count_MASK 0x0000FFFF
|
||||
|
@ -1896,6 +1943,7 @@ struct lpfc_acqe_fcoe {
|
|||
#define LPFC_FCOE_EVENT_TYPE_NEW_FCF 0x1
|
||||
#define LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL 0x2
|
||||
#define LPFC_FCOE_EVENT_TYPE_FCF_DEAD 0x3
|
||||
#define LPFC_FCOE_EVENT_TYPE_CVL 0x4
|
||||
uint32_t event_tag;
|
||||
uint32_t trailer;
|
||||
};
|
||||
|
@ -1924,9 +1972,9 @@ struct lpfc_bmbx_create {
|
|||
#define NO_XRI ((uint16_t)-1)
|
||||
struct wqe_common {
|
||||
uint32_t word6;
|
||||
#define wqe_xri_SHIFT 0
|
||||
#define wqe_xri_MASK 0x0000FFFF
|
||||
#define wqe_xri_WORD word6
|
||||
#define wqe_xri_tag_SHIFT 0
|
||||
#define wqe_xri_tag_MASK 0x0000FFFF
|
||||
#define wqe_xri_tag_WORD word6
|
||||
#define wqe_ctxt_tag_SHIFT 16
|
||||
#define wqe_ctxt_tag_MASK 0x0000FFFF
|
||||
#define wqe_ctxt_tag_WORD word6
|
||||
|
@ -1987,7 +2035,7 @@ struct wqe_common {
|
|||
#define wqe_wqec_MASK 0x00000001
|
||||
#define wqe_wqec_WORD word11
|
||||
#define wqe_cqid_SHIFT 16
|
||||
#define wqe_cqid_MASK 0x000003ff
|
||||
#define wqe_cqid_MASK 0x0000ffff
|
||||
#define wqe_cqid_WORD word11
|
||||
};
|
||||
|
||||
|
@ -1996,6 +2044,9 @@ struct wqe_did {
|
|||
#define wqe_els_did_SHIFT 0
|
||||
#define wqe_els_did_MASK 0x00FFFFFF
|
||||
#define wqe_els_did_WORD word5
|
||||
#define wqe_xmit_bls_pt_SHIFT 28
|
||||
#define wqe_xmit_bls_pt_MASK 0x00000003
|
||||
#define wqe_xmit_bls_pt_WORD word5
|
||||
#define wqe_xmit_bls_ar_SHIFT 30
|
||||
#define wqe_xmit_bls_ar_MASK 0x00000001
|
||||
#define wqe_xmit_bls_ar_WORD word5
|
||||
|
@ -2044,6 +2095,23 @@ struct xmit_els_rsp64_wqe {
|
|||
|
||||
struct xmit_bls_rsp64_wqe {
|
||||
uint32_t payload0;
|
||||
/* Payload0 for BA_ACC */
|
||||
#define xmit_bls_rsp64_acc_seq_id_SHIFT 16
|
||||
#define xmit_bls_rsp64_acc_seq_id_MASK 0x000000ff
|
||||
#define xmit_bls_rsp64_acc_seq_id_WORD payload0
|
||||
#define xmit_bls_rsp64_acc_seq_id_vald_SHIFT 24
|
||||
#define xmit_bls_rsp64_acc_seq_id_vald_MASK 0x000000ff
|
||||
#define xmit_bls_rsp64_acc_seq_id_vald_WORD payload0
|
||||
/* Payload0 for BA_RJT */
|
||||
#define xmit_bls_rsp64_rjt_vspec_SHIFT 0
|
||||
#define xmit_bls_rsp64_rjt_vspec_MASK 0x000000ff
|
||||
#define xmit_bls_rsp64_rjt_vspec_WORD payload0
|
||||
#define xmit_bls_rsp64_rjt_expc_SHIFT 8
|
||||
#define xmit_bls_rsp64_rjt_expc_MASK 0x000000ff
|
||||
#define xmit_bls_rsp64_rjt_expc_WORD payload0
|
||||
#define xmit_bls_rsp64_rjt_rsnc_SHIFT 16
|
||||
#define xmit_bls_rsp64_rjt_rsnc_MASK 0x000000ff
|
||||
#define xmit_bls_rsp64_rjt_rsnc_WORD payload0
|
||||
uint32_t word1;
|
||||
#define xmit_bls_rsp64_rxid_SHIFT 0
|
||||
#define xmit_bls_rsp64_rxid_MASK 0x0000ffff
|
||||
|
@ -2052,18 +2120,19 @@ struct xmit_bls_rsp64_wqe {
|
|||
#define xmit_bls_rsp64_oxid_MASK 0x0000ffff
|
||||
#define xmit_bls_rsp64_oxid_WORD word1
|
||||
uint32_t word2;
|
||||
#define xmit_bls_rsp64_seqcntlo_SHIFT 0
|
||||
#define xmit_bls_rsp64_seqcntlo_MASK 0x0000ffff
|
||||
#define xmit_bls_rsp64_seqcntlo_WORD word2
|
||||
#define xmit_bls_rsp64_seqcnthi_SHIFT 16
|
||||
#define xmit_bls_rsp64_seqcnthi_SHIFT 0
|
||||
#define xmit_bls_rsp64_seqcnthi_MASK 0x0000ffff
|
||||
#define xmit_bls_rsp64_seqcnthi_WORD word2
|
||||
#define xmit_bls_rsp64_seqcntlo_SHIFT 16
|
||||
#define xmit_bls_rsp64_seqcntlo_MASK 0x0000ffff
|
||||
#define xmit_bls_rsp64_seqcntlo_WORD word2
|
||||
uint32_t rsrvd3;
|
||||
uint32_t rsrvd4;
|
||||
struct wqe_did wqe_dest;
|
||||
struct wqe_common wqe_com; /* words 6-11 */
|
||||
uint32_t rsvd_12_15[4];
|
||||
};
|
||||
|
||||
struct wqe_rctl_dfctl {
|
||||
uint32_t word5;
|
||||
#define wqe_si_SHIFT 2
|
||||
|
|
|
@ -1669,6 +1669,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
|||
oneConnect = 1;
|
||||
m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_TS_BE3:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)) {"OCeXXXXX-F", max_speed, "PCIe"};
|
||||
break;
|
||||
default:
|
||||
m = (typeof(m)){ NULL };
|
||||
break;
|
||||
|
@ -2698,6 +2702,63 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
|
|||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
*
|
||||
* This function uses the QUERY_FW_CFG mailbox command to determine if the
|
||||
* firmware loaded supports FCoE. A return of zero indicates that the mailbox
|
||||
* was successful and the firmware supports FCoE. Any other return indicates
|
||||
* a error. It is assumed that this function will be called before interrupts
|
||||
* are enabled.
|
||||
**/
|
||||
static int
|
||||
lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba)
|
||||
{
|
||||
int rc = 0;
|
||||
LPFC_MBOXQ_t *mboxq;
|
||||
struct lpfc_mbx_query_fw_cfg *query_fw_cfg;
|
||||
uint32_t length;
|
||||
uint32_t shdr_status, shdr_add_status;
|
||||
|
||||
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!mboxq) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2621 Failed to allocate mbox for "
|
||||
"query firmware config cmd\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg;
|
||||
length = (sizeof(struct lpfc_mbx_query_fw_cfg) -
|
||||
sizeof(struct lpfc_sli4_cfg_mhdr));
|
||||
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
|
||||
LPFC_MBOX_OPCODE_QUERY_FW_CFG,
|
||||
length, LPFC_SLI4_MBX_EMBED);
|
||||
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
|
||||
/* The IOCTL status is embedded in the mailbox subheader. */
|
||||
shdr_status = bf_get(lpfc_mbox_hdr_status,
|
||||
&query_fw_cfg->header.cfg_shdr.response);
|
||||
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
|
||||
&query_fw_cfg->header.cfg_shdr.response);
|
||||
if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"2622 Query Firmware Config failed "
|
||||
"mbx status x%x, status x%x add_status x%x\n",
|
||||
rc, shdr_status, shdr_add_status);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"2623 FCoE Function not supported by firmware. "
|
||||
"Function mode = %08x\n",
|
||||
query_fw_cfg->function_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rc != MBX_TIMEOUT)
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
|
@ -2918,6 +2979,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
|||
{
|
||||
uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
|
||||
int rc;
|
||||
struct lpfc_vport *vport;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
phba->fc_eventTag = acqe_fcoe->event_tag;
|
||||
phba->fcoe_eventtag = acqe_fcoe->event_tag;
|
||||
|
@ -2925,7 +2989,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
|||
case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||
"2546 New FCF found index 0x%x tag 0x%x\n",
|
||||
acqe_fcoe->fcf_index,
|
||||
acqe_fcoe->index,
|
||||
acqe_fcoe->event_tag);
|
||||
/*
|
||||
* If the current FCF is in discovered state, or
|
||||
|
@ -2958,10 +3022,10 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
|||
case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||
"2549 FCF disconnected fron network index 0x%x"
|
||||
" tag 0x%x\n", acqe_fcoe->fcf_index,
|
||||
" tag 0x%x\n", acqe_fcoe->index,
|
||||
acqe_fcoe->event_tag);
|
||||
/* If the event is not for currently used fcf do nothing */
|
||||
if (phba->fcf.fcf_indx != acqe_fcoe->fcf_index)
|
||||
if (phba->fcf.fcf_indx != acqe_fcoe->index)
|
||||
break;
|
||||
/*
|
||||
* Currently, driver support only one FCF - so treat this as
|
||||
|
@ -2971,7 +3035,28 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
|||
/* Unregister FCF if no devices connected to it */
|
||||
lpfc_unregister_unused_fcf(phba);
|
||||
break;
|
||||
|
||||
case LPFC_FCOE_EVENT_TYPE_CVL:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||
"2718 Clear Virtual Link Received for VPI 0x%x"
|
||||
" tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
|
||||
vport = lpfc_find_vport_by_vpid(phba,
|
||||
acqe_fcoe->index /*- phba->vpi_base*/);
|
||||
if (!vport)
|
||||
break;
|
||||
ndlp = lpfc_findnode_did(vport, Fabric_DID);
|
||||
if (!ndlp)
|
||||
break;
|
||||
shost = lpfc_shost_from_vport(vport);
|
||||
lpfc_linkdown_port(vport);
|
||||
if (vport->port_type != LPFC_NPIV_PORT) {
|
||||
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
ndlp->nlp_flag |= NLP_DELAY_TMO;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
ndlp->nlp_last_elscmd = ELS_CMD_FLOGI;
|
||||
vport->port_state = LPFC_FLOGI;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"0288 Unknown FCoE event type 0x%x event tag "
|
||||
|
@ -3463,6 +3548,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
|||
if (unlikely(rc))
|
||||
goto out_free_bsmbx;
|
||||
|
||||
rc = lpfc_sli4_fw_cfg_check(phba);
|
||||
if (unlikely(rc))
|
||||
goto out_free_bsmbx;
|
||||
|
||||
/* Set up the hba's configuration parameters. */
|
||||
rc = lpfc_sli4_read_config(phba);
|
||||
if (unlikely(rc))
|
||||
|
@ -6687,6 +6776,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
{
|
||||
struct lpfc_hba *phba;
|
||||
struct lpfc_vport *vport = NULL;
|
||||
struct Scsi_Host *shost = NULL;
|
||||
int error;
|
||||
uint32_t cfg_mode, intr_mode;
|
||||
|
||||
|
@ -6765,6 +6855,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
goto out_destroy_shost;
|
||||
}
|
||||
|
||||
shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
|
||||
/* Now, trying to enable interrupt and bring up the device */
|
||||
cfg_mode = phba->cfg_use_msi;
|
||||
while (true) {
|
||||
|
@ -6831,6 +6922,8 @@ out_unset_pci_mem_s3:
|
|||
lpfc_sli_pci_mem_unset(phba);
|
||||
out_disable_pci_dev:
|
||||
lpfc_disable_pci_dev(phba);
|
||||
if (shost)
|
||||
scsi_host_put(shost);
|
||||
out_free_phba:
|
||||
lpfc_hba_free(phba);
|
||||
return error;
|
||||
|
@ -7214,6 +7307,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
{
|
||||
struct lpfc_hba *phba;
|
||||
struct lpfc_vport *vport = NULL;
|
||||
struct Scsi_Host *shost = NULL;
|
||||
int error;
|
||||
uint32_t cfg_mode, intr_mode;
|
||||
int mcnt;
|
||||
|
@ -7294,6 +7388,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
goto out_destroy_shost;
|
||||
}
|
||||
|
||||
shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
|
||||
/* Now, trying to enable interrupt and bring up the device */
|
||||
cfg_mode = phba->cfg_use_msi;
|
||||
while (true) {
|
||||
|
@ -7362,6 +7457,8 @@ out_unset_pci_mem_s4:
|
|||
lpfc_sli4_pci_mem_unset(phba);
|
||||
out_disable_pci_dev:
|
||||
lpfc_disable_pci_dev(phba);
|
||||
if (shost)
|
||||
scsi_host_put(shost);
|
||||
out_free_phba:
|
||||
lpfc_hba_free(phba);
|
||||
return error;
|
||||
|
@ -7936,6 +8033,8 @@ static struct pci_device_id lpfc_id_table[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TS_BE3,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -849,7 +849,10 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
|
|||
MAILBOX_t *mb = &pmb->u.mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varUnregVpi.vpi = vpi + phba->vpi_base;
|
||||
if (phba->sli_rev < LPFC_SLI_REV4)
|
||||
mb->un.varUnregVpi.vpi = vpi + phba->vpi_base;
|
||||
else
|
||||
mb->un.varUnregVpi.sli4_vpi = vpi + phba->vpi_base;
|
||||
|
||||
mb->mbxCommand = MBX_UNREG_VPI;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
|
@ -1850,7 +1853,7 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
|
|||
/**
|
||||
* lpfc_unreg_vfi - Initialize the UNREG_VFI mailbox command
|
||||
* @mbox: pointer to lpfc mbox command to initialize.
|
||||
* @vfi: VFI to be unregistered.
|
||||
* @vport: vport associated with the VF.
|
||||
*
|
||||
* The UNREG_VFI mailbox command causes the SLI Host to put a virtual fabric
|
||||
* (logical NPort) into the inactive state. The SLI Host must have logged out
|
||||
|
@ -1859,11 +1862,12 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
|
|||
* fabric inactive.
|
||||
**/
|
||||
void
|
||||
lpfc_unreg_vfi(struct lpfcMboxq *mbox, uint16_t vfi)
|
||||
lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
|
||||
{
|
||||
memset(mbox, 0, sizeof(*mbox));
|
||||
bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI);
|
||||
bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, vfi);
|
||||
bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi,
|
||||
vport->vfi + vport->phba->vfi_base);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,8 @@ 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 void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
|
||||
struct hbq_dmabuf *);
|
||||
static IOCB_t *
|
||||
lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
|
||||
{
|
||||
|
@ -572,9 +573,9 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
|
|||
sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag);
|
||||
if (sglq) {
|
||||
if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED
|
||||
|| ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
|
||||
&& ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
|
||||
&& (iocbq->iocb.un.ulpWord[4]
|
||||
== IOERR_SLI_ABORTED))) {
|
||||
== IOERR_ABORT_REQUESTED))) {
|
||||
spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock,
|
||||
iflag);
|
||||
list_add(&sglq->list,
|
||||
|
@ -767,6 +768,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
|
|||
case CMD_CLOSE_XRI_CX:
|
||||
case CMD_XRI_ABORTED_CX:
|
||||
case CMD_ABORT_MXRI64_CN:
|
||||
case CMD_XMIT_BLS_RSP64_CX:
|
||||
type = LPFC_ABORT_IOCB;
|
||||
break;
|
||||
case CMD_RCV_SEQUENCE_CX:
|
||||
|
@ -6081,6 +6083,23 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||
command_type = OTHER_COMMAND;
|
||||
xritag = 0;
|
||||
break;
|
||||
case CMD_XMIT_BLS_RSP64_CX:
|
||||
/* As BLS ABTS-ACC WQE is very different from other WQEs,
|
||||
* we re-construct this WQE here based on information in
|
||||
* iocbq from scratch.
|
||||
*/
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe));
|
||||
bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
|
||||
iocbq->iocb.un.ulpWord[3]);
|
||||
bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
|
||||
iocbq->sli4_xritag);
|
||||
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_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com,
|
||||
iocbq->iocb.ulpContext);
|
||||
/* Overwrite the pre-set comnd type with OTHER_COMMAND */
|
||||
command_type = OTHER_COMMAND;
|
||||
break;
|
||||
case CMD_XRI_ABORTED_CX:
|
||||
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
|
||||
/* words0-2 are all 0's no bde */
|
||||
|
@ -6139,7 +6158,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|||
|
||||
if (piocb->sli4_xritag == NO_XRI) {
|
||||
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
|
||||
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
|
||||
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
|
||||
sglq = NULL;
|
||||
else {
|
||||
sglq = __lpfc_sli_get_sglq(phba);
|
||||
|
@ -6464,7 +6483,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
|
|||
pring->iotag_max = 4096;
|
||||
pring->lpfc_sli_rcv_async_status =
|
||||
lpfc_sli_async_event_handler;
|
||||
pring->num_mask = 4;
|
||||
pring->num_mask = LPFC_MAX_RING_MASK;
|
||||
pring->prt[0].profile = 0; /* Mask 0 */
|
||||
pring->prt[0].rctl = FC_ELS_REQ;
|
||||
pring->prt[0].type = FC_ELS_DATA;
|
||||
|
@ -6489,6 +6508,12 @@ lpfc_sli_setup(struct lpfc_hba *phba)
|
|||
pring->prt[3].type = FC_COMMON_TRANSPORT_ULP;
|
||||
pring->prt[3].lpfc_sli_rcv_unsol_event =
|
||||
lpfc_ct_unsol_event;
|
||||
/* abort unsolicited sequence */
|
||||
pring->prt[4].profile = 0; /* Mask 4 */
|
||||
pring->prt[4].rctl = FC_RCTL_BA_ABTS;
|
||||
pring->prt[4].type = FC_TYPE_BLS;
|
||||
pring->prt[4].lpfc_sli_rcv_unsol_event =
|
||||
lpfc_sli4_ct_abort_unsol_event;
|
||||
break;
|
||||
}
|
||||
totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
|
||||
|
@ -10869,6 +10894,177 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_abort_partial_seq - Abort partially assembled unsol sequence
|
||||
* @vport: pointer to a vitural port
|
||||
* @dmabuf: pointer to a dmabuf that describes the FC sequence
|
||||
*
|
||||
* This function tries to abort from the partially assembed sequence, described
|
||||
* by the information from basic abbort @dmabuf. It checks to see whether such
|
||||
* partially assembled sequence held by the driver. If so, it shall free up all
|
||||
* the frames from the partially assembled sequence.
|
||||
*
|
||||
* Return
|
||||
* true -- if there is matching partially assembled sequence present and all
|
||||
* the frames freed with the sequence;
|
||||
* false -- if there is no matching partially assembled sequence present so
|
||||
* nothing got aborted in the lower layer driver
|
||||
**/
|
||||
static bool
|
||||
lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
|
||||
struct hbq_dmabuf *dmabuf)
|
||||
{
|
||||
struct fc_frame_header *new_hdr;
|
||||
struct fc_frame_header *temp_hdr;
|
||||
struct lpfc_dmabuf *d_buf, *n_buf, *h_buf;
|
||||
struct hbq_dmabuf *seq_dmabuf = NULL;
|
||||
|
||||
/* Use the hdr_buf to find the sequence that matches this frame */
|
||||
INIT_LIST_HEAD(&dmabuf->dbuf.list);
|
||||
INIT_LIST_HEAD(&dmabuf->hbuf.list);
|
||||
new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
|
||||
list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) {
|
||||
temp_hdr = (struct fc_frame_header *)h_buf->virt;
|
||||
if ((temp_hdr->fh_seq_id != new_hdr->fh_seq_id) ||
|
||||
(temp_hdr->fh_ox_id != new_hdr->fh_ox_id) ||
|
||||
(memcmp(&temp_hdr->fh_s_id, &new_hdr->fh_s_id, 3)))
|
||||
continue;
|
||||
/* found a pending sequence that matches this frame */
|
||||
seq_dmabuf = container_of(h_buf, struct hbq_dmabuf, hbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free up all the frames from the partially assembled sequence */
|
||||
if (seq_dmabuf) {
|
||||
list_for_each_entry_safe(d_buf, n_buf,
|
||||
&seq_dmabuf->dbuf.list, list) {
|
||||
list_del_init(&d_buf->list);
|
||||
lpfc_in_buf_free(vport->phba, d_buf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler
|
||||
* @phba: Pointer to HBA context object.
|
||||
* @cmd_iocbq: pointer to the command iocbq structure.
|
||||
* @rsp_iocbq: pointer to the response iocbq structure.
|
||||
*
|
||||
* This function handles the sequence abort accept iocb command complete
|
||||
* event. It properly releases the memory allocated to the sequence abort
|
||||
* accept iocb.
|
||||
**/
|
||||
static void
|
||||
lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *cmd_iocbq,
|
||||
struct lpfc_iocbq *rsp_iocbq)
|
||||
{
|
||||
if (cmd_iocbq)
|
||||
lpfc_sli_release_iocbq(phba, cmd_iocbq);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_seq_abort_acc - Accept sequence abort
|
||||
* @phba: Pointer to HBA context object.
|
||||
* @fc_hdr: pointer to a FC frame header.
|
||||
*
|
||||
* This function sends a basic accept to a previous unsol sequence abort
|
||||
* event after aborting the sequence handling.
|
||||
**/
|
||||
static void
|
||||
lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
|
||||
struct fc_frame_header *fc_hdr)
|
||||
{
|
||||
struct lpfc_iocbq *ctiocb = NULL;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
uint16_t oxid;
|
||||
uint32_t sid;
|
||||
IOCB_t *icmd;
|
||||
|
||||
if (!lpfc_is_link_up(phba))
|
||||
return;
|
||||
|
||||
sid = sli4_sid_from_fc_hdr(fc_hdr);
|
||||
oxid = be16_to_cpu(fc_hdr->fh_ox_id);
|
||||
|
||||
ndlp = lpfc_findnode_did(phba->pport, sid);
|
||||
if (!ndlp) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
|
||||
"1268 Find ndlp returned NULL for oxid:x%x "
|
||||
"SID:x%x\n", oxid, sid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate buffer for acc iocb */
|
||||
ctiocb = lpfc_sli_get_iocbq(phba);
|
||||
if (!ctiocb)
|
||||
return;
|
||||
|
||||
icmd = &ctiocb->iocb;
|
||||
icmd->un.xseq64.bdl.ulpIoTag32 = 0;
|
||||
icmd->un.xseq64.bdl.bdeSize = 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 = ndlp->nlp_rpi;
|
||||
icmd->un.ulpWord[3] = oxid;
|
||||
|
||||
ctiocb->sli4_xritag = NO_XRI;
|
||||
ctiocb->iocb_cmpl = NULL;
|
||||
ctiocb->vport = phba->pport;
|
||||
ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl;
|
||||
|
||||
/* Xmit CT abts accept on exchange <xid> */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||
"1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n",
|
||||
CMD_XMIT_BLS_RSP64_CX, phba->link_state);
|
||||
lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_handle_unsol_abort - Handle sli-4 unsolicited abort event
|
||||
* @vport: Pointer to the vport on which this sequence was received
|
||||
* @dmabuf: pointer to a dmabuf that describes the FC sequence
|
||||
*
|
||||
* This function handles an SLI-4 unsolicited abort event. If the unsolicited
|
||||
* receive sequence is only partially assembed by the driver, it shall abort
|
||||
* the partially assembled frames for the sequence. Otherwise, if the
|
||||
* unsolicited receive sequence has been completely assembled and passed to
|
||||
* the Upper Layer Protocol (UPL), it then mark the per oxid status for the
|
||||
* unsolicited sequence has been aborted. After that, it will issue a basic
|
||||
* accept to accept the abort.
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
|
||||
struct hbq_dmabuf *dmabuf)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct fc_frame_header fc_hdr;
|
||||
bool abts_par;
|
||||
|
||||
/* Try to abort partially assembled seq */
|
||||
abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf);
|
||||
|
||||
/* Make a copy of fc_hdr before the dmabuf being released */
|
||||
memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
|
||||
|
||||
/* Send abort to ULP if partially seq abort failed */
|
||||
if (abts_par == false)
|
||||
lpfc_sli4_send_seq_to_ulp(vport, dmabuf);
|
||||
else
|
||||
lpfc_in_buf_free(phba, &dmabuf->dbuf);
|
||||
/* Send basic accept (BA_ACC) to the abort requester */
|
||||
lpfc_sli4_seq_abort_acc(phba, &fc_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_seq_complete - Indicates if a sequence is complete
|
||||
* @dmabuf: pointer to a dmabuf that describes the FC sequence
|
||||
|
@ -10941,9 +11137,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
|
|||
/* remove from receive buffer list */
|
||||
list_del_init(&seq_dmabuf->hbuf.list);
|
||||
/* get the Remote Port's SID */
|
||||
sid = (fc_hdr->fh_s_id[0] << 16 |
|
||||
fc_hdr->fh_s_id[1] << 8 |
|
||||
fc_hdr->fh_s_id[2]);
|
||||
sid = sli4_sid_from_fc_hdr(fc_hdr);
|
||||
/* Get an iocbq struct to fill in. */
|
||||
first_iocbq = lpfc_sli_get_iocbq(vport->phba);
|
||||
if (first_iocbq) {
|
||||
|
@ -11010,6 +11204,43 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
|
|||
return first_iocbq;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport,
|
||||
struct hbq_dmabuf *seq_dmabuf)
|
||||
{
|
||||
struct fc_frame_header *fc_hdr;
|
||||
struct lpfc_iocbq *iocbq, *curr_iocb, *next_iocb;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
||||
iocbq = lpfc_prep_seq(vport, seq_dmabuf);
|
||||
if (!iocbq) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"2707 Ring %d handler: Failed to allocate "
|
||||
"iocb Rctl x%x Type x%x received\n",
|
||||
LPFC_ELS_RING,
|
||||
fc_hdr->fh_r_ctl, fc_hdr->fh_type);
|
||||
return;
|
||||
}
|
||||
if (!lpfc_complete_unsol_iocb(phba,
|
||||
&phba->sli.ring[LPFC_ELS_RING],
|
||||
iocbq, fc_hdr->fh_r_ctl,
|
||||
fc_hdr->fh_type))
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
||||
"2540 Ring %d handler: unexpected Rctl "
|
||||
"x%x Type x%x received\n",
|
||||
LPFC_ELS_RING,
|
||||
fc_hdr->fh_r_ctl, fc_hdr->fh_type);
|
||||
|
||||
/* Free iocb created in lpfc_prep_seq */
|
||||
list_for_each_entry_safe(curr_iocb, next_iocb,
|
||||
&iocbq->list, list) {
|
||||
list_del_init(&curr_iocb->list);
|
||||
lpfc_sli_release_iocbq(phba, curr_iocb);
|
||||
}
|
||||
lpfc_sli_release_iocbq(phba, iocbq);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
|
||||
* @phba: Pointer to HBA context object.
|
||||
|
@ -11030,7 +11261,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
|
|||
struct fc_frame_header *fc_hdr;
|
||||
struct lpfc_vport *vport;
|
||||
uint32_t fcfi;
|
||||
struct lpfc_iocbq *iocbq;
|
||||
|
||||
/* Clear hba flag and get all received buffers into the cmplq */
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
|
@ -11051,6 +11281,12 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
|
|||
lpfc_in_buf_free(phba, &dmabuf->dbuf);
|
||||
return;
|
||||
}
|
||||
/* Handle the basic abort sequence (BA_ABTS) event */
|
||||
if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) {
|
||||
lpfc_sli4_handle_unsol_abort(vport, dmabuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Link this frame */
|
||||
seq_dmabuf = lpfc_fc_frame_add(vport, dmabuf);
|
||||
if (!seq_dmabuf) {
|
||||
|
@ -11068,17 +11304,8 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
|
|||
dmabuf->tag = -1;
|
||||
return;
|
||||
}
|
||||
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
||||
iocbq = lpfc_prep_seq(vport, seq_dmabuf);
|
||||
if (!lpfc_complete_unsol_iocb(phba,
|
||||
&phba->sli.ring[LPFC_ELS_RING],
|
||||
iocbq, fc_hdr->fh_r_ctl,
|
||||
fc_hdr->fh_type))
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
||||
"2540 Ring %d handler: unexpected Rctl "
|
||||
"x%x Type x%x received\n",
|
||||
LPFC_ELS_RING,
|
||||
fc_hdr->fh_r_ctl, fc_hdr->fh_type);
|
||||
/* Send the complete sequence to the upper layer protocol */
|
||||
lpfc_sli4_send_seq_to_ulp(vport, seq_dmabuf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -113,7 +113,7 @@ typedef struct lpfcMboxq {
|
|||
return */
|
||||
#define MBX_NOWAIT 2 /* issue command then return immediately */
|
||||
|
||||
#define LPFC_MAX_RING_MASK 4 /* max num of rctl/type masks allowed per
|
||||
#define LPFC_MAX_RING_MASK 5 /* max num of rctl/type masks allowed per
|
||||
ring */
|
||||
#define LPFC_MAX_RING 4 /* max num of SLI rings used by driver */
|
||||
|
||||
|
|
|
@ -58,6 +58,11 @@
|
|||
#define LPFC_FCOE_FKA_ADV_PER 0
|
||||
#define LPFC_FCOE_FIP_PRIORITY 0x80
|
||||
|
||||
#define sli4_sid_from_fc_hdr(fc_hdr) \
|
||||
((fc_hdr)->fh_s_id[0] << 16 | \
|
||||
(fc_hdr)->fh_s_id[1] << 8 | \
|
||||
(fc_hdr)->fh_s_id[2])
|
||||
|
||||
enum lpfc_sli4_queue_type {
|
||||
LPFC_EQ,
|
||||
LPFC_GCQ,
|
||||
|
|
Reference in a new issue