Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3606

kernel-2.6.18-194.11.1.el5.src.rpm

From: Marcus Barrow <mbarrow@redhat.com>
Date: Tue, 30 Sep 2008 15:12:33 -0400
Subject: [scsi] qla2xxx: use the NPIV table to instantiate port
Message-id: 20080930191233.22441.22512.sendpatchset@file.bos.redhat.com
O-Subject: [rhel 5.3 patch] qla2xxx - NPIV, store virtual ports for persistence
Bugzilla: 459015
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

BZ 459015 qla2xxx - NPIV, store virtual ports for persistence [3/3]

HP has a requirement to allow up to 32 Vports to be supplied via a boot code
mechanism and stored in FLASH on the adapter. The driver will read these
entries and instantiate these Vports during init time.

These patches are upstream.

qla2xxx: Add NPIV-Config Table support.

>From commit 0a941c5b9a9ea2a52736ab9e8d2319385c614a85

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index f5eb432..ac50c39 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -304,10 +304,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
 		valid = 0;
 		if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
 			valid = 1;
-		else if (start == (FA_BOOT_CODE_ADDR*4) ||
-		    start == (FA_RISC_CODE_ADDR*4))
+		else if (start == (ha->flt_region_boot * 4) ||
+		    start == (ha->flt_region_fw * 4))
 			valid = 1;
-		else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4))
+		else if (IS_QLA25XX(ha) &&
+		    start == (ha->flt_region_vpd_nvram * 4))
 		    valid = 1;
 		if (!valid) {
 			qla_printk(KERN_WARNING, ha,
@@ -1075,34 +1076,24 @@ qla2x00_total_isp_aborts_show(struct class_device *cdev, char *buf)
 	    ha->qla_stats.total_isp_aborts);
 }
 
-static ssize_t
-qla24xx_vport_create(struct class_device *cdev, const char *buf, size_t count)
+scsi_qla_host_t *
+qla24xx_vport_create(scsi_qla_host_t *ha, uint64_t fc_wwpn, uint64_t fc_wwnn)
 {
 	int	ret = 0;
-	int	cnt = count;
-	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
 	scsi_qla_host_t *vha;
 
-	/* count may include a LF at end of string */
-	if (buf[cnt-1] == '\n')
-		cnt--;
-
-	/* validate we have enough characters for WWPN */
-	if ((cnt != (16+1+16)) || (buf[16] != ':'))
-		return -EINVAL;
-
-	ret = qla24xx_vport_create_req_sanity_check(ha, buf);
+	ret = qla24xx_vport_create_req_sanity_check(ha, fc_wwpn, fc_wwnn);
 	if (ret) {
 		DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
 		    "status %x\n", ret));
-		return (ret);
+		return NULL;
 	}
 
-	vha = qla24xx_create_vhost(ha, buf);
+	vha = qla24xx_create_vhost(ha, fc_wwpn, fc_wwnn);
 	if (vha == NULL) {
 		DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
 		    vha));
-		return -EINVAL;
+		return NULL;
 	}
 
 	atomic_set(&vha->vp_state, VP_FAILED);
@@ -1139,7 +1130,7 @@ qla24xx_vport_create(struct class_device *cdev, const char *buf, size_t count)
 
 	qla24xx_enable_vp(vha);
 
-	return count;
+	return vha;
 vport_create_failed_2:
 
 	qla24xx_disable_vp(vha);
@@ -1147,7 +1138,33 @@ vport_create_failed_2:
 	kfree(vha->port_name);
 	kfree(vha->node_name);
 	scsi_host_put(vha->host);
-	return -EINVAL;
+	return NULL;
+}
+
+static ssize_t
+qla24xx_vport_create_cdev(struct class_device *cdev, const char *buf,
+    size_t count)
+{
+	int	cnt = count;
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	uint64_t fc_wwpn;
+	uint64_t fc_wwnn;
+
+	/* count may include a LF at end of string */
+	if (buf[cnt-1] == '\n')
+		cnt--;
+
+	/* validate we have enough characters for WWPN */
+	if ((cnt != (16+1+16)) || (buf[16] != ':'))
+		return -EINVAL;
+
+	if (fc_parse_wwn(&buf[0], &fc_wwpn))
+		return -EINVAL;
+
+	if (fc_parse_wwn(&buf[17], &fc_wwnn))
+		return -EINVAL;
+
+	return qla24xx_vport_create(ha, fc_wwpn, fc_wwnn) ? count: -EINVAL;
 }
 
 static ssize_t
@@ -1436,7 +1453,7 @@ static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO,
     qla2x00_optrom_fw_version_show, NULL);
 static CLASS_DEVICE_ATTR(total_isp_aborts, S_IRUGO,
     qla2x00_total_isp_aborts_show, NULL);
-static CLASS_DEVICE_ATTR(vport_create, S_IWUGO, NULL, qla24xx_vport_create);
+static CLASS_DEVICE_ATTR(vport_create, S_IWUGO, NULL, qla24xx_vport_create_cdev);
 static CLASS_DEVICE_ATTR(vport_delete, S_IWUGO, NULL, qla24xx_vport_delete);
 static CLASS_DEVICE_ATTR(max_npiv_vports, S_IRUGO,
 	qla24xx_max_npiv_vports_show, NULL);
@@ -1811,6 +1828,8 @@ struct fc_function_template qla2xxx_transport_functions = {
 	.terminate_rport_io = qla2x00_terminate_rport_io,
 	.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
 	.terminate_rport_io = qla2x00_terminate_rport_io,
+	.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
+	.terminate_rport_io = qla2x00_terminate_rport_io,
 	.get_fc_host_stats = qla2x00_get_fc_host_stats,
 };
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index c455a00..391fda3 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2312,6 +2312,7 @@ typedef struct scsi_qla_host {
 #define REGISTER_FDMI_NEEDED	26
 #define FCPORT_UPDATE_NEEDED	27
 #define VP_DPC_NEEDED		28	/* wake up for VP dpc handling */
+#define NPIV_CONFIG_NEEDED	29
 
 	uint32_t	device_flags;
 #define DFLG_LOCAL_DEVICES		BIT_0
@@ -2615,6 +2616,14 @@ typedef struct scsi_qla_host {
 	uint32_t	fdt_unprotect_sec_cmd;
 	uint32_t	fdt_protect_sec_cmd;
 
+	uint32_t	flt_region_flt;
+	uint32_t	flt_region_fdt;
+	uint32_t	flt_region_boot;
+	uint32_t	flt_region_fw;
+	uint32_t	flt_region_vpd_nvram;
+	uint32_t	flt_region_hw_event;
+	uint32_t	flt_region_npiv_conf;
+
 	/* Needed for BEACON */
 	uint16_t	beacon_blink_led;
 	uint8_t		beacon_color_state;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 4f2f83f..1f29ffb 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -789,14 +789,20 @@ struct device_reg_24xx {
 #define FA_RISC_CODE_ADDR	0x20000
 #define FA_RISC_CODE_SEGMENTS	2
 
+#define FA_FLASH_DESCR_ADDR_24	0x11000
+#define FA_FLASH_LAYOUT_ADDR_24	0x11400
+#define FA_NPIV_CONF0_ADDR_24	0x16000
+#define FA_NPIV_CONF1_ADDR_24	0x17000
+
 #define FA_FW_AREA_ADDR		0x40000
 #define FA_VPD_NVRAM_ADDR	0x48000
 #define FA_FEATURE_ADDR		0x4C000
 #define FA_FLASH_DESCR_ADDR	0x50000
-#define FA_HW_EVENT_ADDR	0x54000
-#define FA_BOOT_LOG_ADDR	0x58000
-#define FA_FW_DUMP0_ADDR	0x60000
-#define FA_FW_DUMP1_ADDR	0x70000
+#define FA_FLASH_LAYOUT_ADDR	0x50400
+#define FA_HW_EVENT0_ADDR	0x54000
+#define FA_HW_EVENT1_ADDR	0x54400
+#define FA_NPIV_CONF0_ADDR	0x5C000
+#define FA_NPIV_CONF1_ADDR	0x5D000
 
 	uint32_t flash_data;		/* Flash/NVRAM BIOS data. */
 
@@ -1194,6 +1200,43 @@ struct qla_fdt_layout {
 	uint8_t unused2[65];
 };
 
+/* Flash Layout Table ********************************************************/
+
+struct qla_flt_location {
+	uint8_t sig[4];
+	uint32_t start_lo;
+	uint32_t start_hi;
+	uint16_t unused;
+	uint16_t checksum;
+};
+
+struct qla_flt_header {
+	uint16_t version;
+	uint16_t length;
+	uint16_t checksum;
+	uint16_t unused;
+};
+
+#define FLT_REG_FW	0x01
+#define FLT_REG_BOOT_CODE	0x07
+#define FLT_REG_VPD_0	0x14
+#define FLT_REG_NVRAM_0	0x15
+#define FLT_REG_VPD_1	0x16
+#define FLT_REG_NVRAM_1	0x07
+#define FLT_REG_FDT	0x1a
+#define FLT_REG_FLT	0x1c
+#define FLT_REG_HW_EVENT_0	0x1d
+#define FLT_REG_HW_EVENT_1	0x1f
+#define FLT_REG_NPIV_CONF_0	0x29
+#define FLT_REG_NPIV_CONF_1	0x2a
+
+struct qla_flt_region {
+	uint32_t code;
+	uint32_t size;
+	uint32_t start;
+	uint32_t end;
+};
+
 /* 84XX Support ****************************************************/
 
 #define MBA_ISP84XX_ALERT       0x800f  /* Alert Notification. */
@@ -1318,4 +1361,23 @@ struct access_chip_rsp_84xx {
 };
 /* End of 84XX Support ************************************************/
 
+/* Flash NPIV Configuration Table ********************************************/
+
+struct qla_npiv_header {
+	uint8_t sig[2];
+	uint16_t version;
+	uint16_t entries;
+	uint16_t unused[4];
+	uint16_t checksum;
+};
+
+struct qla_npiv_entry {
+	uint16_t flags;
+	uint16_t vf_id;
+	uint16_t qos;
+	uint16_t unused1;
+	uint8_t port_name[WWN_SIZE];
+	uint8_t node_name[WWN_SIZE];
+};
+
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0c284b3..82764a8 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -92,9 +92,10 @@ extern void qla24xx_report_id_acquisition(scsi_qla_host_t *,
 extern scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *,
 	uint8_t *);
 extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
-extern int qla24xx_vport_create_req_sanity_check(scsi_qla_host_t *,
-	const char *);
-extern scsi_qla_host_t * qla24xx_create_vhost(scsi_qla_host_t *, const char *);
+extern int qla24xx_vport_create_req_sanity_check(scsi_qla_host_t *, uint64_t,
+    uint64_t);
+extern scsi_qla_host_t *qla24xx_create_vhost(scsi_qla_host_t *, uint64_t,
+    uint64_t);
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -283,7 +284,6 @@ extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
     uint32_t);
 extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
     uint32_t);
-extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
 extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
     uint32_t);
 extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
@@ -312,6 +312,10 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
 extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
 extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
 
+extern int qla2xxx_get_flash_info(scsi_qla_host_t *);
+
+extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_dbg.c source file.
  */
@@ -355,11 +359,11 @@ extern struct class_device_attribute *qla24xx_host_attrs[];
 extern struct class_device_attribute *qla24xx_host_vport_attrs[];
 struct fc_function_template;
 extern struct fc_function_template qla2xxx_transport_functions;
-extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
-extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
 extern void qla2x00_init_host_attr(scsi_qla_host_t *);
 extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
 extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
+extern scsi_qla_host_t *qla24xx_vport_create(scsi_qla_host_t *, uint64_t,
+    uint64_t);
 
 /*
  * Global functions in qla_nlk.c
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 0eee017..290deca 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -383,19 +383,12 @@ fc_convert_hex_char(uint8_t *nm, char *ns, int count)
 }
 
 int
-qla24xx_vport_create_req_sanity_check(scsi_qla_host_t *ha, const char *buf)
+qla24xx_vport_create_req_sanity_check(scsi_qla_host_t *ha, uint64_t fc_wwpn,
+    uint64_t fc_wwnn)
 {
 	scsi_qla_host_t *vha;
-	uint64_t	fc_wwpn;
-	uint64_t	fc_wwnn;
 	uint8_t		port_name[WWN_SIZE];
 
-	if (fc_parse_wwn(&buf[0], &fc_wwpn))
-		return -EINVAL;
-
-	if (fc_parse_wwn(&buf[17], &fc_wwnn))
-		return -EINVAL;
-
 	/* Check up whether npiv supported switch presented */
 	if (!(ha->switch_cap & FLOGI_MID_SUPPORT))
 		return -EINVAL;
@@ -421,12 +414,10 @@ qla24xx_vport_create_req_sanity_check(scsi_qla_host_t *ha, const char *buf)
 }
 
 scsi_qla_host_t *
-qla24xx_create_vhost(scsi_qla_host_t *ha, const char *buf)
+qla24xx_create_vhost(scsi_qla_host_t *ha, uint64_t fc_wwpn, uint64_t fc_wwnn)
 {
 	scsi_qla_host_t *vha;
 	struct Scsi_Host *host;
-	uint64_t	fc_wwpn;
-	uint64_t	fc_wwnn;
 
 	host = scsi_host_alloc(&qla24xx_driver_vport_template,
 	    sizeof(scsi_qla_host_t));
@@ -449,12 +440,6 @@ qla24xx_create_vhost(scsi_qla_host_t *ha, const char *buf)
 	if (!vha->port_name)
 		goto create_vhost_failed_2;
 
-	if (fc_parse_wwn(&buf[0], &fc_wwpn))
-		return NULL;
-
-	if (fc_parse_wwn(&buf[17], &fc_wwnn))
-		return NULL;
-
 	/* New host info */
 	u64_to_wwn(fc_wwpn, vha->port_name);
 	u64_to_wwn(fc_wwnn, vha->node_name);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index fbc3a55..45c7b3a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1867,6 +1867,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	    ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
 	    ha->isp_ops->fw_version_str(ha, fw_str));
 
+	set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags);
+
 	return 0;
 
 probe_failed:
@@ -2653,6 +2655,12 @@ qla2x00_do_dpc(void *data)
 			    ha->host_no));
 		}
 
+		if (test_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags) &&
+		    atomic_read(&ha->loop_state) == LOOP_READY) {
+			clear_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags);
+			qla2xxx_flash_npiv_conf(ha);
+		}
+
 		if (!ha->interrupts_on)
 			ha->isp_ops->enable_intrs(ha);
 
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 220c5c1..11c06b6 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -686,6 +686,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr)
 			if (PCI_FUNC(ha->pdev->devfn))
 				ha->flt_region_hw_event = start;
 			break;
+		case FLT_REG_NPIV_CONF_0:
+			if (!PCI_FUNC(ha->pdev->devfn))
+				ha->flt_region_npiv_conf = start;
+			break;
+		case FLT_REG_NPIV_CONF_1:
+			if (PCI_FUNC(ha->pdev->devfn))
+				ha->flt_region_npiv_conf = start;
+			break;
 		}
 	}
 	goto done;
@@ -700,11 +708,15 @@ no_flash_data:
 	    FA_FLASH_DESCR_ADDR;
 	ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ?
 	    FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR;
+	ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ?
+	    (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR):
+	    (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR);
 done:
 	DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
-	    "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x.\n", loc,
+	    "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc,
 	    ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram,
-	    ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event));
+	    ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event,
+	    ha->flt_region_npiv_conf));
 }
 
 static void
@@ -815,6 +827,75 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha)
 	return QLA_SUCCESS;
 }
 
+void
+qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha)
+{
+#define NPIV_CONFIG_SIZE	(16*1024)
+	void *data;
+	uint16_t *wptr;
+	uint16_t cnt, chksum;
+	struct qla_npiv_header hdr;
+	struct qla_npiv_entry *entry;
+
+	ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr,
+	    ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header));
+	if (hdr.version == __constant_cpu_to_le16(0xffff))
+		return;
+	if (hdr.version != __constant_cpu_to_le16(1)) {
+		DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config "
+		    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
+		    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
+		    le16_to_cpu(hdr.checksum)));
+		return;
+	}
+
+	data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL);
+	if (!data) {
+		DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to "
+		    "allocate memory.\n"));
+		return;
+	}
+
+	ha->isp_ops->read_optrom(ha, (uint8_t *)data,
+	    ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE);
+
+	cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) *
+	    sizeof(struct qla_npiv_entry)) >> 1;
+	for (wptr = data, chksum = 0; cnt; cnt--)
+		chksum += le16_to_cpu(*wptr++);
+	if (chksum) {
+		DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config "
+		    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
+		    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
+		    chksum));
+		goto done;
+	}
+
+	entry = data + sizeof(struct qla_npiv_header);
+	cnt = le16_to_cpu(hdr.entries);
+	for ( ; cnt; cnt--, entry++) {
+		uint16_t flags;
+		uint64_t wwpn, wwnn;
+
+		flags = le16_to_cpu(entry->flags);
+		if (flags == 0xffff)
+			continue;
+		if ((flags & BIT_0) == 0)
+			continue;
+
+		wwpn = wwn_to_u64(entry->port_name);
+		wwnn = wwn_to_u64(entry->node_name);
+
+		DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx "
+		    "wwnn=%llx vf_id=0x%x qos=0x%x.\n", cnt, wwpn, wwnn,
+		    le16_to_cpu(entry->vf_id), le16_to_cpu(entry->qos)));
+
+		qla24xx_vport_create(ha, wwpn, wwnn);
+	}
+done:
+	kfree(data);
+}
+
 static int
 qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
     uint32_t dwords)