diff options
| -rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 9 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 176 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 72 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 188 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 8 | 
5 files changed, 369 insertions, 84 deletions
| diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 9b7fbaf07a55..7706c99ec8bb 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -752,6 +752,15 @@ struct lpfc_hba {  	void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for  					    PCI BAR2 */ +	void __iomem *pci_bar0_memmap_p; /* Kernel memory mapped address for +					    PCI BAR0 with dual-ULP support */ +	void __iomem *pci_bar2_memmap_p; /* Kernel memory mapped address for +					    PCI BAR2 with dual-ULP support */ +	void __iomem *pci_bar4_memmap_p; /* Kernel memory mapped address for +					    PCI BAR4 with dual-ULP support */ +#define PCI_64BIT_BAR0	0 +#define PCI_64BIT_BAR2	2 +#define PCI_64BIT_BAR4	4  	void __iomem *MBslimaddr;	/* virtual address for mbox cmds */  	void __iomem *HAregaddr;	/* virtual address for host attn reg */  	void __iomem *CAregaddr;	/* virtual address for chip attn reg */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index a47cfbdd05f2..6e93b886cd4d 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -106,6 +106,7 @@ struct lpfc_sli_intf {  #define LPFC_SLI4_MB_WORD_COUNT		64  #define LPFC_MAX_MQ_PAGE		8 +#define LPFC_MAX_WQ_PAGE_V0		4  #define LPFC_MAX_WQ_PAGE		8  #define LPFC_MAX_CQ_PAGE		4  #define LPFC_MAX_EQ_PAGE		8 @@ -703,24 +704,41 @@ struct lpfc_register {   * BAR0.  The offsets are the same so the driver must account for   * any base address difference.   */ -#define LPFC_RQ_DOORBELL		0x00A0 -#define lpfc_rq_doorbell_num_posted_SHIFT	16 -#define lpfc_rq_doorbell_num_posted_MASK	0x3FFF -#define lpfc_rq_doorbell_num_posted_WORD	word0 -#define lpfc_rq_doorbell_id_SHIFT		0 -#define lpfc_rq_doorbell_id_MASK		0xFFFF -#define lpfc_rq_doorbell_id_WORD		word0 - -#define LPFC_WQ_DOORBELL		0x0040 -#define lpfc_wq_doorbell_num_posted_SHIFT	24 -#define lpfc_wq_doorbell_num_posted_MASK	0x00FF -#define lpfc_wq_doorbell_num_posted_WORD	word0 -#define lpfc_wq_doorbell_index_SHIFT		16 -#define lpfc_wq_doorbell_index_MASK		0x00FF -#define lpfc_wq_doorbell_index_WORD		word0 -#define lpfc_wq_doorbell_id_SHIFT		0 -#define lpfc_wq_doorbell_id_MASK		0xFFFF -#define lpfc_wq_doorbell_id_WORD		word0 +#define LPFC_ULP0_RQ_DOORBELL		0x00A0 +#define LPFC_ULP1_RQ_DOORBELL		0x00C0 +#define lpfc_rq_db_list_fm_num_posted_SHIFT	24 +#define lpfc_rq_db_list_fm_num_posted_MASK	0x00FF +#define lpfc_rq_db_list_fm_num_posted_WORD	word0 +#define lpfc_rq_db_list_fm_index_SHIFT		16 +#define lpfc_rq_db_list_fm_index_MASK		0x00FF +#define lpfc_rq_db_list_fm_index_WORD		word0 +#define lpfc_rq_db_list_fm_id_SHIFT		0 +#define lpfc_rq_db_list_fm_id_MASK		0xFFFF +#define lpfc_rq_db_list_fm_id_WORD		word0 +#define lpfc_rq_db_ring_fm_num_posted_SHIFT	16 +#define lpfc_rq_db_ring_fm_num_posted_MASK	0x3FFF +#define lpfc_rq_db_ring_fm_num_posted_WORD	word0 +#define lpfc_rq_db_ring_fm_id_SHIFT		0 +#define lpfc_rq_db_ring_fm_id_MASK		0xFFFF +#define lpfc_rq_db_ring_fm_id_WORD		word0 + +#define LPFC_ULP0_WQ_DOORBELL		0x0040 +#define LPFC_ULP1_WQ_DOORBELL		0x0060 +#define lpfc_wq_db_list_fm_num_posted_SHIFT	24 +#define lpfc_wq_db_list_fm_num_posted_MASK	0x00FF +#define lpfc_wq_db_list_fm_num_posted_WORD	word0 +#define lpfc_wq_db_list_fm_index_SHIFT		16 +#define lpfc_wq_db_list_fm_index_MASK		0x00FF +#define lpfc_wq_db_list_fm_index_WORD		word0 +#define lpfc_wq_db_list_fm_id_SHIFT		0 +#define lpfc_wq_db_list_fm_id_MASK		0xFFFF +#define lpfc_wq_db_list_fm_id_WORD		word0 +#define lpfc_wq_db_ring_fm_num_posted_SHIFT     16 +#define lpfc_wq_db_ring_fm_num_posted_MASK      0x3FFF +#define lpfc_wq_db_ring_fm_num_posted_WORD      word0 +#define lpfc_wq_db_ring_fm_id_SHIFT             0 +#define lpfc_wq_db_ring_fm_id_MASK              0xFFFF +#define lpfc_wq_db_ring_fm_id_WORD              word0  #define LPFC_EQCQ_DOORBELL		0x0120  #define lpfc_eqcq_doorbell_se_SHIFT		31 @@ -1131,12 +1149,22 @@ struct lpfc_mbx_wq_create {  		struct {	/* Version 0 Request */  			uint32_t word0;  #define lpfc_mbx_wq_create_num_pages_SHIFT	0 -#define lpfc_mbx_wq_create_num_pages_MASK	0x0000FFFF +#define lpfc_mbx_wq_create_num_pages_MASK	0x000000FF  #define lpfc_mbx_wq_create_num_pages_WORD	word0 +#define lpfc_mbx_wq_create_dua_SHIFT		8 +#define lpfc_mbx_wq_create_dua_MASK		0x00000001 +#define lpfc_mbx_wq_create_dua_WORD		word0  #define lpfc_mbx_wq_create_cq_id_SHIFT		16  #define lpfc_mbx_wq_create_cq_id_MASK		0x0000FFFF  #define lpfc_mbx_wq_create_cq_id_WORD		word0 -			struct dma_address page[LPFC_MAX_WQ_PAGE]; +			struct dma_address page[LPFC_MAX_WQ_PAGE_V0]; +			uint32_t word9; +#define lpfc_mbx_wq_create_bua_SHIFT		0 +#define lpfc_mbx_wq_create_bua_MASK		0x00000001 +#define lpfc_mbx_wq_create_bua_WORD		word9 +#define lpfc_mbx_wq_create_ulp_num_SHIFT	8 +#define lpfc_mbx_wq_create_ulp_num_MASK		0x000000FF +#define lpfc_mbx_wq_create_ulp_num_WORD		word9  		} request;  		struct {	/* Version 1 Request */  			uint32_t word0;	/* Word 0 is the same as in v0 */ @@ -1160,6 +1188,17 @@ struct lpfc_mbx_wq_create {  #define lpfc_mbx_wq_create_q_id_SHIFT	0  #define lpfc_mbx_wq_create_q_id_MASK	0x0000FFFF  #define lpfc_mbx_wq_create_q_id_WORD	word0 +			uint32_t doorbell_offset; +			uint32_t word2; +#define lpfc_mbx_wq_create_bar_set_SHIFT	0 +#define lpfc_mbx_wq_create_bar_set_MASK		0x0000FFFF +#define lpfc_mbx_wq_create_bar_set_WORD		word2 +#define WQ_PCI_BAR_0_AND_1	0x00 +#define WQ_PCI_BAR_2_AND_3	0x01 +#define WQ_PCI_BAR_4_AND_5	0x02 +#define lpfc_mbx_wq_create_db_format_SHIFT	16 +#define lpfc_mbx_wq_create_db_format_MASK	0x0000FFFF +#define lpfc_mbx_wq_create_db_format_WORD	word2  		} response;  	} u;  }; @@ -1223,14 +1262,31 @@ struct lpfc_mbx_rq_create {  #define lpfc_mbx_rq_create_num_pages_SHIFT	0  #define lpfc_mbx_rq_create_num_pages_MASK	0x0000FFFF  #define lpfc_mbx_rq_create_num_pages_WORD	word0 +#define lpfc_mbx_rq_create_dua_SHIFT		16 +#define lpfc_mbx_rq_create_dua_MASK		0x00000001 +#define lpfc_mbx_rq_create_dua_WORD		word0 +#define lpfc_mbx_rq_create_bqu_SHIFT		17 +#define lpfc_mbx_rq_create_bqu_MASK		0x00000001 +#define lpfc_mbx_rq_create_bqu_WORD		word0 +#define lpfc_mbx_rq_create_ulp_num_SHIFT	24 +#define lpfc_mbx_rq_create_ulp_num_MASK		0x000000FF +#define lpfc_mbx_rq_create_ulp_num_WORD		word0  			struct rq_context context;  			struct dma_address page[LPFC_MAX_WQ_PAGE];  		} request;  		struct {  			uint32_t word0; -#define lpfc_mbx_rq_create_q_id_SHIFT	0 -#define lpfc_mbx_rq_create_q_id_MASK	0x0000FFFF -#define lpfc_mbx_rq_create_q_id_WORD	word0 +#define lpfc_mbx_rq_create_q_id_SHIFT		0 +#define lpfc_mbx_rq_create_q_id_MASK		0x0000FFFF +#define lpfc_mbx_rq_create_q_id_WORD		word0 +			uint32_t doorbell_offset; +			uint32_t word2; +#define lpfc_mbx_rq_create_bar_set_SHIFT	0 +#define lpfc_mbx_rq_create_bar_set_MASK		0x0000FFFF +#define lpfc_mbx_rq_create_bar_set_WORD		word2 +#define lpfc_mbx_rq_create_db_format_SHIFT	16 +#define lpfc_mbx_rq_create_db_format_MASK	0x0000FFFF +#define lpfc_mbx_rq_create_db_format_WORD	word2  		} response;  	} u;  }; @@ -1388,6 +1444,33 @@ struct lpfc_mbx_get_rsrc_extent_info {  	} u;  }; +struct lpfc_mbx_query_fw_config { +	struct mbox_header header; +	struct { +		uint32_t config_number; +#define	LPFC_FC_FCOE		0x00000007 +		uint32_t asic_revision; +		uint32_t physical_port; +		uint32_t function_mode; +#define LPFC_FCOE_INI_MODE	0x00000040 +#define LPFC_FCOE_TGT_MODE	0x00000080 +#define LPFC_DUA_MODE		0x00000800 +		uint32_t ulp0_mode; +#define LPFC_ULP_FCOE_INIT_MODE	0x00000040 +#define LPFC_ULP_FCOE_TGT_MODE	0x00000080 +		uint32_t ulp0_nap_words[12]; +		uint32_t ulp1_mode; +		uint32_t ulp1_nap_words[12]; +		uint32_t function_capabilities; +		uint32_t cqid_base; +		uint32_t cqid_tot; +		uint32_t eqid_base; +		uint32_t eqid_tot; +		uint32_t ulp0_nap2_words[2]; +		uint32_t ulp1_nap2_words[2]; +	} rsp; +}; +  struct lpfc_id_range {  	uint32_t word5;  #define lpfc_mbx_rsrc_id_word4_0_SHIFT	0 @@ -1803,51 +1886,6 @@ struct lpfc_mbx_redisc_fcf_tbl {  #define lpfc_mbx_redisc_fcf_index_WORD		word12  }; -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_mode -#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 @@ -2965,7 +3003,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_query_fw_config query_fw_cfg;  		struct lpfc_mbx_supp_pages supp_pages;  		struct lpfc_mbx_pc_sli4_params sli4_params;  		struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5262049651ee..26ca2efa976e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6233,9 +6233,11 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)  			phba->sli4_hba.conf_regs_memmap_p +  						LPFC_CTL_PORT_SEM_OFFSET;  		phba->sli4_hba.RQDBregaddr = -			phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL; +			phba->sli4_hba.conf_regs_memmap_p + +						LPFC_ULP0_RQ_DOORBELL;  		phba->sli4_hba.WQDBregaddr = -			phba->sli4_hba.conf_regs_memmap_p + LPFC_WQ_DOORBELL; +			phba->sli4_hba.conf_regs_memmap_p + +						LPFC_ULP0_WQ_DOORBELL;  		phba->sli4_hba.EQCQDBregaddr =  			phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;  		phba->sli4_hba.MQDBregaddr = @@ -6289,9 +6291,11 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)  		return -ENODEV;  	phba->sli4_hba.RQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + -				vf * LPFC_VFR_PAGE_SIZE + LPFC_RQ_DOORBELL); +				vf * LPFC_VFR_PAGE_SIZE + +					LPFC_ULP0_RQ_DOORBELL);  	phba->sli4_hba.WQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + -				vf * LPFC_VFR_PAGE_SIZE + LPFC_WQ_DOORBELL); +				vf * LPFC_VFR_PAGE_SIZE + +					LPFC_ULP0_WQ_DOORBELL);  	phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +  				vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL);  	phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + @@ -6987,6 +6991,19 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)  		phba->sli4_hba.fcp_wq = NULL;  	} +	if (phba->pci_bar0_memmap_p) { +		iounmap(phba->pci_bar0_memmap_p); +		phba->pci_bar0_memmap_p = NULL; +	} +	if (phba->pci_bar2_memmap_p) { +		iounmap(phba->pci_bar2_memmap_p); +		phba->pci_bar2_memmap_p = NULL; +	} +	if (phba->pci_bar4_memmap_p) { +		iounmap(phba->pci_bar4_memmap_p); +		phba->pci_bar4_memmap_p = NULL; +	} +  	/* Release FCP CQ mapping array */  	if (phba->sli4_hba.fcp_cq_map != NULL) {  		kfree(phba->sli4_hba.fcp_cq_map); @@ -7050,6 +7067,53 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)  	int rc = -ENOMEM;  	int fcp_eqidx, fcp_cqidx, fcp_wqidx;  	int fcp_cq_index = 0; +	uint32_t shdr_status, shdr_add_status; +	union lpfc_sli4_cfg_shdr *shdr; +	LPFC_MBOXQ_t *mboxq; +	uint32_t length; + +	/* Check for dual-ULP support */ +	mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); +	if (!mboxq) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"3249 Unable to allocate memory for " +				"QUERY_FW_CFG mailbox command\n"); +		return -ENOMEM; +	} +	length = (sizeof(struct lpfc_mbx_query_fw_config) - +		  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); + +	shdr = (union lpfc_sli4_cfg_shdr *) +			&mboxq->u.mqe.un.sli4_config.header.cfg_shdr; +	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); +	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); +	if (shdr_status || shdr_add_status || rc) { +		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +				"3250 QUERY_FW_CFG mailbox failed with status " +				"x%x add_status x%x, mbx status x%x\n", +				shdr_status, shdr_add_status, rc); +		if (rc != MBX_TIMEOUT) +			mempool_free(mboxq, phba->mbox_mem_pool); +		rc = -ENXIO; +		goto out_error; +	} + +	phba->sli4_hba.fw_func_mode = +			mboxq->u.mqe.un.query_fw_cfg.rsp.function_mode; +	phba->sli4_hba.ulp0_mode = mboxq->u.mqe.un.query_fw_cfg.rsp.ulp0_mode; +	phba->sli4_hba.ulp1_mode = mboxq->u.mqe.un.query_fw_cfg.rsp.ulp1_mode; +	lpfc_printf_log(phba, KERN_INFO, LOG_INIT, +			"3251 QUERY_FW_CFG: func_mode:x%x, ulp0_mode:x%x, " +			"ulp1_mode:x%x\n", phba->sli4_hba.fw_func_mode, +			phba->sli4_hba.ulp0_mode, phba->sli4_hba.ulp1_mode); + +	if (rc != MBX_TIMEOUT) +		mempool_free(mboxq, phba->mbox_mem_pool);  	/*  	 * Set up HBA Event Queues (EQs) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c997b919b6fe..0988b320d317 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -124,10 +124,17 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)  	/* Ring Doorbell */  	doorbell.word0 = 0; -	bf_set(lpfc_wq_doorbell_num_posted, &doorbell, 1); -	bf_set(lpfc_wq_doorbell_index, &doorbell, host_index); -	bf_set(lpfc_wq_doorbell_id, &doorbell, q->queue_id); -	writel(doorbell.word0, q->phba->sli4_hba.WQDBregaddr); +	if (q->db_format == LPFC_DB_LIST_FORMAT) { +		bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1); +		bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index); +		bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id); +	} else if (q->db_format == LPFC_DB_RING_FORMAT) { +		bf_set(lpfc_wq_db_ring_fm_num_posted, &doorbell, 1); +		bf_set(lpfc_wq_db_ring_fm_id, &doorbell, q->queue_id); +	} else { +		return -EINVAL; +	} +	writel(doorbell.word0, q->db_regaddr);  	return 0;  } @@ -456,10 +463,20 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,  	/* Ring The Header Receive Queue Doorbell */  	if (!(hq->host_index % hq->entry_repost)) {  		doorbell.word0 = 0; -		bf_set(lpfc_rq_doorbell_num_posted, &doorbell, -		       hq->entry_repost); -		bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id); -		writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr); +		if (hq->db_format == LPFC_DB_RING_FORMAT) { +			bf_set(lpfc_rq_db_ring_fm_num_posted, &doorbell, +			       hq->entry_repost); +			bf_set(lpfc_rq_db_ring_fm_id, &doorbell, hq->queue_id); +		} else if (hq->db_format == LPFC_DB_LIST_FORMAT) { +			bf_set(lpfc_rq_db_list_fm_num_posted, &doorbell, +			       hq->entry_repost); +			bf_set(lpfc_rq_db_list_fm_index, &doorbell, +			       hq->host_index); +			bf_set(lpfc_rq_db_list_fm_id, &doorbell, hq->queue_id); +		} else { +			return -EINVAL; +		} +		writel(doorbell.word0, hq->db_regaddr);  	}  	return put_index;  } @@ -4939,7 +4956,7 @@ out_free_mboxq:  static void  lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)  { -	uint8_t fcp_eqidx; +	int fcp_eqidx;  	lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM);  	lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); @@ -11867,7 +11884,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)  	struct lpfc_eqe *eqe;  	unsigned long iflag;  	int ecount = 0; -	uint32_t fcp_eqidx; +	int fcp_eqidx;  	/* Get the driver's phba structure from the dev_id */  	fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id; @@ -11969,7 +11986,7 @@ lpfc_sli4_intr_handler(int irq, void *dev_id)  	struct lpfc_hba  *phba;  	irqreturn_t hba_irq_rc;  	bool hba_handled = false; -	uint32_t fcp_eqidx; +	int fcp_eqidx;  	/* Get the driver's phba structure from the dev_id */  	phba = (struct lpfc_hba *)dev_id; @@ -12091,6 +12108,54 @@ out_fail:  }  /** + * lpfc_dual_chute_pci_bar_map - Map pci base address register to host memory + * @phba: HBA structure that indicates port to create a queue on. + * @pci_barset: PCI BAR set flag. + * + * This function shall perform iomap of the specified PCI BAR address to host + * memory address if not already done so and return it. The returned host + * memory address can be NULL. + */ +static void __iomem * +lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset) +{ +	struct pci_dev *pdev; +	unsigned long bar_map, bar_map_len; + +	if (!phba->pcidev) +		return NULL; +	else +		pdev = phba->pcidev; + +	switch (pci_barset) { +	case WQ_PCI_BAR_0_AND_1: +		if (!phba->pci_bar0_memmap_p) { +			bar_map = pci_resource_start(pdev, PCI_64BIT_BAR0); +			bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR0); +			phba->pci_bar0_memmap_p = ioremap(bar_map, bar_map_len); +		} +		return phba->pci_bar0_memmap_p; +	case WQ_PCI_BAR_2_AND_3: +		if (!phba->pci_bar2_memmap_p) { +			bar_map = pci_resource_start(pdev, PCI_64BIT_BAR2); +			bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR2); +			phba->pci_bar2_memmap_p = ioremap(bar_map, bar_map_len); +		} +		return phba->pci_bar2_memmap_p; +	case WQ_PCI_BAR_4_AND_5: +		if (!phba->pci_bar4_memmap_p) { +			bar_map = pci_resource_start(pdev, PCI_64BIT_BAR4); +			bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR4); +			phba->pci_bar4_memmap_p = ioremap(bar_map, bar_map_len); +		} +		return phba->pci_bar4_memmap_p; +	default: +		break; +	} +	return NULL; +} + +/**   * lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs   * @phba: HBA structure that indicates port to create a queue on.   * @startq: The starting FCP EQ to modify @@ -12667,6 +12732,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,  	union lpfc_sli4_cfg_shdr *shdr;  	uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;  	struct dma_address *page; +	void __iomem *bar_memmap_p; +	uint32_t db_offset; +	uint16_t pci_barset;  	/* sanity check on queue memory */  	if (!wq || !cq) @@ -12690,6 +12758,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,  		    cq->queue_id);  	bf_set(lpfc_mbox_hdr_version, &shdr->request,  	       phba->sli4_hba.pc_sli4_params.wqv); +  	if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) {  		bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,  		       wq->entry_count); @@ -12717,6 +12786,10 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,  		page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys);  		page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys);  	} + +	if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) +		bf_set(lpfc_mbx_wq_create_dua, &wq_create->u.request, 1); +  	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);  	/* The IOCTL status is embedded in the mailbox subheader. */  	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); @@ -12734,6 +12807,47 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,  		status = -ENXIO;  		goto out;  	} +	if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { +		wq->db_format = bf_get(lpfc_mbx_wq_create_db_format, +				       &wq_create->u.response); +		if ((wq->db_format != LPFC_DB_LIST_FORMAT) && +		    (wq->db_format != LPFC_DB_RING_FORMAT)) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3265 WQ[%d] doorbell format not " +					"supported: x%x\n", wq->queue_id, +					wq->db_format); +			status = -EINVAL; +			goto out; +		} +		pci_barset = bf_get(lpfc_mbx_wq_create_bar_set, +				    &wq_create->u.response); +		bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); +		if (!bar_memmap_p) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3263 WQ[%d] failed to memmap pci " +					"barset:x%x\n", wq->queue_id, +					pci_barset); +			status = -ENOMEM; +			goto out; +		} +		db_offset = wq_create->u.response.doorbell_offset; +		if ((db_offset != LPFC_ULP0_WQ_DOORBELL) && +		    (db_offset != LPFC_ULP1_WQ_DOORBELL)) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3252 WQ[%d] doorbell offset not " +					"supported: x%x\n", wq->queue_id, +					db_offset); +			status = -EINVAL; +			goto out; +		} +		wq->db_regaddr = bar_memmap_p + db_offset; +		lpfc_printf_log(phba, KERN_INFO, LOG_INIT, +				"3264 WQ[%d]: barset:x%x, offset:x%x\n", +				wq->queue_id, pci_barset, db_offset); +	} else { +		wq->db_format = LPFC_DB_LIST_FORMAT; +		wq->db_regaddr = phba->sli4_hba.WQDBregaddr; +	}  	wq->type = LPFC_WQ;  	wq->assoc_qid = cq->queue_id;  	wq->subtype = subtype; @@ -12810,6 +12924,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,  	uint32_t shdr_status, shdr_add_status;  	union lpfc_sli4_cfg_shdr *shdr;  	uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; +	void __iomem *bar_memmap_p; +	uint32_t db_offset; +	uint16_t pci_barset;  	/* sanity check on queue memory */  	if (!hrq || !drq || !cq) @@ -12888,6 +13005,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,  		rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =  					putPaddrHigh(dmabuf->phys);  	} +	if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) +		bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1); +  	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);  	/* The IOCTL status is embedded in the mailbox subheader. */  	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); @@ -12905,6 +13025,50 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,  		status = -ENXIO;  		goto out;  	} + +	if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { +		hrq->db_format = bf_get(lpfc_mbx_rq_create_db_format, +					&rq_create->u.response); +		if ((hrq->db_format != LPFC_DB_LIST_FORMAT) && +		    (hrq->db_format != LPFC_DB_RING_FORMAT)) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3262 RQ [%d] doorbell format not " +					"supported: x%x\n", hrq->queue_id, +					hrq->db_format); +			status = -EINVAL; +			goto out; +		} + +		pci_barset = bf_get(lpfc_mbx_rq_create_bar_set, +				    &rq_create->u.response); +		bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); +		if (!bar_memmap_p) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3269 RQ[%d] failed to memmap pci " +					"barset:x%x\n", hrq->queue_id, +					pci_barset); +			status = -ENOMEM; +			goto out; +		} + +		db_offset = rq_create->u.response.doorbell_offset; +		if ((db_offset != LPFC_ULP0_RQ_DOORBELL) && +		    (db_offset != LPFC_ULP1_RQ_DOORBELL)) { +			lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +					"3270 RQ[%d] doorbell offset not " +					"supported: x%x\n", hrq->queue_id, +					db_offset); +			status = -EINVAL; +			goto out; +		} +		hrq->db_regaddr = bar_memmap_p + db_offset; +		lpfc_printf_log(phba, KERN_INFO, LOG_INIT, +				"3266 RQ[qid:%d]: barset:x%x, offset:x%x\n", +				hrq->queue_id, pci_barset, db_offset); +	} else { +		hrq->db_format = LPFC_DB_RING_FORMAT; +		hrq->db_regaddr = phba->sli4_hba.RQDBregaddr; +	}  	hrq->type = LPFC_HRQ;  	hrq->assoc_qid = cq->queue_id;  	hrq->subtype = subtype; @@ -12970,6 +13134,8 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,  		rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =  					putPaddrHigh(dmabuf->phys);  	} +	if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) +		bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1);  	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);  	/* The IOCTL status is embedded in the mailbox subheader. */  	shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 44c427a45d66..be02b59ea279 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -139,6 +139,10 @@ struct lpfc_queue {  	struct lpfc_sli_ring *pring; /* ptr to io ring associated with q */ +	uint16_t db_format; +#define LPFC_DB_RING_FORMAT	0x01 +#define LPFC_DB_LIST_FORMAT	0x02 +	void __iomem *db_regaddr;  	/* For q stats */  	uint32_t q_cnt_1;  	uint32_t q_cnt_2; @@ -508,6 +512,10 @@ struct lpfc_sli4_hba {  	struct lpfc_queue *hdr_rq; /* Slow-path Header Receive queue */  	struct lpfc_queue *dat_rq; /* Slow-path Data Receive queue */ +	uint8_t fw_func_mode;	/* FW function protocol mode */ +	uint32_t ulp0_mode;	/* ULP0 protocol mode */ +	uint32_t ulp1_mode;	/* ULP1 protocol mode */ +  	/* Setup information for various queue parameters */  	int eq_esize;  	int eq_ecount; | 
