From 0a3db7c0a3e566e872aa9b0ac2eaf1353be7ffcc Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Sat, 28 Sep 2013 15:35:49 -0700 Subject: [PATCH] [SCSI] be2iscsi: Fix CID allocation/freeing to support Dual chute mode Configuration parameters returns the number of connection that can be offloaded one each chute. Signed-off-by: John Soni Jose Signed-off-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 54 ++++++++++++---- drivers/scsi/be2iscsi/be_main.c | 108 +++++++++++++++++++++++++------ drivers/scsi/be2iscsi/be_main.h | 20 ++++-- drivers/scsi/be2iscsi/be_mgmt.c | 16 ++++- 4 files changed, 160 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index f698f7aa7ef9..63b2be0f58a8 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -964,15 +964,31 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) */ static int beiscsi_get_cid(struct beiscsi_hba *phba) { - unsigned short cid = 0xFFFF; - - if (!phba->avlbl_cids) - return cid; - - cid = phba->cid_array[phba->cid_alloc++]; - if (phba->cid_alloc == phba->params.cxns_per_ctrl) - phba->cid_alloc = 0; - phba->avlbl_cids--; + unsigned short cid = 0xFFFF, cid_from_ulp; + struct ulp_cid_info *cid_info = NULL; + uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; + + /* Find the ULP which has more CID available */ + cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? + BEISCSI_ULP0_AVLBL_CID(phba) : 0; + cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ? + BEISCSI_ULP1_AVLBL_CID(phba) : 0; + cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? + BEISCSI_ULP0 : BEISCSI_ULP1; + + if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) { + cid_info = phba->cid_array_info[cid_from_ulp]; + if (!cid_info->avlbl_cids) + return cid; + + cid = cid_info->cid_array[cid_info->cid_alloc++]; + + if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT( + phba, cid_from_ulp)) + cid_info->cid_alloc = 0; + + cid_info->avlbl_cids--; + } return cid; } @@ -983,10 +999,22 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) */ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) { - phba->avlbl_cids++; - phba->cid_array[phba->cid_free++] = cid; - if (phba->cid_free == phba->params.cxns_per_ctrl) - phba->cid_free = 0; + uint16_t cid_post_ulp; + struct hwi_controller *phwi_ctrlr; + struct hwi_wrb_context *pwrb_context; + struct ulp_cid_info *cid_info = NULL; + uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); + + phwi_ctrlr = phba->phwi_ctrlr; + pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; + cid_post_ulp = pwrb_context->ulp_num; + + cid_info = phba->cid_array_info[cid_post_ulp]; + cid_info->avlbl_cids++; + + cid_info->cid_array[cid_info->cid_free++] = cid; + if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) + cid_info->cid_free = 0; } /** diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8595908e62dc..b57e5bd62018 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -4079,15 +4079,46 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) static int hba_setup_cid_tbls(struct beiscsi_hba *phba) { - int i; + int ret; + uint16_t i, ulp_num; + struct ulp_cid_info *ptr_cid_info = NULL; - phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, - GFP_KERNEL); - if (!phba->cid_array) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, - "BM_%d : Failed to allocate memory in " - "hba_setup_cid_tbls\n"); - return -ENOMEM; + for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { + if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { + ptr_cid_info = kzalloc(sizeof(struct ulp_cid_info), + GFP_KERNEL); + + if (!ptr_cid_info) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BM_%d : Failed to allocate memory" + "for ULP_CID_INFO for ULP : %d\n", + ulp_num); + ret = -ENOMEM; + goto free_memory; + + } + + /* Allocate memory for CID array */ + ptr_cid_info->cid_array = kzalloc(sizeof(void *) * + BEISCSI_GET_CID_COUNT(phba, + ulp_num), GFP_KERNEL); + if (!ptr_cid_info->cid_array) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BM_%d : Failed to allocate memory" + "for CID_ARRAY for ULP : %d\n", + ulp_num); + kfree(ptr_cid_info); + ptr_cid_info = NULL; + ret = -ENOMEM; + + goto free_memory; + } + ptr_cid_info->avlbl_cids = BEISCSI_GET_CID_COUNT( + phba, ulp_num); + + /* Save the cid_info_array ptr */ + phba->cid_array_info[ulp_num] = ptr_cid_info; + } } phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * phba->params.cxns_per_ctrl, GFP_KERNEL); @@ -4095,9 +4126,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BM_%d : Failed to allocate memory in " "hba_setup_cid_tbls\n"); - kfree(phba->cid_array); - phba->cid_array = NULL; - return -ENOMEM; + ret = -ENOMEM; + + goto free_memory; } phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * @@ -4107,18 +4138,44 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) "BM_%d : Failed to allocate memory in" "hba_setup_cid_tbls\n"); - kfree(phba->cid_array); kfree(phba->ep_array); - phba->cid_array = NULL; phba->ep_array = NULL; - return -ENOMEM; + ret = -ENOMEM; } - for (i = 0; i < phba->params.cxns_per_ctrl; i++) - phba->cid_array[i] = phba->phwi_ctrlr->wrb_context[i].cid; + for (i = 0; i < phba->params.cxns_per_ctrl; i++) { + ulp_num = phba->phwi_ctrlr->wrb_context[i].ulp_num; + + ptr_cid_info = phba->cid_array_info[ulp_num]; + ptr_cid_info->cid_array[ptr_cid_info->cid_alloc++] = + phba->phwi_ctrlr->wrb_context[i].cid; + + } + + for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { + if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { + ptr_cid_info = phba->cid_array_info[ulp_num]; - phba->avlbl_cids = phba->params.cxns_per_ctrl; + ptr_cid_info->cid_alloc = 0; + ptr_cid_info->cid_free = 0; + } + } return 0; + +free_memory: + for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { + if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { + ptr_cid_info = phba->cid_array_info[ulp_num]; + + if (ptr_cid_info) { + kfree(ptr_cid_info->cid_array); + kfree(ptr_cid_info); + phba->cid_array_info[ulp_num] = NULL; + } + } + } + + return ret; } static void hwi_enable_intr(struct beiscsi_hba *phba) @@ -4373,7 +4430,8 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) static void beiscsi_clean_port(struct beiscsi_hba *phba) { - int mgmt_status; + int mgmt_status, ulp_num; + struct ulp_cid_info *ptr_cid_info = NULL; mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); if (mgmt_status) @@ -4384,9 +4442,21 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) hwi_cleanup(phba); kfree(phba->io_sgl_hndl_base); kfree(phba->eh_sgl_hndl_base); - kfree(phba->cid_array); kfree(phba->ep_array); kfree(phba->conn_table); + + for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { + if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { + ptr_cid_info = phba->cid_array_info[ulp_num]; + + if (ptr_cid_info) { + kfree(ptr_cid_info->cid_array); + kfree(ptr_cid_info); + phba->cid_array_info[ulp_num] = NULL; + } + } + } + } /** diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 410efc72bfd9..e5e0d7e32f04 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -297,6 +297,13 @@ struct hwi_wrb_context { uint32_t doorbell_offset; }; +struct ulp_cid_info { + unsigned short *cid_array; + unsigned short avlbl_cids; + unsigned short cid_alloc; + unsigned short cid_free; +}; + #include "be.h" #define chip_be2(phba) (phba->generation == BE_GEN2) #define chip_be3_r(phba) (phba->generation == BE_GEN3) @@ -307,6 +314,14 @@ struct hwi_wrb_context { #define BEISCSI_ULP_COUNT 2 #define BEISCSI_ULP0_LOADED 0x01 #define BEISCSI_ULP1_LOADED 0x02 + +#define BEISCSI_ULP_AVLBL_CID(phba, ulp_num) \ + (((struct ulp_cid_info *)phba->cid_array_info[ulp_num])->avlbl_cids) +#define BEISCSI_ULP0_AVLBL_CID(phba) \ + BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP0) +#define BEISCSI_ULP1_AVLBL_CID(phba) \ + BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP1) + struct beiscsi_hba { struct hba_parameters params; struct hwi_controller *phwi_ctrlr; @@ -343,16 +358,13 @@ struct beiscsi_hba { spinlock_t isr_lock; spinlock_t async_pdu_lock; unsigned int age; - unsigned short avlbl_cids; - unsigned short cid_alloc; - unsigned short cid_free; struct list_head hba_queue; #define BE_MAX_SESSION 2048 #define BE_SET_CID_TO_CRI(cri_index, cid) \ (phba->cid_to_cri_map[cid] = cri_index) #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) unsigned short cid_to_cri_map[BE_MAX_SESSION]; - unsigned short *cid_array; + struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT]; struct iscsi_endpoint **ep_array; struct beiscsi_conn **conn_table; struct iscsi_boot_kset *boot_kset; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 75756d722538..fcb9976e5ec6 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1338,9 +1338,21 @@ beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr, { struct Scsi_Host *shost = class_to_shost(dev); struct beiscsi_hba *phba = iscsi_host_priv(shost); + uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0; + + for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { + if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { + avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num); + total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num); + len += snprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, + (total_cids - avlbl_cids)); + } else + len += snprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, 0); + } - return snprintf(buf, PAGE_SIZE, "%d\n", - (phba->params.cxns_per_ctrl - phba->avlbl_cids)); + return len; } /** -- 2.30.2