mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	[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, | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 James Smart
						James Smart