Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 271110
b: refs/heads/master
c: 4549415
h: refs/heads/master
v: v3
  • Loading branch information
Lalit Chandivade authored and James Bottomley committed Oct 16, 2011
1 parent 04a0854 commit b3cfdb0
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0854f665a1cbb4566d3ebe449169b0200b8cdad0
refs/heads/master: 4549415af6915017f5d3fbdbfd5edd1dfbe63fa9
10 changes: 9 additions & 1 deletion trunk/drivers/scsi/qla4xxx/ql4_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ struct ql82xx_hw_data {
uint32_t flt_region_fw;

uint32_t flt_iscsi_param;
uint32_t reserved;
uint32_t flt_region_chap;
uint32_t flt_chap_size;
};

struct qla4_8xxx_legacy_intr_set {
Expand Down Expand Up @@ -609,6 +610,8 @@ struct scsi_qla_host {
#define QLFLASH_READING 1
#define QLFLASH_WRITING 2
struct dma_pool *chap_dma_pool;
uint8_t *chap_list; /* CHAP table cache */
struct mutex chap_sem;
#define CHAP_DMA_BLOCK_SIZE 512
struct workqueue_struct *task_wq;
unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
Expand Down Expand Up @@ -671,6 +674,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha)
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
}

static inline int is_qla40XX(struct scsi_qla_host *ha)
{
return is_qla4032(ha) || is_qla4022(ha) || is_qla4010(ha);
}

static inline int is_qla8022(struct scsi_qla_host *ha)
{
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/scsi/qla4xxx/ql4_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ union external_hw_config_reg {
#define FA_BOOT_CODE_ADDR_82 0x20000
#define FA_RISC_CODE_ADDR_82 0x40000
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
#define FA_FLASH_ISCSI_CHAP 0x540000
#define FA_FLASH_CHAP_SIZE 0xC0000

/* Flash Description Table */
struct qla_fdt_layout {
Expand Down Expand Up @@ -310,6 +312,7 @@ struct qla_flt_header {
#define FLT_REG_GOLD_FW_82 0x75
#define FLT_REG_BOOT_CODE_82 0x78
#define FLT_REG_ISCSI_PARAM 0x65
#define FLT_REG_ISCSI_CHAP 0x63

struct qla_flt_region {
uint32_t code;
Expand Down Expand Up @@ -681,6 +684,8 @@ struct addr_ctrl_blk_def {

#define MAX_CHAP_ENTRIES_40XX 128
#define MAX_CHAP_ENTRIES_82XX 1024
#define MAX_RESRV_CHAP_IDX 3
#define FLASH_CHAP_OFFSET 0x06000000

struct ql4_chap_table {
uint16_t link;
Expand Down
141 changes: 107 additions & 34 deletions trunk/drivers/scsi/qla4xxx/ql4_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,7 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
{
int ret = 0;
int rval = QLA_ERROR;
uint32_t offset = 0;
uint32_t offset = 0, chap_size;
struct ql4_chap_table *chap_table;
dma_addr_t chap_dma;

Expand All @@ -1314,12 +1314,22 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
goto exit_get_chap;
}

memset(chap_table, 0, sizeof(struct ql4_chap_table));

offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
chap_size = sizeof(struct ql4_chap_table);
memset(chap_table, 0, chap_size);

if (is_qla40XX(ha))
offset = FLASH_CHAP_OFFSET | (idx * chap_size);
else {
offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
/* flt_chap_size is CHAP table size for both ports
* so divide it by 2 to calculate the offset for second port
*/
if (ha->port_num == 1)
offset += (ha->hw.flt_chap_size / 2);
offset += (idx * chap_size);
}

rval = qla4xxx_get_flash(ha, chap_dma, offset,
sizeof(struct ql4_chap_table));
rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
if (rval != QLA_SUCCESS) {
ret = -EINVAL;
goto exit_get_chap;
Expand Down Expand Up @@ -1366,10 +1376,16 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
rval = qla4xxx_set_flash(ha, chap_dma, offset,
sizeof(struct ql4_chap_table),
FLASH_OPT_RMW_COMMIT);

if (rval == QLA_SUCCESS && ha->chap_list) {
/* Update ha chap_list cache */
memcpy((struct ql4_chap_table *)ha->chap_list + idx,
chap_table, sizeof(struct ql4_chap_table));
}
dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
if (rval != QLA_SUCCESS)
ret = -EINVAL;
Expand All @@ -1378,6 +1394,83 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
return ret;
}

/**
* qla4xxx_get_chap_index - Get chap index given username and secret
* @ha: pointer to adapter structure
* @username: CHAP username to be searched
* @password: CHAP password to be searched
* @bidi: Is this a BIDI CHAP
* @chap_index: CHAP index to be returned
*
* Match the username and password in the chap_list, return the index if a
* match is found. If a match is not found then add the entry in FLASH and
* return the index at which entry is written in the FLASH.
**/
static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
char *password, int bidi, uint16_t *chap_index)
{
int i, rval;
int free_index = -1;
int found_index = 0;
int max_chap_entries = 0;
struct ql4_chap_table *chap_table;

if (is_qla8022(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
max_chap_entries = MAX_CHAP_ENTRIES_40XX;

if (!ha->chap_list) {
ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
return QLA_ERROR;
}

mutex_lock(&ha->chap_sem);
for (i = 0; i < max_chap_entries; i++) {
chap_table = (struct ql4_chap_table *)ha->chap_list + i;
if (chap_table->cookie !=
__constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
free_index = i;
continue;
}
if (bidi) {
if (chap_table->flags & BIT_7)
continue;
} else {
if (chap_table->flags & BIT_6)
continue;
}
if (!strncmp(chap_table->secret, password,
MAX_CHAP_SECRET_LEN) &&
!strncmp(chap_table->name, username,
MAX_CHAP_NAME_LEN)) {
*chap_index = i;
found_index = 1;
break;
}
}

/* If chap entry is not present and a free index is available then
* write the entry in flash
*/
if (!found_index && free_index != -1) {
rval = qla4xxx_set_chap(ha, username, password,
free_index, bidi);
if (!rval) {
*chap_index = free_index;
found_index = 1;
}
}

mutex_unlock(&ha->chap_sem);

if (found_index)
return QLA_SUCCESS;
return QLA_ERROR;
}

int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
uint16_t fw_ddb_index,
uint16_t connection_id,
Expand Down Expand Up @@ -1490,7 +1583,6 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
uint16_t iscsi_opts = 0;
uint32_t options = 0;
uint16_t idx;
int max_chap_entries = 0;

fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
&fw_ddb_entry_dma, GFP_KERNEL);
Expand Down Expand Up @@ -1559,26 +1651,14 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
goto exit_set_param;
}

if (is_qla8022(ha))
max_chap_entries = MAX_CHAP_ENTRIES_82XX;
else
max_chap_entries = MAX_CHAP_ENTRIES_40XX;
/* CHAP */
if (sess->username != NULL && sess->password != NULL) {
if (strlen(sess->username) && strlen(sess->password)) {
iscsi_opts |= BIT_7;
idx = ddb_entry->fw_ddb_index * 2;
if (idx > max_chap_entries) {
ql4_printk(KERN_ERR, ha,
"%s: Invalid ddb or chap index\n",
__func__);
rval = -EINVAL;
goto exit_set_param;
}

rval = qla4xxx_set_chap(ha, sess->username,
sess->password, idx,
LOCAL_CHAP);
rval = qla4xxx_get_chap_index(ha, sess->username,
sess->password,
LOCAL_CHAP, &idx);
if (rval)
goto exit_set_param;

Expand All @@ -1590,17 +1670,10 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
/* Check if BIDI CHAP */
if (strlen(sess->username_in) && strlen(sess->password_in)) {
iscsi_opts |= BIT_4;
idx = (ddb_entry->fw_ddb_index * 2) + 1;
if (idx > max_chap_entries) {
ql4_printk(KERN_ERR, ha,
"%s: Invalid ddb or bidi chap "
"index\n", __func__);
rval = -EINVAL;
goto exit_set_param;
}
rval = qla4xxx_set_chap(ha, sess->username_in,
sess->password_in, idx,
BIDI_CHAP);

rval = qla4xxx_get_chap_index(ha, sess->username_in,
sess->password_in,
BIDI_CHAP, &idx);
if (rval)
goto exit_set_param;
}
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/scsi/qla4xxx/ql4_nx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,10 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
case FLT_REG_ISCSI_PARAM:
hw->flt_iscsi_param = start;
break;
case FLT_REG_ISCSI_CHAP:
hw->flt_region_chap = start;
hw->flt_chap_size = le32_to_cpu(region->size);
break;
}
}
goto done;
Expand All @@ -2036,6 +2040,9 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_boot = FA_BOOT_CODE_ADDR_82;
hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
hw->flt_region_chap = FA_FLASH_ISCSI_CHAP;
hw->flt_chap_size = FA_FLASH_CHAP_SIZE;

done:
DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x "
"boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt,
Expand Down
67 changes: 67 additions & 0 deletions trunk/drivers/scsi/qla4xxx/ql4_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,10 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
if (ha->chap_dma_pool)
dma_pool_destroy(ha->chap_dma_pool);

if (ha->chap_list)
vfree(ha->chap_list);
ha->chap_list = NULL;

/* release io space registers */
if (is_qla8022(ha)) {
if (ha->nx_pcibase)
Expand Down Expand Up @@ -3058,6 +3062,66 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
return -ENOMEM;
}


/**
* qla4xxx_create chap_list - Create CHAP list from FLASH
* @ha: pointer to adapter structure
*
* Read flash and make a list of CHAP entries, during login when a CHAP entry
* is received, it will be checked in this list. If entry exist then the CHAP
* entry index is set in the DDB. If CHAP entry does not exist in this list
* then a new entry is added in FLASH in CHAP table and the index obtained is
* used in the DDB.
**/
static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
{
int rval = 0;
uint8_t *chap_flash_data = NULL;
uint32_t offset;
dma_addr_t chap_dma;
uint32_t chap_size = 0;

if (is_qla40XX(ha))
chap_size = MAX_CHAP_ENTRIES_40XX *
sizeof(struct ql4_chap_table);
else /* Single region contains CHAP info for both
* ports which is divided into half for each port.
*/
chap_size = ha->hw.flt_chap_size / 2;

chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,
&chap_dma, GFP_KERNEL);
if (!chap_flash_data) {
ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");
return;
}
if (is_qla40XX(ha))
offset = FLASH_CHAP_OFFSET;
else {
offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
if (ha->port_num == 1)
offset += chap_size;
}

rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
if (rval != QLA_SUCCESS)
goto exit_chap_list;

if (ha->chap_list == NULL)
ha->chap_list = vmalloc(chap_size);
if (ha->chap_list == NULL) {
ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");
goto exit_chap_list;
}

memcpy(ha->chap_list, chap_flash_data, chap_size);

exit_chap_list:
dma_free_coherent(&ha->pdev->dev, chap_size,
chap_flash_data, chap_dma);
return;
}

/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
Expand Down Expand Up @@ -3135,6 +3199,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
INIT_LIST_HEAD(&ha->free_srb_q);

mutex_init(&ha->mbox_sem);
mutex_init(&ha->chap_sem);
init_completion(&ha->mbx_intr_comp);
init_completion(&ha->disable_acb_comp);

Expand Down Expand Up @@ -3266,6 +3331,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
ha->patch_number, ha->build_number);

qla4xxx_create_chap_list(ha);

if (qla4xxx_setup_boot_info(ha))
ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
__func__);
Expand Down

0 comments on commit b3cfdb0

Please sign in to comment.