Commit 0a3db7c0 authored by Jayamohan Kallickal's avatar Jayamohan Kallickal Committed by James Bottomley

[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: default avatarJohn Soni Jose <sony.john-n@emulex.com>
Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 4eea99d5
......@@ -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)
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 = phba->cid_array[phba->cid_alloc++];
if (phba->cid_alloc == phba->params.cxns_per_ctrl)
phba->cid_alloc = 0;
phba->avlbl_cids--;
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;
}
/**
......
......@@ -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,
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 (!phba->cid_array) {
if (!ptr_cid_info) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed to allocate memory in "
"hba_setup_cid_tbls\n");
return -ENOMEM;
"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;
}
}
}
}
/**
......
......@@ -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;
......
......@@ -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;
return snprintf(buf, PAGE_SIZE, "%d\n",
(phba->params.cxns_per_ctrl - phba->avlbl_cids));
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 len;
}
/**
......
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