Commit 962bc51b authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.37: Provide support for FCoE protocol dual-chute (ULP) operation

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 8b455cf3
...@@ -752,6 +752,15 @@ struct lpfc_hba { ...@@ -752,6 +752,15 @@ struct lpfc_hba {
void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for
PCI BAR2 */ 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 *MBslimaddr; /* virtual address for mbox cmds */
void __iomem *HAregaddr; /* virtual address for host attn reg */ void __iomem *HAregaddr; /* virtual address for host attn reg */
void __iomem *CAregaddr; /* virtual address for chip attn reg */ void __iomem *CAregaddr; /* virtual address for chip attn reg */
......
...@@ -106,6 +106,7 @@ struct lpfc_sli_intf { ...@@ -106,6 +106,7 @@ struct lpfc_sli_intf {
#define LPFC_SLI4_MB_WORD_COUNT 64 #define LPFC_SLI4_MB_WORD_COUNT 64
#define LPFC_MAX_MQ_PAGE 8 #define LPFC_MAX_MQ_PAGE 8
#define LPFC_MAX_WQ_PAGE_V0 4
#define LPFC_MAX_WQ_PAGE 8 #define LPFC_MAX_WQ_PAGE 8
#define LPFC_MAX_CQ_PAGE 4 #define LPFC_MAX_CQ_PAGE 4
#define LPFC_MAX_EQ_PAGE 8 #define LPFC_MAX_EQ_PAGE 8
...@@ -703,24 +704,41 @@ struct lpfc_register { ...@@ -703,24 +704,41 @@ struct lpfc_register {
* BAR0. The offsets are the same so the driver must account for * BAR0. The offsets are the same so the driver must account for
* any base address difference. * any base address difference.
*/ */
#define LPFC_RQ_DOORBELL 0x00A0 #define LPFC_ULP0_RQ_DOORBELL 0x00A0
#define lpfc_rq_doorbell_num_posted_SHIFT 16 #define LPFC_ULP1_RQ_DOORBELL 0x00C0
#define lpfc_rq_doorbell_num_posted_MASK 0x3FFF #define lpfc_rq_db_list_fm_num_posted_SHIFT 24
#define lpfc_rq_doorbell_num_posted_WORD word0 #define lpfc_rq_db_list_fm_num_posted_MASK 0x00FF
#define lpfc_rq_doorbell_id_SHIFT 0 #define lpfc_rq_db_list_fm_num_posted_WORD word0
#define lpfc_rq_doorbell_id_MASK 0xFFFF #define lpfc_rq_db_list_fm_index_SHIFT 16
#define lpfc_rq_doorbell_id_WORD word0 #define lpfc_rq_db_list_fm_index_MASK 0x00FF
#define lpfc_rq_db_list_fm_index_WORD word0
#define LPFC_WQ_DOORBELL 0x0040 #define lpfc_rq_db_list_fm_id_SHIFT 0
#define lpfc_wq_doorbell_num_posted_SHIFT 24 #define lpfc_rq_db_list_fm_id_MASK 0xFFFF
#define lpfc_wq_doorbell_num_posted_MASK 0x00FF #define lpfc_rq_db_list_fm_id_WORD word0
#define lpfc_wq_doorbell_num_posted_WORD word0 #define lpfc_rq_db_ring_fm_num_posted_SHIFT 16
#define lpfc_wq_doorbell_index_SHIFT 16 #define lpfc_rq_db_ring_fm_num_posted_MASK 0x3FFF
#define lpfc_wq_doorbell_index_MASK 0x00FF #define lpfc_rq_db_ring_fm_num_posted_WORD word0
#define lpfc_wq_doorbell_index_WORD word0 #define lpfc_rq_db_ring_fm_id_SHIFT 0
#define lpfc_wq_doorbell_id_SHIFT 0 #define lpfc_rq_db_ring_fm_id_MASK 0xFFFF
#define lpfc_wq_doorbell_id_MASK 0xFFFF #define lpfc_rq_db_ring_fm_id_WORD word0
#define lpfc_wq_doorbell_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 0x0120
#define lpfc_eqcq_doorbell_se_SHIFT 31 #define lpfc_eqcq_doorbell_se_SHIFT 31
...@@ -1131,12 +1149,22 @@ struct lpfc_mbx_wq_create { ...@@ -1131,12 +1149,22 @@ struct lpfc_mbx_wq_create {
struct { /* Version 0 Request */ struct { /* Version 0 Request */
uint32_t word0; uint32_t word0;
#define lpfc_mbx_wq_create_num_pages_SHIFT 0 #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_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_SHIFT 16
#define lpfc_mbx_wq_create_cq_id_MASK 0x0000FFFF #define lpfc_mbx_wq_create_cq_id_MASK 0x0000FFFF
#define lpfc_mbx_wq_create_cq_id_WORD word0 #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; } request;
struct { /* Version 1 Request */ struct { /* Version 1 Request */
uint32_t word0; /* Word 0 is the same as in v0 */ uint32_t word0; /* Word 0 is the same as in v0 */
...@@ -1160,6 +1188,17 @@ struct lpfc_mbx_wq_create { ...@@ -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_SHIFT 0
#define lpfc_mbx_wq_create_q_id_MASK 0x0000FFFF #define lpfc_mbx_wq_create_q_id_MASK 0x0000FFFF
#define lpfc_mbx_wq_create_q_id_WORD word0 #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; } response;
} u; } u;
}; };
...@@ -1223,6 +1262,15 @@ struct lpfc_mbx_rq_create { ...@@ -1223,6 +1262,15 @@ struct lpfc_mbx_rq_create {
#define lpfc_mbx_rq_create_num_pages_SHIFT 0 #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_MASK 0x0000FFFF
#define lpfc_mbx_rq_create_num_pages_WORD word0 #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 rq_context context;
struct dma_address page[LPFC_MAX_WQ_PAGE]; struct dma_address page[LPFC_MAX_WQ_PAGE];
} request; } request;
...@@ -1231,6 +1279,14 @@ struct lpfc_mbx_rq_create { ...@@ -1231,6 +1279,14 @@ struct lpfc_mbx_rq_create {
#define lpfc_mbx_rq_create_q_id_SHIFT 0 #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_MASK 0x0000FFFF
#define lpfc_mbx_rq_create_q_id_WORD word0 #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; } response;
} u; } u;
}; };
...@@ -1388,6 +1444,33 @@ struct lpfc_mbx_get_rsrc_extent_info { ...@@ -1388,6 +1444,33 @@ struct lpfc_mbx_get_rsrc_extent_info {
} u; } 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 { struct lpfc_id_range {
uint32_t word5; uint32_t word5;
#define lpfc_mbx_rsrc_id_word4_0_SHIFT 0 #define lpfc_mbx_rsrc_id_word4_0_SHIFT 0
...@@ -1803,51 +1886,6 @@ struct lpfc_mbx_redisc_fcf_tbl { ...@@ -1803,51 +1886,6 @@ struct lpfc_mbx_redisc_fcf_tbl {
#define lpfc_mbx_redisc_fcf_index_WORD word12 #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 */ /* Status field for embedded SLI_CONFIG mailbox command */
#define STATUS_SUCCESS 0x0 #define STATUS_SUCCESS 0x0
#define STATUS_FAILED 0x1 #define STATUS_FAILED 0x1
...@@ -2965,7 +3003,7 @@ struct lpfc_mqe { ...@@ -2965,7 +3003,7 @@ struct lpfc_mqe {
struct lpfc_mbx_read_config rd_config; struct lpfc_mbx_read_config rd_config;
struct lpfc_mbx_request_features req_ftrs; struct lpfc_mbx_request_features req_ftrs;
struct lpfc_mbx_post_hdr_tmpl hdr_tmpl; 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_supp_pages supp_pages;
struct lpfc_mbx_pc_sli4_params sli4_params; struct lpfc_mbx_pc_sli4_params sli4_params;
struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
......
...@@ -6233,9 +6233,11 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) ...@@ -6233,9 +6233,11 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
phba->sli4_hba.conf_regs_memmap_p + phba->sli4_hba.conf_regs_memmap_p +
LPFC_CTL_PORT_SEM_OFFSET; LPFC_CTL_PORT_SEM_OFFSET;
phba->sli4_hba.RQDBregaddr = 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.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.EQCQDBregaddr =
phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL; phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
phba->sli4_hba.MQDBregaddr = phba->sli4_hba.MQDBregaddr =
...@@ -6289,9 +6291,11 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf) ...@@ -6289,9 +6291,11 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)
return -ENODEV; return -ENODEV;
phba->sli4_hba.RQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + 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 + 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 + phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL); vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL);
phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
...@@ -6987,6 +6991,19 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) ...@@ -6987,6 +6991,19 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
phba->sli4_hba.fcp_wq = NULL; 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 */ /* Release FCP CQ mapping array */
if (phba->sli4_hba.fcp_cq_map != NULL) { if (phba->sli4_hba.fcp_cq_map != NULL) {
kfree(phba->sli4_hba.fcp_cq_map); kfree(phba->sli4_hba.fcp_cq_map);
...@@ -7050,6 +7067,53 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) ...@@ -7050,6 +7067,53 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
int rc = -ENOMEM; int rc = -ENOMEM;
int fcp_eqidx, fcp_cqidx, fcp_wqidx; int fcp_eqidx, fcp_cqidx, fcp_wqidx;
int fcp_cq_index = 0; 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) * Set up HBA Event Queues (EQs)
......
...@@ -124,10 +124,17 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) ...@@ -124,10 +124,17 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
/* Ring Doorbell */ /* Ring Doorbell */
doorbell.word0 = 0; doorbell.word0 = 0;
bf_set(lpfc_wq_doorbell_num_posted, &doorbell, 1); if (q->db_format == LPFC_DB_LIST_FORMAT) {
bf_set(lpfc_wq_doorbell_index, &doorbell, host_index); bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1);
bf_set(lpfc_wq_doorbell_id, &doorbell, q->queue_id); bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index);
writel(doorbell.word0, q->phba->sli4_hba.WQDBregaddr); 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; return 0;
} }
...@@ -456,10 +463,20 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, ...@@ -456,10 +463,20 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
/* Ring The Header Receive Queue Doorbell */ /* Ring The Header Receive Queue Doorbell */
if (!(hq->host_index % hq->entry_repost)) { if (!(hq->host_index % hq->entry_repost)) {
doorbell.word0 = 0; doorbell.word0 = 0;
bf_set(lpfc_rq_doorbell_num_posted, &doorbell, 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); hq->entry_repost);
bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id); bf_set(lpfc_rq_db_list_fm_index, &doorbell,
writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr); 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; return put_index;
} }
...@@ -4939,7 +4956,7 @@ lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba) ...@@ -4939,7 +4956,7 @@ lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba)
static void static void
lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) 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.mbx_cq, LPFC_QUEUE_REARM);
lpfc_sli4_cq_release(phba->sli4_hba.els_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) ...@@ -11867,7 +11884,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
struct lpfc_eqe *eqe; struct lpfc_eqe *eqe;
unsigned long iflag; unsigned long iflag;
int ecount = 0; int ecount = 0;
uint32_t fcp_eqidx; int fcp_eqidx;
/* Get the driver's phba structure from the dev_id */ /* Get the driver's phba structure from the dev_id */
fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)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) ...@@ -11969,7 +11986,7 @@ lpfc_sli4_intr_handler(int irq, void *dev_id)
struct lpfc_hba *phba; struct lpfc_hba *phba;
irqreturn_t hba_irq_rc; irqreturn_t hba_irq_rc;
bool hba_handled = false; bool hba_handled = false;
uint32_t fcp_eqidx; int fcp_eqidx;
/* Get the driver's phba structure from the dev_id */ /* Get the driver's phba structure from the dev_id */
phba = (struct lpfc_hba *)dev_id; phba = (struct lpfc_hba *)dev_id;
...@@ -12090,6 +12107,54 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, ...@@ -12090,6 +12107,54 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
return NULL; return NULL;
} }
/**
* 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 * lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs
* @phba: HBA structure that indicates port to create a queue on. * @phba: HBA structure that indicates port to create a queue on.
...@@ -12667,6 +12732,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, ...@@ -12667,6 +12732,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
union lpfc_sli4_cfg_shdr *shdr; union lpfc_sli4_cfg_shdr *shdr;
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
struct dma_address *page; struct dma_address *page;
void __iomem *bar_memmap_p;
uint32_t db_offset;
uint16_t pci_barset;
/* sanity check on queue memory */ /* sanity check on queue memory */
if (!wq || !cq) if (!wq || !cq)
...@@ -12690,6 +12758,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, ...@@ -12690,6 +12758,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
cq->queue_id); cq->queue_id);
bf_set(lpfc_mbox_hdr_version, &shdr->request, bf_set(lpfc_mbox_hdr_version, &shdr->request,
phba->sli4_hba.pc_sli4_params.wqv); phba->sli4_hba.pc_sli4_params.wqv);
if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) { 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, bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,
wq->entry_count); wq->entry_count);
...@@ -12717,6 +12786,10 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, ...@@ -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_lo = putPaddrLow(dmabuf->phys);
page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(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); rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */ /* The IOCTL status is embedded in the mailbox subheader. */
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); 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, ...@@ -12734,6 +12807,47 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
status = -ENXIO; status = -ENXIO;
goto out; 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->type = LPFC_WQ;
wq->assoc_qid = cq->queue_id; wq->assoc_qid = cq->queue_id;
wq->subtype = subtype; wq->subtype = subtype;
...@@ -12810,6 +12924,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, ...@@ -12810,6 +12924,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
uint32_t shdr_status, shdr_add_status; uint32_t shdr_status, shdr_add_status;
union lpfc_sli4_cfg_shdr *shdr; union lpfc_sli4_cfg_shdr *shdr;
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; 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 */ /* sanity check on queue memory */
if (!hrq || !drq || !cq) if (!hrq || !drq || !cq)
...@@ -12888,6 +13005,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, ...@@ -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 = rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
putPaddrHigh(dmabuf->phys); 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); rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */ /* The IOCTL status is embedded in the mailbox subheader. */
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); 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, ...@@ -12905,6 +13025,50 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
status = -ENXIO; status = -ENXIO;
goto out; 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->type = LPFC_HRQ;
hrq->assoc_qid = cq->queue_id; hrq->assoc_qid = cq->queue_id;
hrq->subtype = subtype; hrq->subtype = subtype;
...@@ -12970,6 +13134,8 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, ...@@ -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 = rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
putPaddrHigh(dmabuf->phys); 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); rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */ /* The IOCTL status is embedded in the mailbox subheader. */
shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr; shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
......
...@@ -139,6 +139,10 @@ struct lpfc_queue { ...@@ -139,6 +139,10 @@ struct lpfc_queue {
struct lpfc_sli_ring *pring; /* ptr to io ring associated with q */ 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 */ /* For q stats */
uint32_t q_cnt_1; uint32_t q_cnt_1;
uint32_t q_cnt_2; uint32_t q_cnt_2;
...@@ -508,6 +512,10 @@ struct lpfc_sli4_hba { ...@@ -508,6 +512,10 @@ struct lpfc_sli4_hba {
struct lpfc_queue *hdr_rq; /* Slow-path Header Receive queue */ struct lpfc_queue *hdr_rq; /* Slow-path Header Receive queue */
struct lpfc_queue *dat_rq; /* Slow-path Data 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 */ /* Setup information for various queue parameters */
int eq_esize; int eq_esize;
int eq_ecount; int eq_ecount;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment