summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_os.c
diff options
context:
space:
mode:
authorLalit Chandivade <lalit.chandivade@qlogic.com>2011-10-07 16:55:42 -0700
committerJames Bottomley <JBottomley@Parallels.com>2011-10-16 11:08:41 -0500
commit4549415af6915017f5d3fbdbfd5edd1dfbe63fa9 (patch)
treeb06ad5224dd3093d6fd9377d8461a295f101e1b7 /drivers/scsi/qla4xxx/ql4_os.c
parent0854f665a1cbb4566d3ebe449169b0200b8cdad0 (diff)
downloadtalos-obmc-linux-4549415af6915017f5d3fbdbfd5edd1dfbe63fa9.tar.gz
talos-obmc-linux-4549415af6915017f5d3fbdbfd5edd1dfbe63fa9.zip
[SCSI] qla4xxx: Do not add duplicate CHAP entry in FLASH
QLogic applications store the CHAP information in FLASH. During login, authentication information is provided using an index into the CHAP region. In order to support QLogic applications along with iscsiadm, updated the LLD to not add duplicate CHAP entries in the CHAP region and preserve the existing CHAP info in the CHAP region in FLASH. This allows QLogic applications to pre-write the CHAP entries in the CHAP region. With iscsiadm, when the CHAP authentication information is sent to the LLD, the LLD searches for the entry in CHAP region in FLASH, if exists then do not add. If CHAP entry does not exist then add the CHAP entry in the CHAP region. JIRA Key: UPSISCSI-146 Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ce391d5511e3..874621db4a98 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -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)
@@ -3058,6 +3062,66 @@ kset_free:
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
@@ -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);
@@ -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__);
OpenPOWER on IntegriCloud