From: Jayamohan Kallickal <jayamohan.kallickal@xxxxxxxxxx> Provides IRQ_Affinity setting for the driver. Enabling IRQ_Affinity is through module params. Default IRQ_AFFINITY support is OFF. Signed-off-by: John Soni Jose <sony.john-n@xxxxxxxxxx> Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@xxxxxxxxxx> --- drivers/scsi/be2iscsi/be_cmds.h | 9 +++- drivers/scsi/be2iscsi/be_main.c | 97 +++++++++++++++++++++++++++++++++++++++-- drivers/scsi/be2iscsi/be_main.h | 22 +++++++--- drivers/scsi/be2iscsi/be_mgmt.c | 63 ++++++++++++++++++++++++-- drivers/scsi/be2iscsi/be_mgmt.h | 49 ++++++++++++++++++--- 5 files changed, 222 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 770b6c8..69f849e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -174,6 +174,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_EQ_DESTROY 55 #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 #define OPCODE_COMMON_FUNCTION_RESET 61 +#define OPCODE_COMMON_GET_CNTL_ADV_ATTRIB 121 /** * LIST of opcodes that are common between Initiator and Target @@ -197,6 +198,8 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ISCSI_WRBQ_CREATE 66 #define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67 +#define MBOX_CMD_V2 0x01 + struct be_cmd_req_hdr { u8 opcode; /* dword 0 */ u8 subsystem; /* dword 0 */ @@ -966,6 +969,9 @@ struct amap_it_dmsg_cqe_v2 { #define DB_DEF_PDU_WRB_INDEX_SHIFT 16 #define DB_DEF_PDU_NUM_POSTED_SHIFT 24 +#define BEISCSI_IFD_STATE_DISABLE 0x0 +#define BEISCSI_IFD_STATE_ENABLE 0x1 + struct fragnum_bits_for_sgl_cra_in { struct be_cmd_req_hdr hdr; u32 num_bits; @@ -1002,7 +1008,8 @@ struct tcp_connect_and_offload_in { u16 hdr_ring_id; u16 data_ring_id; u8 do_offload; - u8 rsvd0[3]; + u8 ifd_state; + u8 rsvd0[2]; } __packed; struct tcp_connect_and_offload_out { diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 1a1729b..89bf558 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -47,6 +47,7 @@ static unsigned int be_iopoll_budget = 10; static unsigned int be_max_phys_size = 64; static unsigned int enable_msix = 1; +static unsigned int beiscsi_irq_affinity_enable; MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); @@ -59,6 +60,7 @@ module_param(be_max_phys_size, uint, S_IRUGO); MODULE_PARM_DESC(be_max_phys_size, "Maximum Size (In Kilobytes) of physically contiguous " "memory that can be allocated. Range is 16 - 128"); +module_param(beiscsi_irq_affinity_enable, uint, 0); #define beiscsi_disp_param(_name)\ ssize_t \ @@ -1026,6 +1028,46 @@ static irqreturn_t be_isr(int irq, void *dev_id) } } +static void beiscsi_set_irq_affinity_params(struct beiscsi_hba *phba, + uint16_t cpu_index, uint16_t eqcq_index, uint16_t msix_vec) +{ + struct hwi_controller *phwi_ctrlr; + struct hwi_context_memory *phwi_context; + + phwi_ctrlr = phba->phwi_ctrlr; + phwi_context = phwi_ctrlr->phwi_ctxt; + + if (msix_vec) { + if (cpu_online(cpu_index)) + cpumask_set_cpu(cpu_index, + &phba->msix_cpu_map[ + cpu_index].affinity_mask); + else + cpumask_copy(&phba->msix_cpu_map[ + cpu_index].affinity_mask, + cpu_online_mask); + + phba->msix_cpu_map[cpu_index].eq_id = + phwi_context->be_eq[eqcq_index].q.id; + phba->msix_cpu_map[cpu_index].cq_id = + phwi_context->be_cq[eqcq_index].id; + phba->msix_cpu_map[cpu_index].cpu_id = cpu_index; + phba->msix_cpu_map[cpu_index].nvec = msix_vec; + phba->msix_cpu_map[cpu_index].node_id = + cpu_to_node(cpu_index); + + irq_set_affinity_hint(msix_vec, + &phba->msix_cpu_map[ + cpu_index].affinity_mask); + } else { + phba->msix_cpu_map[cpu_index].eq_id = + phba->msix_cpu_map[eqcq_index].eq_id; + phba->msix_cpu_map[cpu_index].cq_id = + phba->msix_cpu_map[eqcq_index].cq_id; + phba->msix_cpu_map[cpu_index].cpu_id = cpu_index; + } +} + static int beiscsi_init_irqs(struct beiscsi_hba *phba) { struct pci_dev *pcidev = phba->pcidev; @@ -1059,7 +1101,11 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) kfree(phba->msi_name[i]); goto free_msix_irqs; } + if (beiscsi_irq_affinity_enable) + beiscsi_set_irq_affinity_params(phba, + i, i, msix_vec); } + phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL); if (!phba->msi_name[i]) { ret = -ENOMEM; @@ -1078,6 +1124,12 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) goto free_msix_irqs; } + if (beiscsi_irq_affinity_enable) { + j = i; + while (i++ < num_online_cpus()) + beiscsi_set_irq_affinity_params(phba, + i, (i - j), 0); + } } else { ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba); @@ -4663,10 +4715,9 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, /* Check for the adapter family */ if (is_chip_be2_be3r(phba)) - beiscsi_offload_cxn_v0(params, pwrb_handle, - phba->init_mem); + beiscsi_offload_cxn_v0(phba, params, pwrb_handle); else - beiscsi_offload_cxn_v2(params, pwrb_handle); + beiscsi_offload_cxn_v2(phba, params, pwrb_handle); be_dws_le_to_cpu(pwrb_handle->pwrb, sizeof(struct iscsi_target_context_update_wrb)); @@ -4860,6 +4911,8 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, struct beiscsi_hba *phba = beiscsi_conn->phba; struct iscsi_wrb *pwrb = NULL; unsigned int doorbell = 0; + uint8_t cpu_num; + u8 cq_num; pwrb = io_task->pwrb_handle->pwrb; @@ -4891,6 +4944,13 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, io_task->psgl_handle->sgl_index); hwi_write_sgl_v2(pwrb, sg, num_sg, io_task); + if (phba->func_caps & BE_ADAPTER_IFD_CAP) { + cpu_num = get_cpu(); + cq_num = phba->msix_cpu_map[cpu_num].cq_id; + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cq_id, pwrb, cq_num); + put_cpu(); + } + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, io_task->pwrb_handle->nxt_wrb_index); @@ -4917,6 +4977,7 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, struct beiscsi_hba *phba = beiscsi_conn->phba; struct iscsi_wrb *pwrb = NULL; unsigned int doorbell = 0; + uint8_t cpu_num, cq_num; pwrb = io_task->pwrb_handle->pwrb; io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; @@ -4948,6 +5009,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, hwi_write_sgl(pwrb, sg, num_sg, io_task); + if (phba->func_caps & BE_ADAPTER_IFD_CAP) { + cpu_num = get_cpu(); + cq_num = phba->msix_cpu_map[cpu_num].cq_id; + AMAP_SET_BITS(struct amap_iscsi_wrb, cq_id, pwrb, cq_num); + put_cpu(); + } + AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, io_task->pwrb_handle->nxt_wrb_index); be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); @@ -4972,6 +5040,7 @@ static int beiscsi_mtask(struct iscsi_task *task) unsigned int doorbell = 0; unsigned int cid; unsigned int pwrb_typeoffset = 0; + uint8_t cpu_num, cq_num; cid = beiscsi_conn->beiscsi_conn_cid; pwrb = io_task->pwrb_handle->pwrb; @@ -5003,6 +5072,19 @@ static int beiscsi_mtask(struct iscsi_task *task) pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; } + if (phba->func_caps & BE_ADAPTER_IFD_CAP) { + cpu_num = get_cpu(); + cq_num = phba->msix_cpu_map[cpu_num].cq_id; + + if (is_chip_be2_be3r(phba)) + AMAP_SET_BITS(struct amap_iscsi_wrb, + cq_id, pwrb, cq_num); + else + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + cq_id, pwrb, cq_num); + put_cpu(); + } + switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { case ISCSI_OP_LOGIN: @@ -5587,6 +5669,15 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, phba->num_cpus = 1; } + + if (beiscsi_irq_affinity_enable) { + if (mgmt_get_adapter_caps(phba)) + beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, + "BM_%d : Error in getting Capabilites" + "IRQ_Affinity setting is disabled\n"); + } else + phba->func_caps = BEISCSI_IFD_STATE_DISABLE; + phba->shost->max_id = phba->params.cxns_per_ctrl; beiscsi_get_params(phba); phba->shost->can_queue = phba->params.ios_per_ctrl; diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 31fa27b..0076119 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -234,6 +234,15 @@ struct sgl_handle { struct iscsi_sge *pfrag; }; +struct msix_vec_map { + cpumask_t affinity_mask; + u16 eq_id; + u16 cq_id; + u32 nvec; + unsigned int cpu_id; + unsigned int node_id; +}; + struct hba_parameters { unsigned int ios_per_ctrl; unsigned int cxns_per_ctrl; @@ -412,12 +421,13 @@ struct beiscsi_hba { unsigned int interface_handle; struct mgmt_session_info boot_sess; struct invalidate_command_table inv_tbl[128]; - + struct msix_vec_map msix_cpu_map[MAX_CPUS]; unsigned int attr_log_enable; int (*iotask_fn)(struct iscsi_task *, struct scatterlist *sg, uint32_t num_sg, uint32_t xferlen, uint32_t writedir); + uint32_t func_caps; }; struct beiscsi_session { @@ -479,20 +489,21 @@ struct be_cmd_bhs { struct beiscsi_io_task { struct wrb_handle *pwrb_handle; + struct be_cmd_bhs *cmd_bhs; + unsigned short bhs_len; struct sgl_handle *psgl_handle; + struct hwi_wrb_context *pwrb_context; struct beiscsi_conn *conn; struct scsi_cmnd *scsi_cmnd; + uint8_t wrb_type; unsigned int cmd_sn; unsigned int flags; unsigned short cid; unsigned short header_len; itt_t libiscsi_itt; - struct be_cmd_bhs *cmd_bhs; struct be_bus_address bhs_pa; - unsigned short bhs_len; dma_addr_t mtask_addr; uint32_t mtask_data_count; - uint8_t wrb_type; }; struct be_nonio_bhs { @@ -745,7 +756,8 @@ struct amap_iscsi_wrb { u8 ptr2nextwrb[8]; /* DWORD 1 */ u8 r2t_exp_dtl[24]; /* DWORD 1 */ u8 sgl_icd_idx[12]; /* DWORD 2 */ - u8 rsvd0[20]; /* DWORD 2 */ + u8 cq_id[10]; /* DWORD 2 */ + u8 rsvd0[10]; /* DWORD 2 */ u8 exp_data_sn[32]; /* DWORD 3 */ u8 iscsi_bhs_addr_hi[32]; /* DWORD 4 */ u8 iscsi_bhs_addr_lo[32]; /* DWORD 5 */ diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 088bdf7..1b6c3fb 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -758,11 +758,47 @@ int mgmt_open_connection(struct beiscsi_hba *phba, sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); sge->len = cpu_to_le32(nonemb_cmd->size); + + /* Enable interrupt redirection for CXN */ + if (phba->func_caps & BE_ADAPTER_IFD_CAP) + req->ifd_state = BEISCSI_IFD_STATE_ENABLE; + be_mcc_notify(phba); spin_unlock(&ctrl->mbox_lock); return tag; } +int mgmt_get_adapter_caps(struct beiscsi_hba *phba) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_mgmt_cntl_additional_attrib *req = embedded_payload(wrb); + int status = 0; + + spin_lock(&ctrl->mbox_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_CNTL_ADV_ATTRIB, + sizeof(*req)); + status = be_mbox_notify(ctrl); + + if (status) { + beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, + "BG_%d : Failed in mgmt_get_adapter_caps\n"); + spin_unlock(&ctrl->mbox_lock); + phba->func_caps = BEISCSI_IFD_STATE_DISABLE; + return status; + } + + phba->func_caps = req->params.func_caps; + spin_unlock(&ctrl->mbox_lock); + return status; +} + + + unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; @@ -1525,11 +1561,13 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, phba->fw_config.phys_port); } -void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, - struct wrb_handle *pwrb_handle, - struct be_mem_descriptor *mem_descr) +void beiscsi_offload_cxn_v0(struct beiscsi_hba *phba, + struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle) { struct iscsi_wrb *pwrb = pwrb_handle->pwrb; + struct be_mem_descriptor *mem_descr = phba->init_mem; + uint8_t cpu_num, cq_num; memset(pwrb, 0, sizeof(*pwrb)); AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, @@ -1588,12 +1626,21 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, pad_buffer_addr_lo, pwrb, mem_descr->mem_array[0].bus_address.u.a32.address_lo); + + if (phba->func_caps & BE_ADAPTER_IFD_CAP) { + cpu_num = get_cpu(); + cq_num = phba->msix_cpu_map[cpu_num].cq_id; + AMAP_SET_BITS(struct amap_iscsi_wrb, cq_id, pwrb, cq_num); + put_cpu(); + } } -void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, +void beiscsi_offload_cxn_v2(struct beiscsi_hba *phba, + struct beiscsi_offload_params *params, struct wrb_handle *pwrb_handle) { struct iscsi_wrb *pwrb = pwrb_handle->pwrb; + uint8_t cpu_num, cq_num; memset(pwrb, 0, sizeof(*pwrb)); @@ -1660,4 +1707,12 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, pwrb, (params->dw[offsetof(struct amap_beiscsi_offload_params, exp_statsn) / 32] + 1)); + + if (phba->func_caps & BE_ADAPTER_IFD_CAP) { + cpu_num = get_cpu(); + cq_num = phba->msix_cpu_map[cpu_num].cq_id; + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cq_id, pwrb, cq_num); + put_cpu(); + } + } diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 01b8c97..e1dd796 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -221,6 +221,41 @@ struct be_mgmt_controller_attributes_resp { struct mgmt_controller_attributes params; } __packed; +#define BE_ADAPTER_IFD_CAP 0x01 +struct mgmt_cntrl_additional_attrib { + u16 ipl_file_number; + u8 ipl_file_version; + u8 rsvd0; + u8 on_die_temp; + u8 rsvd1[3]; + u32 func_caps; + u32 rsvd2[4]; + u8 fcoe_universal_bios_version[32]; + u8 fcoe_x86_bios_version[32]; + u8 fcoe_efi_bios_version[32]; + u8 fcoe_fcode_version[32]; + u8 uefi_bios_version[32]; + u8 uefi_nic_version[32]; + u8 uefi_fcode_version[32]; + u8 uefi_iscsi_version[32]; + u8 iscsi_x86_bios_version[32]; + u8 pxe_x86_bios_version[32]; + u8 fcoe_default_wwpn[8]; + u8 ext_phy_version[32]; + u8 fc_universal_bios_version[32]; + u8 fc_x86_bios_version[32]; + u8 fc_efi_bios_version[32]; + u8 fc_fcode_version[32]; + u8 ext_phy_crc_label[8]; + u8 rsvd3[88]; +} __packed; + +struct be_mgmt_cntl_additional_attrib { + struct be_cmd_req_hdr hdr; + struct mgmt_cntrl_additional_attrib params; +} __packed; + + struct be_bsg_vendor_cmd { struct be_cmd_req_hdr hdr; unsigned short region; @@ -269,6 +304,8 @@ struct beiscsi_endpoint { int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); +int mgmt_get_adapter_caps(struct beiscsi_hba *phba); + unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, struct beiscsi_endpoint *beiscsi_ep, unsigned short cid, @@ -328,12 +365,14 @@ ssize_t beiscsi_free_session_disp(struct device *dev, ssize_t beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, char *buf); -void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, - struct wrb_handle *pwrb_handle, - struct be_mem_descriptor *mem_descr); - -void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, +void beiscsi_offload_cxn_v0(struct beiscsi_hba *phba, + struct beiscsi_offload_params *params, struct wrb_handle *pwrb_handle); + +void beiscsi_offload_cxn_v2(struct beiscsi_hba *phba, + struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle); + void beiscsi_ue_detect(struct beiscsi_hba *phba); #endif -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html