All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration
@ 2011-04-22 18:07 vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 1/5] iscsi_transport: add support for set_net_config vikas.chaudhary
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

These patches are to configure network setting for iSCSI Adapter (qla4xxx)
that use private IP address. Patches are made on top of scsi-misc-2.6
git tree.

This patchset is revision of our RFC-v2 patchset which we posted earlier:
link: http://marc.info/?l=linux-scsi&m=130176955503554&w=2

Patches include following major changes from RFC-v2 patches.

- Cleanup white space errors.
- rename sysfs attr file from state to enabled as suggested by Mike Christie

Kernel Patches:
Lalit Chandivade (2):
      iscsi_transport: add support for set_net_config
      qla4xxx: add support for set_net_config

Vikas Chaudhary (3):
      qla4xxx: Added new "struct ipaddress_config"
      iscsi_transport: show network configuration in sysfs
      qla4xxx: added support to show multiple iface in sysfs

iscsiadm patch:
Lalit Chandivade (1):
      iscsiadm: Add netconfig support in iscsiadm and iscsid

Thanks,
Vikas.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] iscsi_transport: add support for set_net_config
  2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
@ 2011-04-22 18:07 ` vikas.chaudhary
  2011-04-23  5:19   ` Mike Christie
  2011-04-22 18:07 ` [PATCH 2/5] qla4xxx: " vikas.chaudhary
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Harish Zunjarrao

From: Lalit Chandivade <lalit.chandivade@qlogic.com>

Allows user space (iscsiadm) to send down network configuration parameters
for LLD to set private network configuration on the iSCSI adapters.

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Ravi Anand <ravi.anand@qlogic.com>
---
 drivers/scsi/scsi_transport_iscsi.c |   27 ++++++++++++++++
 include/scsi/iscsi_if.h             |   58 +++++++++++++++++++++++++++++++++++
 include/scsi/scsi_transport_iscsi.h |    1 +
 3 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3fd16d7..7596234 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1558,6 +1558,30 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 }
 
 static int
+iscsi_set_net_config(struct iscsi_transport *transport,
+		     struct iscsi_uevent *ev)
+{
+	char *data = (char *)ev + sizeof(*ev);
+	struct Scsi_Host *shost;
+	int err;
+
+	if (!transport->set_net_config)
+		return -ENOSYS;
+
+	shost = scsi_host_lookup(ev->u.set_net_config.host_no);
+	if (!shost) {
+		printk(KERN_ERR "set_net_config could not find host no %u\n",
+		       ev->u.set_net_config.host_no);
+		return -ENODEV;
+	}
+
+	err = transport->set_net_config(shost, data,
+					ev->u.set_net_config.count);
+	scsi_host_put(shost);
+	return err;
+}
+
+static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 {
 	int err = 0;
@@ -1696,6 +1720,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 	case ISCSI_UEVENT_PATH_UPDATE:
 		err = iscsi_set_path(transport, ev);
 		break;
+	case ISCSI_UEVENT_SET_NET_CONFIG:
+		err = iscsi_set_net_config(transport, ev);
+		break;
 	default:
 		err = -ENOSYS;
 		break;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index ddb0456..449e55b 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
 	ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST	= UEVENT_BASE + 19,
 
 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
+	ISCSI_UEVENT_SET_NET_CONFIG	= UEVENT_BASE + 21,
 
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
@@ -172,6 +173,10 @@ struct iscsi_uevent {
 		struct msg_set_path {
 			uint32_t	host_no;
 		} set_path;
+		struct msg_set_net_config {
+			uint32_t	host_no;
+			uint32_t	count;
+		} set_net_config;
 	} u;
 	union {
 		/* messages k -> u */
@@ -237,6 +242,59 @@ struct iscsi_path {
 	uint16_t	pmtu;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
+#define ISCSI_FALSE	0
+#define ISCSI_TRUE	1
+
+/* ipv4 bootproto */
+#define ISCSI_BOOTPROTO_STATIC		0x01
+#define ISCSI_BOOTPROTO_DHCP		0x02
+
+/* ipv6 addr autoconfig type */
+#define ISCSI_IPV6_AUTOCFG_DISABLE		0x01
+#define ISCSI_IPV6_AUTOCFG_ND_ENABLE		0x02
+#define ISCSI_IPV6_AUTOCFG_DHCPV6_ENABLE	0x03
+
+/* ipv6 link local addr type */
+#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE	0x01
+#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE	0x02
+
+/* ipv6 router addr type */
+#define ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE	0x01
+#define ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE	0x02
+
+/* iSCSI network params */
+enum iscsi_net_param_type {
+	ISCSI_NET_PARAM_IPV4_ADDR		= 1,
+	ISCSI_NET_PARAM_IPV4_SUBNET		= 2,
+	ISCSI_NET_PARAM_IPV4_GW			= 3,
+	ISCSI_NET_PARAM_IPV4_BOOTPROTO		= 4,
+	ISCSI_NET_PARAM_MAC			= 5,
+	ISCSI_NET_PARAM_IPV6_LINKLOCAL		= 6,
+	ISCSI_NET_PARAM_IPV6_ADDR		= 7,
+	ISCSI_NET_PARAM_IPV6_ROUTER		= 8,
+	ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG	= 9,
+	ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG	= 10,
+	ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG	= 11,
+	ISCSI_NET_PARAM_IFACE_ENABLED		= 12,
+	ISCSI_NET_PARAM_VLAN			= 13,
+};
+
+/* 20 param per iface * 10 iface per port = 200 params */
+#define ISCSI_MAX_IFACE_PER_HW		10
+#define ISCSI_MAX_PARAM_PER_IFACE	20
+#define ISCSI_MAX_NET_PARAMS (ISCSI_MAX_IFACE_PER_HW * \
+			      ISCSI_MAX_PARAM_PER_IFACE)
+
+#define IFACE_TYPE_IPV4		0x01
+#define IFACE_TYPE_IPV6		0x02
+struct iscsi_net_param {
+	uint32_t param_type;	/* enum iscsi_net_param */
+	uint32_t iface_type;	/* IPv4 or IPv6 */
+	uint32_t iface_num;	/* iface number, 0 - n */
+	uint32_t length;	/* Actual length of the param */
+	uint8_t value[0];	/* length sized value follows */
+} __packed;
+
 /*
  * Common error codes
  */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index bf8f529..45b9df9 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -137,6 +137,7 @@ struct iscsi_transport {
 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
 			  uint32_t enable, struct sockaddr *dst_addr);
 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+	int (*set_net_config) (struct Scsi_Host *shost, char *data, int count);
 };
 
 /*
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] qla4xxx: add support for set_net_config
  2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 1/5] iscsi_transport: add support for set_net_config vikas.chaudhary
@ 2011-04-22 18:07 ` vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 3/5] qla4xxx: Added new "struct ipaddress_config" vikas.chaudhary
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Harish Zunjarrao

From: Lalit Chandivade <lalit.chandivade@qlogic.com>

Allows user space (iscsiadm) to send down network configuration parameters
for LLD to set private network configuration on the iSCSI adapters.

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Ravi Anand <ravi.anand@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_fw.h   |   77 ++++++++++
 drivers/scsi/qla4xxx/ql4_glbl.h |   20 +++-
 drivers/scsi/qla4xxx/ql4_mbx.c  |  119 +++++++++++++++-
 drivers/scsi/qla4xxx/ql4_os.c   |  302 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 514 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 31e2bf9..d05e8be 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -434,6 +434,14 @@ struct qla_flt_region {
 #define ACB_STATE_VALID		0x05
 #define ACB_STATE_DISABLING	0x06
 
+/* FLASH offsets */
+#define FLASH_SEGMENT_IFCB	0x04000000
+
+#define FLASH_OPT_RMW_HOLD	0
+#define FLASH_OPT_RMW_INIT	1
+#define FLASH_OPT_COMMIT	2
+#define FLASH_OPT_RMW_COMMIT	3
+
 /*************************************************************************/
 
 /* Host Adapter Initialization Control Block (from host) */
@@ -473,6 +481,7 @@ struct addr_ctrl_blk {
 
 	uint16_t iscsi_opts;	/* 30-31 */
 	uint16_t ipv4_tcp_opts;	/* 32-33 */
+#define TCPOPT_DHCP_ENABLE		0x0200
 	uint16_t ipv4_ip_opts;	/* 34-35 */
 #define  IPOPT_IPv4_PROTOCOL_ENABLE	0x8000
 
@@ -574,6 +583,74 @@ struct init_fw_ctrl_blk {
 /*	struct addr_ctrl_blk sec;*/
 };
 
+struct addr_ctrl_blk_def {
+	uint8_t reserved1[1];	/* 00 */
+	uint8_t control;	/* 01 */
+	uint8_t reserved2[11];	/* 02-0C */
+	uint8_t inst_num;	/* 0D */
+	uint8_t reserved3[34];	/* 0E-2F */
+	uint16_t iscsi_opts;	/* 30-31 */
+	uint16_t ipv4_tcp_opts;	/* 32-33 */
+	uint16_t ipv4_ip_opts;	/* 34-35 */
+	uint16_t iscsi_max_pdu_size;	/* 36-37 */
+	uint8_t ipv4_tos;	/* 38 */
+	uint8_t ipv4_ttl;	/* 39 */
+	uint8_t reserved4[2];	/* 3A-3B */
+	uint16_t def_timeout;	/* 3C-3D */
+	uint16_t iscsi_fburst_len;	/* 3E-3F */
+	uint8_t reserved5[4];	/* 40-43 */
+	uint16_t iscsi_max_outstnd_r2t;	/* 44-45 */
+	uint8_t reserved6[2];	/* 46-47 */
+	uint16_t ipv4_port;	/* 48-49 */
+	uint16_t iscsi_max_burst_len;	/* 4A-4B */
+	uint8_t reserved7[4];	/* 4C-4F */
+	uint8_t ipv4_addr[4];	/* 50-53 */
+	uint16_t ipv4_vlan_tag;	/* 54-55 */
+	uint8_t ipv4_addr_state;	/* 56 */
+	uint8_t ipv4_cacheid;	/* 57 */
+	uint8_t reserved8[8];	/* 58-5F */
+	uint8_t ipv4_subnet[4];	/* 60-63 */
+	uint8_t reserved9[12];	/* 64-6F */
+	uint8_t ipv4_gw_addr[4];	/* 70-73 */
+	uint8_t reserved10[84];	/* 74-C7 */
+	uint8_t abort_timer;	/* C8    */
+	uint8_t ipv4_tcp_wsf;	/* C9    */
+	uint8_t reserved11[10];	/* CA-D3 */
+	uint8_t ipv4_dhcp_vid_len;	/* D4 */
+	uint8_t ipv4_dhcp_vid[11];	/* D5-DF */
+	uint8_t reserved12[20];	/* E0-F3 */
+	uint8_t ipv4_dhcp_alt_cid_len;	/* F4 */
+	uint8_t ipv4_dhcp_alt_cid[11];	/* F5-FF */
+	uint8_t iscsi_name[224];	/* 100-1DF */
+	uint8_t reserved13[32];	/* 1E0-1FF */
+	uint32_t cookie;	/* 200-203 */
+	uint16_t ipv6_port;	/* 204-205 */
+	uint16_t ipv6_opts;	/* 206-207 */
+	uint16_t ipv6_addtl_opts;	/* 208-209 */
+	uint16_t ipv6_tcp_opts;		/* 20A-20B */
+	uint8_t ipv6_tcp_wsf;		/* 20C */
+	uint16_t ipv6_flow_lbl;		/* 20D-20F */
+	uint8_t ipv6_dflt_rtr_addr[16];	/* 210-21F */
+	uint16_t ipv6_vlan_tag;		/* 220-221 */
+	uint8_t ipv6_lnk_lcl_addr_state;	/* 222 */
+	uint8_t ipv6_addr0_state;	/* 223 */
+	uint8_t ipv6_addr1_state;	/* 224 */
+	uint8_t ipv6_dflt_rtr_state;	/* 225 */
+	uint8_t ipv6_traffic_class;	/* 226 */
+	uint8_t ipv6_hop_limit;		/* 227 */
+	uint8_t ipv6_if_id[8];		/* 228-22F */
+	uint8_t ipv6_addr0[16];		/* 230-23F */
+	uint8_t ipv6_addr1[16];		/* 240-24F */
+	uint32_t ipv6_nd_reach_time;	/* 250-253 */
+	uint32_t ipv6_nd_rexmit_timer;	/* 254-257 */
+	uint32_t ipv6_nd_stale_timeout;	/* 258-25B */
+	uint8_t ipv6_dup_addr_detect_count;	/* 25C */
+	uint8_t ipv6_cache_id;		/* 25D */
+	uint8_t reserved14[18];		/* 25E-26F */
+	uint32_t ipv6_gw_advrt_mtu;	/* 270-273 */
+	uint8_t reserved15[140];	/* 274-2FF */
+};
+
 /*************************************************************************/
 
 struct dev_db_entry {
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index cc53e3f..9c5c5e3 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -52,7 +52,17 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
 
 int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
 			  dma_addr_t fw_ddb_entry_dma);
-
+uint8_t qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+			 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+				   uint16_t fw_ddb_index,
+				   uint16_t connection_id,
+				   uint16_t option);
+int qla4xxx_disable_acb(struct scsi_qla_host *ha);
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+		    uint32_t *mbox_sts, dma_addr_t acb_dma);
+int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+		    uint32_t *mbox_sts, dma_addr_t acb_dma);
 void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
 				 struct ddb_entry *ddb_entry);
 u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
@@ -75,7 +85,8 @@ void qla4xxx_dump_buffer(void *b, uint32_t size);
 int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
 	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
 int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);
-
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+		      uint32_t offset, uint32_t length, uint32_t options);
 int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
 		uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
 
@@ -95,6 +106,11 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha);
 void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha);
 void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha);
 void qla4xxx_dump_registers(struct scsi_qla_host *ha);
+uint8_t qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
+				  uint32_t *mbox_cmd,
+				  uint32_t *mbox_sts,
+				  struct addr_ctrl_blk *init_fw_cb,
+				  dma_addr_t init_fw_cb_dma);
 
 void qla4_8xxx_pci_config(struct scsi_qla_host *);
 int qla4_8xxx_iospace_config(struct scsi_qla_host *ha);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index f9d81c8..743290e 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -317,7 +317,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
 	return QLA_SUCCESS;
 }
 
-static uint8_t
+uint8_t
 qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
 {
@@ -377,7 +377,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha,
 	}
 }
 
-static uint8_t
+uint8_t
 qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
 			  uint32_t *mbox_cmd,
 			  uint32_t *mbox_sts,
@@ -1194,3 +1194,118 @@ exit_send_tgts_no_free:
 	return ret_val;
 }
 
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+		      uint32_t offset, uint32_t length, uint32_t options)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status = QLA_SUCCESS;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
+	mbox_cmd[1] = LSDW(dma_addr);
+	mbox_cmd[2] = MSDW(dma_addr);
+	mbox_cmd[3] = offset;
+	mbox_cmd[4] = length;
+	mbox_cmd[5] = options;
+
+	status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
+				  "failed w/ status %04X, mbx1 %04X\n",
+				  __func__, mbox_sts[0], mbox_sts[1]));
+	}
+	return status;
+}
+
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+				   uint16_t fw_ddb_index,
+				   uint16_t connection_id,
+				   uint16_t option)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status = QLA_SUCCESS;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+	mbox_cmd[1] = fw_ddb_index;
+	mbox_cmd[2] = connection_id;
+	mbox_cmd[3] = option;
+
+	status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
+				  "option %04x failed w/ status %04X %04X\n",
+				  __func__, option, mbox_sts[0], mbox_sts[1]));
+	}
+	return status;
+}
+
+int qla4xxx_disable_acb(struct scsi_qla_host *ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status = QLA_SUCCESS;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
+
+	status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
+				  "failed w/ status %04X %04X %04X", __func__,
+				  mbox_sts[0], mbox_sts[1], mbox_sts[2]));
+	}
+	return status;
+}
+
+int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+		    uint32_t *mbox_sts, dma_addr_t acb_dma)
+{
+	int status = QLA_SUCCESS;
+
+	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+	mbox_cmd[0] = MBOX_CMD_GET_ACB;
+	mbox_cmd[1] = 0; /* Primary ACB */
+	mbox_cmd[2] = LSDW(acb_dma);
+	mbox_cmd[3] = MSDW(acb_dma);
+	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
+
+	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
+				  "failed w/ status %04X\n", __func__,
+				  mbox_sts[0]));
+	}
+	return status;
+}
+
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+		    uint32_t *mbox_sts, dma_addr_t acb_dma)
+{
+	int status = QLA_SUCCESS;
+
+	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+	mbox_cmd[0] = MBOX_CMD_SET_ACB;
+	mbox_cmd[1] = 0; /* Primary ACB */
+	mbox_cmd[2] = LSDW(acb_dma);
+	mbox_cmd[3] = MSDW(acb_dma);
+	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
+
+	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: MBOX_CMD_SET_ACB "
+				  "failed w/ status %04X\n", __func__,
+				  mbox_sts[0]));
+	}
+	return status;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 230ba09..e9b669d 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -80,6 +80,8 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
 				  enum iscsi_param param, char *buf);
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
 				  enum iscsi_host_param param, char *buf);
+static int qla4xxx_set_net_config(struct Scsi_Host *shost, char *data,
+				  int count);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
 static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
 
@@ -141,6 +143,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
 	.get_conn_param		= qla4xxx_conn_get_param,
 	.get_session_param	= qla4xxx_sess_get_param,
 	.get_host_param		= qla4xxx_host_get_param,
+	.set_net_config		= qla4xxx_set_net_config,
 	.session_recovery_timedout = qla4xxx_recovery_timedout,
 };
 
@@ -201,6 +204,305 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
 	return len;
 }
 
+static inline void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
+				    struct iscsi_net_param *net_param,
+				    struct addr_ctrl_blk *init_fw_cb)
+{
+	/*
+	 * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
+	 * iface_num 1 is valid only for IPv6 Addr.
+	 */
+	switch (net_param->param_type) {
+	case ISCSI_NET_PARAM_IPV6_ADDR:
+		if (net_param->iface_num & 0x1)
+			/* IPv6 Addr 1 */
+			memcpy(init_fw_cb->ipv6_addr1, net_param->value,
+			       sizeof(init_fw_cb->ipv6_addr1));
+		else
+			/* IPv6 Addr 0 */
+			memcpy(init_fw_cb->ipv6_addr0, net_param->value,
+			       sizeof(init_fw_cb->ipv6_addr0));
+		break;
+	case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+		if (net_param->iface_num & 0x1)
+			break;
+		memcpy(init_fw_cb->ipv6_if_id, &net_param->value[8],
+		       sizeof(init_fw_cb->ipv6_if_id));
+		break;
+	case ISCSI_NET_PARAM_IPV6_ROUTER:
+		if (net_param->iface_num & 0x1)
+			break;
+		memcpy(init_fw_cb->ipv6_dflt_rtr_addr, net_param->value,
+		       sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+		break;
+	case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+		/* Autocfg applies to even interface */
+		if (net_param->iface_num & 0x1)
+			break;
+
+		if (net_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
+			init_fw_cb->ipv6_addtl_opts &=
+				cpu_to_le16(
+				  ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+		else if (net_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
+			init_fw_cb->ipv6_addtl_opts |=
+				cpu_to_le16(
+				  IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+		else
+			ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+				   "IPv6 addr\n");
+		break;
+	case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+		/* Autocfg applies to even interface */
+		if (net_param->iface_num & 0x1)
+			break;
+
+		if (net_param->value[0] == ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
+			init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
+					IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+		else if (net_param->value[0] ==
+			 ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
+			init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
+				       ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+		else
+			ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+				   "IPv6 linklocal addr\n");
+		break;
+	case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
+		/* Autocfg applies to even interface */
+		if (net_param->iface_num & 0x1)
+			break;
+
+		if (net_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
+			memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
+			       sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+		break;
+	case ISCSI_NET_PARAM_IFACE_ENABLED:
+		if (net_param->value[0] == ISCSI_TRUE)
+			init_fw_cb->ipv6_opts |=
+				cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
+		else
+			init_fw_cb->ipv6_opts &=
+				cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
+					    0xFFFF);
+		break;
+	case ISCSI_NET_PARAM_VLAN:
+		if (net_param->length != sizeof(init_fw_cb->ipv6_vlan_tag))
+			break;
+		init_fw_cb->ipv6_vlan_tag = *(uint16_t *)net_param->value;
+		break;
+	default:
+		ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
+			   net_param->param_type);
+		break;
+	}
+}
+
+static inline void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
+				    struct iscsi_net_param *net_param,
+				    struct addr_ctrl_blk *init_fw_cb)
+{
+	switch (net_param->param_type) {
+	case ISCSI_NET_PARAM_IPV4_ADDR:
+		memcpy(init_fw_cb->ipv4_addr, net_param->value,
+		       sizeof(init_fw_cb->ipv4_addr));
+		break;
+	case ISCSI_NET_PARAM_IPV4_SUBNET:
+		memcpy(init_fw_cb->ipv4_subnet,	net_param->value,
+		       sizeof(init_fw_cb->ipv4_subnet));
+		break;
+	case ISCSI_NET_PARAM_IPV4_GW:
+		memcpy(init_fw_cb->ipv4_gw_addr, net_param->value,
+		       sizeof(init_fw_cb->ipv4_gw_addr));
+		break;
+	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+		if (net_param->value[0] == ISCSI_BOOTPROTO_DHCP)
+			init_fw_cb->ipv4_tcp_opts |=
+					cpu_to_le16(TCPOPT_DHCP_ENABLE);
+		else if (net_param->value[0] == ISCSI_BOOTPROTO_STATIC)
+			init_fw_cb->ipv4_tcp_opts &=
+					cpu_to_le16(~TCPOPT_DHCP_ENABLE);
+		else
+			ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
+		break;
+	case ISCSI_NET_PARAM_IFACE_ENABLED:
+		if (net_param->value[0] == ISCSI_TRUE)
+			init_fw_cb->ipv4_ip_opts |=
+				cpu_to_le16(IPOPT_IPv4_PROTOCOL_ENABLE);
+		else
+			init_fw_cb->ipv4_ip_opts &=
+				cpu_to_le16(~IPOPT_IPv4_PROTOCOL_ENABLE &
+					    0xFFFF);
+		break;
+	case ISCSI_NET_PARAM_VLAN:
+		if (net_param->length != sizeof(init_fw_cb->ipv4_vlan_tag))
+			break;
+		init_fw_cb->ipv4_vlan_tag = *(uint16_t *)net_param->value;
+		break;
+	default:
+		ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
+			   net_param->param_type);
+		break;
+	}
+}
+
+static void
+qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
+{
+	struct addr_ctrl_blk_def *acb;
+	acb = (struct addr_ctrl_blk_def *)init_fw_cb;
+	memset(acb->reserved1, 0, sizeof(acb->reserved1));
+	memset(acb->reserved2, 0, sizeof(acb->reserved2));
+	memset(acb->reserved3, 0, sizeof(acb->reserved3));
+	memset(acb->reserved4, 0, sizeof(acb->reserved4));
+	memset(acb->reserved5, 0, sizeof(acb->reserved5));
+	memset(acb->reserved6, 0, sizeof(acb->reserved6));
+	memset(acb->reserved7, 0, sizeof(acb->reserved7));
+	memset(acb->reserved8, 0, sizeof(acb->reserved8));
+	memset(acb->reserved9, 0, sizeof(acb->reserved9));
+	memset(acb->reserved10, 0, sizeof(acb->reserved10));
+	memset(acb->reserved11, 0, sizeof(acb->reserved11));
+	memset(acb->reserved12, 0, sizeof(acb->reserved12));
+	memset(acb->reserved13, 0, sizeof(acb->reserved13));
+	memset(acb->reserved14, 0, sizeof(acb->reserved14));
+	memset(acb->reserved15, 0, sizeof(acb->reserved15));
+}
+
+static int
+qla4xxx_set_net_config(struct Scsi_Host *shost, char *data, int count)
+{
+	struct scsi_qla_host *ha = to_qla_host(shost);
+	int rval = 0;
+	struct iscsi_net_param *net_param = NULL;
+	struct addr_ctrl_blk *init_fw_cb = NULL;
+	dma_addr_t init_fw_cb_dma;
+
+	struct addr_ctrl_blk *acb = NULL;
+	dma_addr_t acb_dma;
+
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	uint32_t total_param_count;
+	uint32_t length;
+
+	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+					sizeof(struct addr_ctrl_blk),
+					&init_fw_cb_dma, GFP_KERNEL);
+	if (!init_fw_cb) {
+		ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
+			   __func__);
+		return -ENOMEM;
+	}
+
+	acb = dma_alloc_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
+				 &acb_dma, GFP_KERNEL);
+	if (!acb) {
+		ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
+			   __func__);
+		rval = -ENOMEM;
+		goto exit_init_fw_cb;
+	}
+	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+	memset(acb, 0, sizeof(struct addr_ctrl_blk));
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
+		ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
+		rval = -EIO;
+		goto exit_init_fw_cb;
+	}
+
+	total_param_count = count;
+	net_param = (struct iscsi_net_param *)data;
+
+	for ( ; total_param_count != 0; total_param_count--) {
+		length = net_param->length;
+
+		switch (net_param->iface_type) {
+		case IFACE_TYPE_IPV4:
+			switch (net_param->iface_num) {
+			case 0:
+				qla4xxx_set_ipv4(ha, net_param, init_fw_cb);
+				break;
+			default:
+				/* Cannot have more than one IPv4 interface */
+				ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
+					   "number = %d\n",
+					   net_param->iface_num);
+				break;
+			}
+			break;
+		case IFACE_TYPE_IPV6:
+			switch (net_param->iface_num) {
+			case 0:
+			case 1:
+				qla4xxx_set_ipv6(ha, net_param, init_fw_cb);
+				break;
+			default:
+				/* Cannot have more than two IPv6 interface */
+				ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
+					   "number = %d\n",
+					   net_param->iface_num);
+				break;
+			}
+			break;
+		default:
+			ql4_printk(KERN_ERR, ha, "%s: Invalid iface type\n",
+				   __func__);
+			break;
+		}
+
+		net_param = (struct iscsi_net_param *)((uint8_t *)net_param +
+			    sizeof(struct iscsi_net_param) + length);
+	}
+
+	init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
+
+	rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
+				 sizeof(struct addr_ctrl_blk),
+				 FLASH_OPT_RMW_COMMIT);
+	if (rval != QLA_SUCCESS) {
+		ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
+			   __func__);
+		rval = -EIO;
+		goto exit_init_fw_cb;
+	}
+
+	qla4xxx_disable_acb(ha);
+
+	/* Get ACB to check the state of IP address */
+	rval = qla4xxx_get_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
+	if (rval != QLA_SUCCESS) {
+		ql4_printk(KERN_ERR, ha, "%s: get acb mbx failed\n",
+			   __func__);
+		rval = -EIO;
+		goto exit_acb;
+	}
+
+	qla4xxx_initcb_to_acb(init_fw_cb);
+	rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
+	if (rval != QLA_SUCCESS) {
+		ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
+			   __func__);
+		rval = -EIO;
+		goto exit_acb;
+	}
+
+	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+	qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
+				  init_fw_cb_dma);
+
+exit_acb:
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
+			  acb, acb_dma);
+exit_init_fw_cb:
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
+			  init_fw_cb, init_fw_cb_dma);
+
+	return rval;
+}
+
 static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
 				  enum iscsi_param param, char *buf)
 {
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] qla4xxx: Added new "struct ipaddress_config"
  2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 1/5] iscsi_transport: add support for set_net_config vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 2/5] qla4xxx: " vikas.chaudhary
@ 2011-04-22 18:07 ` vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 4/5] iscsi_transport: show network configuration in sysfs vikas.chaudhary
  2011-04-22 18:07 ` [PATCH 5/5] qla4xxx: added support to show multiple iface " vikas.chaudhary
  4 siblings, 0 replies; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

- Move all ipaddress related param to "struct ipaddress_config"
  from "struct scsi_qla_host"
- update function - qla4xxx_update_local_ip()
- Rename IPOPT_IPv4_PROTOCOL_ENABLE to IPOPT_IPV4_PROTOCOL_ENABLE

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_def.h  |   47 ++++++++++++----------
 drivers/scsi/qla4xxx/ql4_fw.h   |    2 +-
 drivers/scsi/qla4xxx/ql4_init.c |   53 +++++++++++++++----------
 drivers/scsi/qla4xxx/ql4_mbx.c  |   81 ++++++++++++++++++++++-----------------
 drivers/scsi/qla4xxx/ql4_os.c   |    8 +--
 5 files changed, 107 insertions(+), 84 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 4757878..bce5c89 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -357,6 +357,28 @@ struct isp_operations {
 	int (*get_sys_info) (struct scsi_qla_host *);
 };
 
+/*qla4xxx ipaddress configuration details */
+struct ipaddress_config {
+	uint16_t ipv4_options;
+	uint16_t tcp_options;
+	uint16_t ipv4_vlan_tag;
+	uint8_t ipv4_addr_state;
+	uint8_t ip_address[IP_ADDR_LEN];
+	uint8_t subnet_mask[IP_ADDR_LEN];
+	uint8_t gateway[IP_ADDR_LEN];
+	uint32_t ipv6_options;
+	uint32_t ipv6_addl_options;
+	uint8_t ipv6_link_local_state;
+	uint8_t ipv6_addr0_state;
+	uint8_t ipv6_addr1_state;
+	uint8_t ipv6_default_router_state;
+	uint16_t ipv6_vlan_tag;
+	struct in6_addr ipv6_link_local_addr;
+	struct in6_addr ipv6_addr0;
+	struct in6_addr ipv6_addr1;
+	struct in6_addr ipv6_default_router_addr;
+};
+
 /*
  * Linux Host Adapter structure
  */
@@ -452,10 +474,6 @@ struct scsi_qla_host {
 	/* --- From Init_FW --- */
 	/* init_cb_t *init_cb; */
 	uint16_t firmware_options;
-	uint16_t tcp_options;
-	uint8_t ip_address[IP_ADDR_LEN];
-	uint8_t subnet_mask[IP_ADDR_LEN];
-	uint8_t gateway[IP_ADDR_LEN];
 	uint8_t alias[32];
 	uint8_t name_string[256];
 	uint8_t heartbeat_interval;
@@ -534,22 +552,7 @@ struct scsi_qla_host {
 	/* Saved srb for status continuation entry processing */
 	struct srb *status_srb;
 
-	/* IPv6 support info from InitFW */
 	uint8_t acb_version;
-	uint8_t ipv4_addr_state;
-	uint16_t ipv4_options;
-
-	uint32_t resvd2;
-	uint32_t ipv6_options;
-	uint32_t ipv6_addl_options;
-	uint8_t ipv6_link_local_state;
-	uint8_t ipv6_addr0_state;
-	uint8_t ipv6_addr1_state;
-	uint8_t ipv6_default_router_state;
-	struct in6_addr ipv6_link_local_addr;
-	struct in6_addr ipv6_addr0;
-	struct in6_addr ipv6_addr1;
-	struct in6_addr ipv6_default_router_addr;
 
 	/* qla82xx specific fields */
 	struct device_reg_82xx  __iomem *qla4_8xxx_reg; /* Base I/O address */
@@ -584,16 +587,18 @@ struct scsi_qla_host {
 	uint32_t nx_reset_timeout;
 
 	struct completion mbx_intr_comp;
+	struct ipaddress_config ip_config;
 };
 
 static inline int is_ipv4_enabled(struct scsi_qla_host *ha)
 {
-	return ((ha->ipv4_options & IPOPT_IPv4_PROTOCOL_ENABLE) != 0);
+	return ((ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE) != 0);
 }
 
 static inline int is_ipv6_enabled(struct scsi_qla_host *ha)
 {
-	return ((ha->ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
+	return ((ha->ip_config.ipv6_options &
+		IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
 }
 
 static inline int is_qla4010(struct scsi_qla_host *ha)
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index d05e8be..9a07b8d 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -483,7 +483,7 @@ struct addr_ctrl_blk {
 	uint16_t ipv4_tcp_opts;	/* 32-33 */
 #define TCPOPT_DHCP_ENABLE		0x0200
 	uint16_t ipv4_ip_opts;	/* 34-35 */
-#define  IPOPT_IPv4_PROTOCOL_ENABLE	0x8000
+#define IPOPT_IPV4_PROTOCOL_ENABLE	0x8000
 
 	uint16_t iscsi_max_pdu_size;	/* 36-37 */
 	uint8_t ipv4_tos;	/* 38 */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 48e2241..1f267d8 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -236,38 +236,44 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
 				    FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
 			ipv4_wait = 1;
 		}
-		if (((ha->ipv6_addl_options &
-			    IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
-		    ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) ||
-		     (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) ||
-		     (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) {
+		if (((ha->ip_config.ipv6_addl_options &
+		      IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
+		    ((ha->ip_config.ipv6_link_local_state ==
+		      IP_ADDRSTATE_ACQUIRING) ||
+		     (ha->ip_config.ipv6_addr0_state ==
+		      IP_ADDRSTATE_ACQUIRING) ||
+		     (ha->ip_config.ipv6_addr1_state ==
+		      IP_ADDRSTATE_ACQUIRING))) {
 
 			ipv6_wait = 1;
 
-			if ((ha->ipv6_link_local_state ==
-						     IP_ADDRSTATE_PREFERRED) ||
-			    (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) ||
-			    (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) {
+			if ((ha->ip_config.ipv6_link_local_state ==
+			     IP_ADDRSTATE_PREFERRED) ||
+			    (ha->ip_config.ipv6_addr0_state ==
+			     IP_ADDRSTATE_PREFERRED) ||
+			    (ha->ip_config.ipv6_addr1_state ==
+			     IP_ADDRSTATE_PREFERRED)) {
 				DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
 					      "Preferred IP configured."
 					      " Don't wait!\n", ha->host_no,
 					      __func__));
 				ipv6_wait = 0;
 			}
-			if (memcmp(&ha->ipv6_default_router_addr, ip_address,
-				IPv6_ADDR_LEN) == 0) {
+			if (memcmp(&ha->ip_config.ipv6_default_router_addr,
+				   ip_address, IPv6_ADDR_LEN) == 0) {
 				DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
 					      "No Router configured. "
 					      "Don't wait!\n", ha->host_no,
 					      __func__));
 				ipv6_wait = 0;
 			}
-			if ((ha->ipv6_default_router_state ==
-						IPV6_RTRSTATE_MANUAL) &&
-			    (ha->ipv6_link_local_state ==
-						IP_ADDRSTATE_TENTATIVE) &&
-			    (memcmp(&ha->ipv6_link_local_addr,
-				    &ha->ipv6_default_router_addr, 4) == 0)) {
+			if ((ha->ip_config.ipv6_default_router_state ==
+			     IPV6_RTRSTATE_MANUAL) &&
+			    (ha->ip_config.ipv6_link_local_state ==
+			     IP_ADDRSTATE_TENTATIVE) &&
+			    (memcmp(&ha->ip_config.ipv6_link_local_addr,
+			     &ha->ip_config.ipv6_default_router_addr, 4) ==
+			     0)) {
 				DEBUG2(printk("scsi%ld: %s: LinkLocal Router & "
 					"IP configured. Don't wait!\n",
 					ha->host_no, __func__));
@@ -279,11 +285,14 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
 				      "IP(s) \"", ha->host_no, __func__));
 			if (ipv4_wait)
 				DEBUG2(printk("IPv4 "));
-			if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING)
+			if (ha->ip_config.ipv6_link_local_state ==
+			    IP_ADDRSTATE_ACQUIRING)
 				DEBUG2(printk("IPv6LinkLocal "));
-			if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING)
+			if (ha->ip_config.ipv6_addr0_state ==
+			    IP_ADDRSTATE_ACQUIRING)
 				DEBUG2(printk("IPv6Addr0 "));
-			if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING)
+			if (ha->ip_config.ipv6_addr1_state ==
+			    IP_ADDRSTATE_ACQUIRING)
 				DEBUG2(printk("IPv6Addr1 "));
 			DEBUG2(printk("\"\n"));
 		}
@@ -1297,8 +1306,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
 		goto exit_init_online;
 
 	/* Skip device discovery if ip and subnet is zero */
-	if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
-	    memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
+	if (memcmp(ha->ip_config.ip_address, ip_address, IP_ADDR_LEN) == 0 ||
+	    memcmp(ha->ip_config.subnet_mask, ip_address, IP_ADDR_LEN) == 0)
 		goto exit_init_online;
 
 	if (renew_ddb_list == PRESERVE_DDB_LIST) {
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 743290e..d213fa7 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -341,39 +341,57 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
 
 static void
 qla4xxx_update_local_ip(struct scsi_qla_host *ha,
-			 struct addr_ctrl_blk  *init_fw_cb)
+			struct addr_ctrl_blk *init_fw_cb)
 {
+	ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
+	ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
+	ha->ip_config.ipv4_addr_state =
+				le16_to_cpu(init_fw_cb->ipv4_addr_state);
+
+	if (ha->acb_version == ACB_SUPPORTED) {
+		ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
+		ha->ip_config.ipv6_addl_options =
+				le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
+	}
+
 	/* Save IPv4 Address Info */
-	memcpy(ha->ip_address, init_fw_cb->ipv4_addr,
-		min(sizeof(ha->ip_address), sizeof(init_fw_cb->ipv4_addr)));
-	memcpy(ha->subnet_mask, init_fw_cb->ipv4_subnet,
-		min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->ipv4_subnet)));
-	memcpy(ha->gateway, init_fw_cb->ipv4_gw_addr,
-		min(sizeof(ha->gateway), sizeof(init_fw_cb->ipv4_gw_addr)));
+	memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
+	       min(sizeof(ha->ip_config.ip_address),
+		   sizeof(init_fw_cb->ipv4_addr)));
+	memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
+	       min(sizeof(ha->ip_config.subnet_mask),
+		   sizeof(init_fw_cb->ipv4_subnet)));
+	memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
+	       min(sizeof(ha->ip_config.gateway),
+		   sizeof(init_fw_cb->ipv4_gw_addr)));
 
 	if (is_ipv6_enabled(ha)) {
 		/* Save IPv6 Address */
-		ha->ipv6_link_local_state = init_fw_cb->ipv6_lnk_lcl_addr_state;
-		ha->ipv6_addr0_state = init_fw_cb->ipv6_addr0_state;
-		ha->ipv6_addr1_state = init_fw_cb->ipv6_addr1_state;
-		ha->ipv6_default_router_state = init_fw_cb->ipv6_dflt_rtr_state;
-		ha->ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
-		ha->ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
-
-		memcpy(&ha->ipv6_link_local_addr.in6_u.u6_addr8[8],
-			init_fw_cb->ipv6_if_id,
-			min(sizeof(ha->ipv6_link_local_addr)/2,
-			sizeof(init_fw_cb->ipv6_if_id)));
-		memcpy(&ha->ipv6_addr0, init_fw_cb->ipv6_addr0,
-			min(sizeof(ha->ipv6_addr0),
-			sizeof(init_fw_cb->ipv6_addr0)));
-		memcpy(&ha->ipv6_addr1, init_fw_cb->ipv6_addr1,
-			min(sizeof(ha->ipv6_addr1),
-			sizeof(init_fw_cb->ipv6_addr1)));
-		memcpy(&ha->ipv6_default_router_addr,
-			init_fw_cb->ipv6_dflt_rtr_addr,
-			min(sizeof(ha->ipv6_default_router_addr),
-			sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
+		ha->ip_config.ipv6_link_local_state =
+			le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
+		ha->ip_config.ipv6_addr0_state =
+				le16_to_cpu(init_fw_cb->ipv6_addr0_state);
+		ha->ip_config.ipv6_addr1_state =
+				le16_to_cpu(init_fw_cb->ipv6_addr1_state);
+		ha->ip_config.ipv6_default_router_state =
+				le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
+		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
+		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
+
+		memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
+		       init_fw_cb->ipv6_if_id,
+		       min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
+			   sizeof(init_fw_cb->ipv6_if_id)));
+		memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
+		       min(sizeof(ha->ip_config.ipv6_addr0),
+			   sizeof(init_fw_cb->ipv6_addr0)));
+		memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
+		       min(sizeof(ha->ip_config.ipv6_addr1),
+			   sizeof(init_fw_cb->ipv6_addr1)));
+		memcpy(&ha->ip_config.ipv6_default_router_addr,
+		       init_fw_cb->ipv6_dflt_rtr_addr,
+		       min(sizeof(ha->ip_config.ipv6_default_router_addr),
+			   sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
 	}
 }
 
@@ -397,9 +415,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
 	/* Save some info in adapter structure. */
 	ha->acb_version = init_fw_cb->acb_version;
 	ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
-	ha->tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
-	ha->ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
-	ha->ipv4_addr_state = le16_to_cpu(init_fw_cb->ipv4_addr_state);
 	ha->heartbeat_interval = init_fw_cb->hb_interval;
 	memcpy(ha->name_string, init_fw_cb->iscsi_name,
 		min(sizeof(ha->name_string),
@@ -407,10 +422,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
 	/*memcpy(ha->alias, init_fw_cb->Alias,
 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
 
-	if (ha->acb_version == ACB_SUPPORTED) {
-		ha->ipv6_options = init_fw_cb->ipv6_opts;
-		ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
-	}
 	qla4xxx_update_local_ip(ha, init_fw_cb);
 
 	return QLA_SUCCESS;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index e9b669d..09e371f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -190,9 +190,7 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
 		len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
 		break;
 	case ISCSI_HOST_PARAM_IPADDRESS:
-		len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
-			      ha->ip_address[1], ha->ip_address[2],
-			      ha->ip_address[3]);
+		len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
 		break;
 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
 		len = sprintf(buf, "%s\n", ha->name_string);
@@ -328,10 +326,10 @@ static inline void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
 	case ISCSI_NET_PARAM_IFACE_ENABLED:
 		if (net_param->value[0] == ISCSI_TRUE)
 			init_fw_cb->ipv4_ip_opts |=
-				cpu_to_le16(IPOPT_IPv4_PROTOCOL_ENABLE);
+				cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);
 		else
 			init_fw_cb->ipv4_ip_opts &=
-				cpu_to_le16(~IPOPT_IPv4_PROTOCOL_ENABLE &
+				cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &
 					    0xFFFF);
 		break;
 	case ISCSI_NET_PARAM_VLAN:
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] iscsi_transport: show network configuration in sysfs
  2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
                   ` (2 preceding siblings ...)
  2011-04-22 18:07 ` [PATCH 3/5] qla4xxx: Added new "struct ipaddress_config" vikas.chaudhary
@ 2011-04-22 18:07 ` vikas.chaudhary
  2011-04-23 22:40   ` Mike Christie
  2011-04-22 18:07 ` [PATCH 5/5] qla4xxx: added support to show multiple iface " vikas.chaudhary
  4 siblings, 1 reply; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

To support multiple network addresses per adapter need to have a new way to
represent network interface (net iface) in sysfs.

Currently only one ipaddress and hwaddress is displayed

\# ls /sys/class/iscsi_host/host18
device  hwaddress  initiatorname  ipaddress  power  subsystem  uevent

In this patch the net iface is presented as a separate class device.
The one that can be added/removed dynamically or statically, based on how
the user configures the multiple net iface on the adapter.

The new sysfs directory would look like this
\# /sys/class/iscsi_iface/
|
|- ipv4-iface-<host_no>-<iface_no>/                             <-- for ipv4
                                |- ipaddress
                                |- subnet
                                |- gateway
                                |- bootproto
                                |- enabled
|- ipv6-iface-<host_no>-<iface_no>/                             <-- for ipv6
                                |- ipaddress
                                |- link_local_addr
                                |- router_addr
                                |- ipaddr_autocfg
                                |- linklocal_autocfg
                                |- enabled

We can also get above .iscsi_iface. class from:-
\# /sys/class/iscsi_host/host12/device/iscsi_iface/

With this change, iscsadm would need changes to create iface by getting
hw/ip related data from new sysfs path.
The old path still can be maintained to keep backward compatibility.

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Reviewed-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
---
 drivers/scsi/scsi_transport_iscsi.c |  179 ++++++++++++++++++++++++++++++++++-
 include/scsi/iscsi_if.h             |   17 ++++
 include/scsi/scsi_transport_iscsi.h |   24 +++++
 3 files changed, 219 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 7596234..76967a7 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -270,6 +270,155 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
 }
 EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
 
+/*
+ * Interface to display network param to sysfs
+ */
+
+static void iscsi_iface_release(struct device *dev)
+{
+	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
+	kfree(iface);
+}
+
+static struct class iscsi_iface_class = {
+	.name = "iscsi_iface",
+	.dev_release = iscsi_iface_release,
+};
+
+#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store)	\
+struct device_attribute dev_attr_##_prefix##_##_name =		\
+	__ATTR(_name, _mode, _show, _store)
+
+/* iface attrs show */
+#define iscsi_iface_attr_show(type, name, param)			\
+static ssize_t								\
+show_##type##_##name(struct device *dev, struct device_attribute *attr,	\
+		     char *buf)						\
+{									\
+	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);		\
+	struct iscsi_transport *t = iface->transport;			\
+	return t->get_iface_param(iface, param, buf);			\
+}									\
+
+#define iscsi_iface_attr(type, name, param)				\
+	iscsi_iface_attr_show(type, name, param)			\
+static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
+
+/* generic read only ipvi4 attribute */
+iscsi_iface_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
+iscsi_iface_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
+iscsi_iface_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
+iscsi_iface_attr(ipv4_iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLED);
+iscsi_iface_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
+
+/* generic read only ipv6 attribute */
+iscsi_iface_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
+iscsi_iface_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
+iscsi_iface_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
+iscsi_iface_attr(ipv6_iface, ipaddr_autocfg,
+		 ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
+iscsi_iface_attr(ipv6_iface, linklocal_autocfg,
+		 ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
+iscsi_iface_attr(ipv6_iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLED);
+
+/* IPv4 Attrs */
+#define ISCSI_IPV4_IFACE_ATTRS	5
+static struct attribute *iscsi_ipv4_iface_attrs[ISCSI_IPV4_IFACE_ATTRS + 1];
+
+#define SETUP_IPV4_IFACE_RD_ATTR(field, param_flag)			\
+do {									\
+	if (tt->ipv4_iface_param_mask & param_flag) {			\
+		iscsi_ipv4_iface_attrs[count] =				\
+				&dev_attr_ipv4_iface_##field.attr;	\
+		count++;						\
+	}								\
+} while (0)
+
+static struct attribute_group iscsi_ipv4_iface_group = {
+	.attrs = iscsi_ipv4_iface_attrs,
+};
+
+/* IPv6 Attrs */
+#define ISCSI_IPV6_IFACE_ATTRS	6
+static struct attribute *iscsi_ipv6_iface_attrs[ISCSI_IPV6_IFACE_ATTRS + 1];
+
+#define SETUP_IPV6_IFACE_RD_ATTR(field, param_flag)			\
+do {									\
+	if (tt->ipv6_iface_param_mask & param_flag) {			\
+		iscsi_ipv6_iface_attrs[count] =				\
+				&dev_attr_ipv6_iface_##field.attr;	\
+		count++;						\
+	}								\
+} while (0)
+
+static struct attribute_group iscsi_ipv6_iface_group = {
+	.attrs = iscsi_ipv6_iface_attrs,
+};
+
+struct iscsi_iface *
+iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
+		   uint32_t iface_type, uint32_t iface_num, int dd_size)
+{
+	struct iscsi_iface *iface;
+	int err;
+
+	iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
+	if (!iface)
+		return NULL;
+
+	iface->transport = transport;
+	iface->iface_type = iface_type;
+	iface->iface_num = iface_num;
+	iface->dev.class = &iscsi_iface_class;
+	/* parent reference */
+	iface->dev.parent = get_device(&shost->shost_gendev);
+	if (iface_type == IFACE_TYPE_IPV4)
+		dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
+			     iface_num);
+	else if (iface_type == IFACE_TYPE_IPV6)
+		dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
+			     iface_num);
+	else
+		goto free_iface;
+
+	err = device_register(&iface->dev);
+	if (err)
+		goto free_iface;
+
+	if (iface_type == IFACE_TYPE_IPV4)
+		err = sysfs_create_group(&iface->dev.kobj,
+					 &iscsi_ipv4_iface_group);
+	else if (iface_type == IFACE_TYPE_IPV6)
+		err = sysfs_create_group(&iface->dev.kobj,
+					 &iscsi_ipv6_iface_group);
+
+	if (err)
+		goto iface_unregister_dev;
+
+	if (dd_size)
+		iface->dd_data = &iface[1];
+	return iface;
+
+iface_unregister_dev:
+	device_unregister(&iface->dev);
+
+free_iface:
+	kfree(iface);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_create_iface);
+
+void iscsi_destroy_iface(struct iscsi_iface *iface)
+{
+	if (iface->iface_type == IFACE_TYPE_IPV6)
+		sysfs_remove_group(&iface->dev.kobj, &iscsi_ipv6_iface_group);
+	else
+		sysfs_remove_group(&iface->dev.kobj, &iscsi_ipv4_iface_group);
+
+	device_unregister(&iface->dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
+
 static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
 			    struct device *cdev)
 {
@@ -2175,6 +2324,27 @@ iscsi_register_transport(struct iscsi_transport *tt)
 
 	BUG_ON(count > ISCSI_SESSION_ATTRS);
 	priv->session_attrs[count] = NULL;
+	count = 0;
+
+	SETUP_IPV4_IFACE_RD_ATTR(ipaddress, ISCSI_NET_IPV4_ADDR);
+	SETUP_IPV4_IFACE_RD_ATTR(gateway, ISCSI_NET_IPV4_GW);
+	SETUP_IPV4_IFACE_RD_ATTR(subnet, ISCSI_NET_IPV4_SUBNET);
+	SETUP_IPV4_IFACE_RD_ATTR(bootproto, ISCSI_NET_IPV4_BOOTPROTO);
+	SETUP_IPV4_IFACE_RD_ATTR(enabled, ISCSI_NET_IFACE_ENABLED);
+	BUG_ON(count > ISCSI_IPV4_IFACE_ATTRS);
+	iscsi_ipv4_iface_attrs[count] = NULL;
+	count = 0;
+
+	SETUP_IPV6_IFACE_RD_ATTR(ipaddress, ISCSI_NET_IPV6_ADDR);
+	SETUP_IPV6_IFACE_RD_ATTR(link_local_addr, ISCSI_NET_IPV6_LINKLOCAL);
+	SETUP_IPV6_IFACE_RD_ATTR(router_addr, ISCSI_NET_IPV6_ROUTER);
+	SETUP_IPV6_IFACE_RD_ATTR(ipaddr_autocfg,
+				 ISCSI_NET_IPV6_ADDR_AUTOCFG);
+	SETUP_IPV6_IFACE_RD_ATTR(linklocal_autocfg,
+				 ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG);
+	SETUP_IPV6_IFACE_RD_ATTR(enabled, ISCSI_NET_IFACE_ENABLED);
+	BUG_ON(count > ISCSI_IPV6_IFACE_ATTRS);
+	iscsi_ipv6_iface_attrs[count] = NULL;
 
 	spin_lock_irqsave(&iscsi_transport_lock, flags);
 	list_add(&priv->list, &iscsi_transports);
@@ -2237,10 +2407,14 @@ static __init int iscsi_transport_init(void)
 	if (err)
 		goto unregister_transport_class;
 
-	err = transport_class_register(&iscsi_host_class);
+	err = class_register(&iscsi_iface_class);
 	if (err)
 		goto unregister_endpoint_class;
 
+	err = transport_class_register(&iscsi_host_class);
+	if (err)
+		goto unregister_iface_class;
+
 	err = transport_class_register(&iscsi_connection_class);
 	if (err)
 		goto unregister_host_class;
@@ -2270,6 +2444,8 @@ unregister_conn_class:
 	transport_class_unregister(&iscsi_connection_class);
 unregister_host_class:
 	transport_class_unregister(&iscsi_host_class);
+unregister_iface_class:
+	class_unregister(&iscsi_iface_class);
 unregister_endpoint_class:
 	class_unregister(&iscsi_endpoint_class);
 unregister_transport_class:
@@ -2285,6 +2461,7 @@ static void __exit iscsi_transport_exit(void)
 	transport_class_unregister(&iscsi_session_class);
 	transport_class_unregister(&iscsi_host_class);
 	class_unregister(&iscsi_endpoint_class);
+	class_unregister(&iscsi_iface_class);
 	class_unregister(&iscsi_transport_class);
 }
 
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 449e55b..6282f8b 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -279,6 +279,23 @@ enum iscsi_net_param_type {
 	ISCSI_NET_PARAM_VLAN			= 13,
 };
 
+#define ISCSI_NET_IPV4_ADDR		(1ULL << ISCSI_NET_PARAM_IPV4_ADDR)
+#define ISCSI_NET_IPV4_SUBNET		(1ULL << ISCSI_NET_PARAM_IPV4_SUBNET)
+#define ISCSI_NET_IPV4_GW		(1ULL << ISCSI_NET_PARAM_IPV4_GW)
+#define ISCSI_NET_IPV4_BOOTPROTO	(1ULL << ISCSI_NET_PARAM_IPV4_BOOTPROTO)
+#define ISCSI_NET_MAC			(1ULL << ISCSI_NET_PARAM_MAC)
+#define ISCSI_NET_IPV6_LINKLOCAL	(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL)
+#define ISCSI_NET_IPV6_ADDR		(1ULL << ISCSI_NET_PARAM_IPV6_ADDR)
+#define ISCSI_NET_IPV6_ROUTER		(1ULL << ISCSI_NET_PARAM_IPV6_ROUTER)
+#define ISCSI_NET_IPV6_ADDR_AUTOCFG			\
+				(1ULL << ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG)
+#define ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG		\
+				(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG)
+#define ISCSI_NET_IPV6_ROUTER_AUTOCFG		\
+				(1ULL << ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG)
+#define ISCSI_NET_IFACE_ENABLED		(1ULL << ISCSI_NET_PARAM_IFACE_ENABLED)
+#define ISCSI_NET_VLAN			(1ULL << ISCSI_NET_PARAM_VLAN)
+
 /* 20 param per iface * 10 iface per port = 200 params */
 #define ISCSI_MAX_IFACE_PER_HW		10
 #define ISCSI_MAX_PARAM_PER_IFACE	20
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 45b9df9..09a0108 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -37,6 +37,7 @@ struct iscsi_cls_conn;
 struct iscsi_conn;
 struct iscsi_task;
 struct sockaddr;
+struct iscsi_iface;
 
 /**
  * struct iscsi_transport - iSCSI Transport template
@@ -87,6 +88,8 @@ struct iscsi_transport {
 	/* LLD sets this to indicate what values it can export to sysfs */
 	uint64_t param_mask;
 	uint64_t host_param_mask;
+	uint64_t ipv4_iface_param_mask;
+	uint64_t ipv6_iface_param_mask;
 	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
 					uint16_t cmds_max, uint16_t qdepth,
 					uint32_t sn);
@@ -138,6 +141,8 @@ struct iscsi_transport {
 			  uint32_t enable, struct sockaddr *dst_addr);
 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
 	int (*set_net_config) (struct Scsi_Host *shost, char *data, int count);
+	int (*get_iface_param) (struct iscsi_iface *iface,
+				enum iscsi_net_param_type param, char *buf);
 };
 
 /*
@@ -229,6 +234,19 @@ struct iscsi_endpoint {
 	struct iscsi_cls_conn *conn;
 };
 
+struct iscsi_iface {
+	struct device dev;
+	struct iscsi_transport *transport;
+	uint32_t iface_type;	/* IPv4 or IPv6 */
+	uint32_t iface_num;	/* iface number, 0 - n */
+	void *dd_data;		/* LLD private data */
+};
+
+#define iscsi_dev_to_iface(_dev) \
+	container_of(_dev, struct iscsi_iface, dev)
+#define iscsi_iface_to_shost(_iface) \
+	dev_to_shost(_iface->dev.parent)
+
 /*
  * session and connection functions that can be used by HW iSCSI LLDs
  */
@@ -262,5 +280,11 @@ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
 extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
 extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
 extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
+extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
+					      struct iscsi_transport *t,
+					      uint32_t iface_type,
+					      uint32_t iface_num, int dd_size);
+extern void iscsi_destroy_iface(struct iscsi_iface *iface);
+extern struct iscsi_iface *iscsi_lookup_iface(int handle);
 
 #endif
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] qla4xxx: added support to show multiple iface in sysfs
  2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
                   ` (3 preceding siblings ...)
  2011-04-22 18:07 ` [PATCH 4/5] iscsi_transport: show network configuration in sysfs vikas.chaudhary
@ 2011-04-22 18:07 ` vikas.chaudhary
  4 siblings, 0 replies; 8+ messages in thread
From: vikas.chaudhary @ 2011-04-22 18:07 UTC (permalink / raw)
  To: James.Bottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Reviewed-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_def.h |    3 +
 drivers/scsi/qla4xxx/ql4_os.c  |  114 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index bce5c89..3a0316c 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -588,6 +588,9 @@ struct scsi_qla_host {
 
 	struct completion mbx_intr_comp;
 	struct ipaddress_config ip_config;
+	struct iscsi_iface *iface_ipv4;
+	struct iscsi_iface *iface_ipv6_1;
+	struct iscsi_iface *iface_ipv6_2;
 };
 
 static inline int is_ipv4_enabled(struct scsi_qla_host *ha)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 09e371f..673deb3 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -82,6 +82,8 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
 				  enum iscsi_host_param param, char *buf);
 static int qla4xxx_set_net_config(struct Scsi_Host *shost, char *data,
 				  int count);
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+				   enum iscsi_net_param_type param, char *buf);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
 static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
 
@@ -139,16 +141,95 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
 				  ISCSI_HOST_IPADDRESS |
 				  ISCSI_HOST_INITIATOR_NAME,
+	.ipv4_iface_param_mask	= ISCSI_NET_IPV4_ADDR |
+				  ISCSI_NET_IPV4_SUBNET |
+				  ISCSI_NET_IPV4_GW |
+				  ISCSI_NET_IPV4_BOOTPROTO |
+				  ISCSI_NET_IFACE_ENABLED,
+	.ipv6_iface_param_mask	= ISCSI_NET_IPV6_LINKLOCAL |
+				  ISCSI_NET_IPV6_ADDR |
+				  ISCSI_NET_IPV6_ROUTER |
+				  ISCSI_NET_IPV6_ADDR_AUTOCFG |
+				  ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG |
+				  ISCSI_NET_IFACE_ENABLED,
 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
 	.get_conn_param		= qla4xxx_conn_get_param,
 	.get_session_param	= qla4xxx_sess_get_param,
 	.get_host_param		= qla4xxx_host_get_param,
 	.set_net_config		= qla4xxx_set_net_config,
 	.session_recovery_timedout = qla4xxx_recovery_timedout,
+	.get_iface_param	= qla4xxx_get_iface_param,
 };
 
 static struct scsi_transport_template *qla4xxx_scsi_transport;
 
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+				   enum iscsi_net_param_type param, char *buf)
+{
+	struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
+	struct scsi_qla_host *ha = to_qla_host(shost);
+	int len = -ENOSYS;
+
+	switch (param) {
+	case ISCSI_NET_PARAM_IPV4_ADDR:
+		len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
+		break;
+	case ISCSI_NET_PARAM_IPV4_SUBNET:
+		len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask);
+		break;
+	case ISCSI_NET_PARAM_IPV4_GW:
+		len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway);
+		break;
+	case ISCSI_NET_PARAM_IFACE_ENABLED:
+		if (iface->iface_type == IFACE_TYPE_IPV4)
+			len = sprintf(buf, "%s\n",
+				      (ha->ip_config.ipv4_options &
+				       IPOPT_IPV4_PROTOCOL_ENABLE) ?
+				      "true" : "false");
+		else if (iface->iface_type == IFACE_TYPE_IPV6)
+			len = sprintf(buf, "%s\n",
+				      (ha->ip_config.ipv6_options &
+				       IPV6_OPT_IPV6_PROTOCOL_ENABLE) ?
+				       "true" : "false");
+		break;
+	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+		len = sprintf(buf, "%s\n",
+			      (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ?
+			      "dhcp" : "static");
+		break;
+	case ISCSI_NET_PARAM_IPV6_ADDR:
+		if (iface->iface_num == 1)
+			len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0);
+		if (iface->iface_num == 2)
+			len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1);
+		break;
+	case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+		len = sprintf(buf, "%pI6\n",
+			      &ha->ip_config.ipv6_link_local_addr);
+		break;
+	case ISCSI_NET_PARAM_IPV6_ROUTER:
+		len = sprintf(buf, "%pI6\n",
+			      &ha->ip_config.ipv6_default_router_addr);
+		break;
+	case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+		len = sprintf(buf, "%s\n",
+			      (ha->ip_config.ipv6_addl_options &
+			       IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ?
+			       "nd" : "static");
+		break;
+	case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+		len = sprintf(buf, "%s\n",
+			      (ha->ip_config.ipv6_addl_options &
+			       IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ?
+			       "auto" : "static");
+		break;
+	default:
+		len = -ENOSYS;
+	}
+
+	return len;
+}
+
 static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
 {
 	struct iscsi_cls_session *session;
@@ -1899,6 +1980,34 @@ uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
 	return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
 }
 
+static void qla4xxx_create_iface(struct scsi_qla_host *ha)
+{
+	/* IPv4 */
+	ha->iface_ipv4 = iscsi_create_iface(ha->host,
+					    &qla4xxx_iscsi_transport,
+					    IFACE_TYPE_IPV4, 1, 0);
+
+	/* IPv6 iface-1 */
+	ha->iface_ipv6_1 = iscsi_create_iface(ha->host,
+					      &qla4xxx_iscsi_transport,
+					      IFACE_TYPE_IPV6, 1, 0);
+
+	/* IPv6 iface-2 */
+	ha->iface_ipv6_2 = iscsi_create_iface(ha->host,
+					      &qla4xxx_iscsi_transport,
+					      IFACE_TYPE_IPV6, 2, 0);
+}
+
+static void qla4xxx_destroy_iface(struct scsi_qla_host *ha)
+{
+	if (ha->iface_ipv4)
+		iscsi_destroy_iface(ha->iface_ipv4);
+	if (ha->iface_ipv6_1)
+		iscsi_destroy_iface(ha->iface_ipv6_1);
+	if (ha->iface_ipv6_2)
+		iscsi_destroy_iface(ha->iface_ipv6_2);
+}
+
 /**
  * qla4xxx_probe_adapter - callback function to probe HBA
  * @pdev: pointer to pci_dev structure
@@ -2099,6 +2208,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);
 	scsi_scan_host(host);
+
+	qla4xxx_create_iface(ha);
 	return 0;
 
 probe_failed:
@@ -2168,6 +2279,9 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
 	/* remove devs from iscsi_sessions to scsi_devices */
 	qla4xxx_free_ddb_list(ha);
 
+	/* destroy iface from sysfs */
+	qla4xxx_destroy_iface(ha);
+
 	scsi_remove_host(ha->host);
 
 	qla4xxx_free_adapter(ha);
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/5] iscsi_transport: add support for set_net_config
  2011-04-22 18:07 ` [PATCH 1/5] iscsi_transport: add support for set_net_config vikas.chaudhary
@ 2011-04-23  5:19   ` Mike Christie
  0 siblings, 0 replies; 8+ messages in thread
From: Mike Christie @ 2011-04-23  5:19 UTC (permalink / raw)
  To: vikas.chaudhary
  Cc: James.Bottomley, linux-scsi, lalit.chandivade, ravi.anand,
	Harish Zunjarrao

On 04/22/2011 01:07 PM, vikas.chaudhary@qlogic.com wrote:
> +/* 20 param per iface * 10 iface per port = 200 params */
> +#define ISCSI_MAX_IFACE_PER_HW		10
> +#define ISCSI_MAX_PARAM_PER_IFACE	20
> +#define ISCSI_MAX_NET_PARAMS (ISCSI_MAX_IFACE_PER_HW * \
> +			      ISCSI_MAX_PARAM_PER_IFACE)
> +

See comment from here:
http://marc.info/?l=linux-scsi&m=130266611526117&w=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] iscsi_transport: show network configuration in sysfs
  2011-04-22 18:07 ` [PATCH 4/5] iscsi_transport: show network configuration in sysfs vikas.chaudhary
@ 2011-04-23 22:40   ` Mike Christie
  0 siblings, 0 replies; 8+ messages in thread
From: Mike Christie @ 2011-04-23 22:40 UTC (permalink / raw)
  To: vikas.chaudhary; +Cc: James.Bottomley, linux-scsi, lalit.chandivade, ravi.anand

On 04/22/2011 01:07 PM, vikas.chaudhary@qlogic.com wrote:
> From: Vikas Chaudhary<vikas.chaudhary@qlogic.com>
>
> To support multiple network addresses per adapter need to have a new way to
> represent network interface (net iface) in sysfs.
>

 From the previous posting's comments you did not handle or respond to 
the comment about linking the sessions to the iface. Basically, I want 
to know how for sessionX you know which iface is being used? For 
example, users want to know the src ip address for the session.

You could make a symlink from the session to the iface or make the iface 
the parent of the session instead of the host then add symlinks to/from, 
for compat with existing tools, the session/host.

We could do this in another patch, but I would then want to wait off on 
sending this patch and the 5/5 to James so we do not have some kernels 
with it and some without.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-04-23 22:40 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-22 18:07 [PATCH 0/5] qla4xxx: Proposal for iSCSI Network Configuration vikas.chaudhary
2011-04-22 18:07 ` [PATCH 1/5] iscsi_transport: add support for set_net_config vikas.chaudhary
2011-04-23  5:19   ` Mike Christie
2011-04-22 18:07 ` [PATCH 2/5] qla4xxx: " vikas.chaudhary
2011-04-22 18:07 ` [PATCH 3/5] qla4xxx: Added new "struct ipaddress_config" vikas.chaudhary
2011-04-22 18:07 ` [PATCH 4/5] iscsi_transport: show network configuration in sysfs vikas.chaudhary
2011-04-23 22:40   ` Mike Christie
2011-04-22 18:07 ` [PATCH 5/5] qla4xxx: added support to show multiple iface " vikas.chaudhary

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.