diff mbox series

[1/4] include:scsi: FDMI enhancement

Message ID 20201009093631.4182-2-jhasan@marvell.com
State New
Headers show
Series [1/4] include:scsi: FDMI enhancement | expand

Commit Message

Javed Hasan Oct. 9, 2020, 9:36 a.m. UTC
All the attributes added for RHBA and RPA registration.
Fall back mechanism is added in between RBHA V2 and
RHBA V1 attributes. In case RHBA get failed
for RBHA V2 attributes, then we fall back to  RHBA V1
attributes registration.

Signed-off-by: Javed Hasan <jhasan@marvell.com>
---
 include/scsi/fc_encode.h         | 249 ++++++++++++++++++++++++++++++-
 include/scsi/scsi_transport_fc.h |  25 +++-
 2 files changed, 270 insertions(+), 4 deletions(-)

Comments

Himanshu Madhani Oct. 19, 2020, 3:25 p.m. UTC | #1
> On Oct 9, 2020, at 4:36 AM, Javed Hasan <jhasan@marvell.com> wrote:
> 
> All the attributes added for RHBA and RPA registration.
> Fall back mechanism is added in between RBHA V2 and
> RHBA V1 attributes. In case RHBA get failed
> for RBHA V2 attributes, then we fall back to  RHBA V1
> attributes registration.
> 
> Signed-off-by: Javed Hasan <jhasan@marvell.com>
> ---
> include/scsi/fc_encode.h         | 249 ++++++++++++++++++++++++++++++-
> include/scsi/scsi_transport_fc.h |  25 +++-
> 2 files changed, 270 insertions(+), 4 deletions(-)
> 
> diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
> index c6660205d73f..57aae3e25c43 100644
> --- a/include/scsi/fc_encode.h
> +++ b/include/scsi/fc_encode.h
> @@ -210,10 +210,11 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 	struct fc_fdmi_attr_entry *entry;
> 	struct fs_fdmi_attrs *hba_attrs;
> 	int numattrs = 0;
> +	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
> 
> 	switch (op) {
> 	case FC_FDMI_RHBA:
> -		numattrs = 10;
> +		numattrs = 11;
> 		len = sizeof(struct fc_fdmi_rhba);
> 		len -= sizeof(struct fc_fdmi_attr_entry);
> 		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
> @@ -227,8 +228,21 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
> 		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
> 		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
> +		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
> +
> +		if (fc_host->fdmi_version == FDMI_V2) {
> +			numattrs += 7;
> +			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
> +			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
> +			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
> +			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
> +			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
> +			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
> +			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
> +		}
> +
> 		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
> -				    FC_FDMI_SUBTYPE);
> +				FC_FDMI_SUBTYPE);
> 
> 		/* HBA Identifier */
> 		put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
> @@ -333,7 +347,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 				   &entry->type);
> 		put_unaligned_be16(len, &entry->len);
> 		strncpy((char *)&entry->value,
> -			fc_host_optionrom_version(lport->host),
> +			"unknown",
> 			FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
> 
> 		/* Firmware Version */
> @@ -361,6 +375,100 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 			"%s v%s",
> 			init_utsname()->sysname,
> 			init_utsname()->release);
> +
> +		/* Max CT payload */
> +		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN);
> +		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
> +		put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
> +				&entry->type);
> +		put_unaligned_be16(len, &entry->len);
> +		put_unaligned_be32(fc_host_max_ct_payload(lport->host),
> +				&entry->value);
> +
> +		if (fc_host->fdmi_version == FDMI_V2) {
> +			/* Node symbolic name */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +				FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
> +				&entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			strncpy((char *)&entry->value,
> +				fc_host_symbolic_name(lport->host),
> +				FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
> +
> +			/* Vendor specific info */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_num_ports(lport->host),
> +				   &entry->value);
> +
> +			/* Number of ports */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_num_ports(lport->host),
> +				   &entry->value);
> +
> +			/* Fabric name */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +				FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME,
> +				&entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be64(fc_host_fabric_name(lport->host),
> +			   &entry->value);
> +
> +			/* BIOS version */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +				FC_FDMI_HBA_ATTR_FABRICNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION,
> +				&entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +				strncpy((char *)&entry->value,
> +				fc_host_bootbios_version(lport->host),
> +				FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
> +
> +			/* BIOS state */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_bootbios_state(lport->host),
> +				   &entry->value);
> +
> +			/* Vendor identifier  */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +				FC_FDMI_HBA_ATTR_BIOSSTATE_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
> +			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
> +				&entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			strncpy((char *)&entry->value,
> +				fc_host_vendor_identifier(lport->host),
> +				FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
> +		}
> +
> 		break;
> 	case FC_FDMI_RPA:
> 		numattrs = 6;
> @@ -373,6 +481,25 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
> 		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
> 		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
> +
> +
> +		if (fc_host->fdmi_version == FDMI_V2) {
> +			numattrs += 10;
> +
> +			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
> +			//Port name already added in RPA1

Fix incorrect comment style. 

> +			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
> +			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
> +			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
> +			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
> +			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
> +			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
> +
> +		}
> +
> 		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
> 				    FC_FDMI_SUBTYPE);
> 
> @@ -461,6 +588,122 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport,
> 			strncpy((char *)&entry->value,
> 				init_utsname()->nodename,
> 				FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
> +
> +
> +		if (fc_host->fdmi_version == FDMI_V2) {
> +
> +			/* Node name */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be64(fc_host_node_name(lport->host),
> +				   &entry->value);
> +
> +			/* Port name  */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_NODENAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be64(lport->wwpn,
> +				   &entry->value);
> +
> +			/* Port symbolic name */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_PORTNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			strncpy((char *)&entry->value,
> +				fc_host_symbolic_name(lport->host),
> +				FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
> +
> +			/* Port type */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_port_type(lport->host),
> +				   &entry->value);
> +
> +			/* Supported class of service */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_PORTTYPE_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_supported_classes(lport->host),
> +				   &entry->value);
> +
> +			/* Port Fabric name */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be64(fc_host_fabric_name(lport->host),
> +				   &entry->value);
> +
> +			/* Port active FC-4 */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_FABRICNAME_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			memcpy(&entry->value, fc_host_active_fc4s(lport->host),
> +		       FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
> +
> +			/* Port state */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_port_state(lport->host),
> +				   &entry->value);
> +
> +			/* Discovered ports */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_PORTSTATE_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
> +				   &entry->value);
> +
> +			/* Port ID */
> +			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
> +					FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN);
> +			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
> +			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
> +			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID,
> +				   &entry->type);
> +			put_unaligned_be16(len, &entry->len);
> +			put_unaligned_be32(fc_host_port_id(lport->host),
> +				   &entry->value);
> +		}
> +
> 		break;
> 	case FC_FDMI_DPRT:
> 		len = sizeof(struct fc_fdmi_dprt);
> diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
> index 1c7dd35cb7a0..d718a54bb0fb 100644
> --- a/include/scsi/scsi_transport_fc.h
> +++ b/include/scsi/scsi_transport_fc.h
> @@ -482,10 +482,11 @@ enum fc_host_event_code  {
>  * managed by the transport w/o driver interaction.
>  */
> 
> +#define FC_VENDOR_IDENTIFIER	8
> #define FC_FC4_LIST_SIZE		32
> #define FC_SYMBOLIC_NAME_SIZE		256
> #define FC_VERSION_STRING_SIZE		64
> -#define FC_SERIAL_NUMBER_SIZE		80
> +#define FC_SERIAL_NUMBER_SIZE		64
> 
> struct fc_host_attrs {
> 	/* Fixed Attributes */
> @@ -497,6 +498,10 @@ struct fc_host_attrs {
> 	u32 supported_speeds;
> 	u32 maxframe_size;
> 	u16 max_npiv_vports;
> +	u32 max_ct_payload;
> +	u32 num_ports;
> +	u32 num_discovered_ports;
> +	u32 bootbios_state;
> 	char serial_number[FC_SERIAL_NUMBER_SIZE];
> 	char manufacturer[FC_SERIAL_NUMBER_SIZE];
> 	char model[FC_SYMBOLIC_NAME_SIZE];
> @@ -505,6 +510,9 @@ struct fc_host_attrs {
> 	char driver_version[FC_VERSION_STRING_SIZE];
> 	char firmware_version[FC_VERSION_STRING_SIZE];
> 	char optionrom_version[FC_VERSION_STRING_SIZE];
> +	char vendor_identifier[FC_VENDOR_IDENTIFIER];
> +	char bootbios_version[FC_SYMBOLIC_NAME_SIZE];
> +
> 
> 	/* Dynamic Attributes */
> 	u32 port_id;
> @@ -537,6 +545,9 @@ struct fc_host_attrs {
> 
> 	/* bsg support */
> 	struct request_queue *rqst_q;
> +
> +	/* FDMI support version*/
> +	u8 fdmi_version;
> };
> 
> #define shost_to_fc_host(x) \
> @@ -616,6 +627,18 @@ struct fc_host_attrs {
> 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
> #define fc_host_dev_loss_tmo(x) \
> 	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
> +#define fc_host_max_ct_payload(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->max_ct_payload)
> +#define fc_host_vendor_identifier(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->vendor_identifier)
> +#define fc_host_num_discovered_ports(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->num_discovered_ports)
> +#define fc_host_num_ports(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->num_ports)
> +#define fc_host_bootbios_version(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->bootbios_version)
> +#define fc_host_bootbios_state(x)  \
> +	(((struct fc_host_attrs *)(x)->shost_data)->bootbios_state)
> 
> /* The functions by which the transport class and the driver communicate */
> struct fc_function_template {
> -- 
> 2.18.2
> 

Other than the incorrect comment style this patch looks good. 

You can add my R-B once you have addressed the comment. 

--
Himanshu Madhani	 Oracle Linux Engineering
diff mbox series

Patch

diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index c6660205d73f..57aae3e25c43 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -210,10 +210,11 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 	struct fc_fdmi_attr_entry *entry;
 	struct fs_fdmi_attrs *hba_attrs;
 	int numattrs = 0;
+	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
 
 	switch (op) {
 	case FC_FDMI_RHBA:
-		numattrs = 10;
+		numattrs = 11;
 		len = sizeof(struct fc_fdmi_rhba);
 		len -= sizeof(struct fc_fdmi_attr_entry);
 		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
@@ -227,8 +228,21 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
 		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
 		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
+		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
+
+		if (fc_host->fdmi_version == FDMI_V2) {
+			numattrs += 7;
+			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
+			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
+			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
+			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
+			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
+			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
+			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
+		}
+
 		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
-				    FC_FDMI_SUBTYPE);
+				FC_FDMI_SUBTYPE);
 
 		/* HBA Identifier */
 		put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
@@ -333,7 +347,7 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 				   &entry->type);
 		put_unaligned_be16(len, &entry->len);
 		strncpy((char *)&entry->value,
-			fc_host_optionrom_version(lport->host),
+			"unknown",
 			FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
 
 		/* Firmware Version */
@@ -361,6 +375,100 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 			"%s v%s",
 			init_utsname()->sysname,
 			init_utsname()->release);
+
+		/* Max CT payload */
+		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN);
+		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
+		put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
+				&entry->type);
+		put_unaligned_be16(len, &entry->len);
+		put_unaligned_be32(fc_host_max_ct_payload(lport->host),
+				&entry->value);
+
+		if (fc_host->fdmi_version == FDMI_V2) {
+			/* Node symbolic name */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+				FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
+				&entry->type);
+			put_unaligned_be16(len, &entry->len);
+			strncpy((char *)&entry->value,
+				fc_host_symbolic_name(lport->host),
+				FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
+
+			/* Vendor specific info */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_num_ports(lport->host),
+				   &entry->value);
+
+			/* Number of ports */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_num_ports(lport->host),
+				   &entry->value);
+
+			/* Fabric name */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+				FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME,
+				&entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be64(fc_host_fabric_name(lport->host),
+			   &entry->value);
+
+			/* BIOS version */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+				FC_FDMI_HBA_ATTR_FABRICNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION,
+				&entry->type);
+			put_unaligned_be16(len, &entry->len);
+				strncpy((char *)&entry->value,
+				fc_host_bootbios_version(lport->host),
+				FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
+
+			/* BIOS state */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_bootbios_state(lport->host),
+				   &entry->value);
+
+			/* Vendor identifier  */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+				FC_FDMI_HBA_ATTR_BIOSSTATE_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
+			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
+				&entry->type);
+			put_unaligned_be16(len, &entry->len);
+			strncpy((char *)&entry->value,
+				fc_host_vendor_identifier(lport->host),
+				FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
+		}
+
 		break;
 	case FC_FDMI_RPA:
 		numattrs = 6;
@@ -373,6 +481,25 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
 		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
 		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
+
+
+		if (fc_host->fdmi_version == FDMI_V2) {
+			numattrs += 10;
+
+			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
+			//Port name already added in RPA1
+			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
+			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
+			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
+			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
+			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
+			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
+
+		}
+
 		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
 				    FC_FDMI_SUBTYPE);
 
@@ -461,6 +588,122 @@  static inline int fc_ct_ms_fill(struct fc_lport *lport,
 			strncpy((char *)&entry->value,
 				init_utsname()->nodename,
 				FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
+
+
+		if (fc_host->fdmi_version == FDMI_V2) {
+
+			/* Node name */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be64(fc_host_node_name(lport->host),
+				   &entry->value);
+
+			/* Port name  */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_NODENAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be64(lport->wwpn,
+				   &entry->value);
+
+			/* Port symbolic name */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_PORTNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			strncpy((char *)&entry->value,
+				fc_host_symbolic_name(lport->host),
+				FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
+
+			/* Port type */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_port_type(lport->host),
+				   &entry->value);
+
+			/* Supported class of service */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_PORTTYPE_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_supported_classes(lport->host),
+				   &entry->value);
+
+			/* Port Fabric name */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be64(fc_host_fabric_name(lport->host),
+				   &entry->value);
+
+			/* Port active FC-4 */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_FABRICNAME_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			memcpy(&entry->value, fc_host_active_fc4s(lport->host),
+		       FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
+
+			/* Port state */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_port_state(lport->host),
+				   &entry->value);
+
+			/* Discovered ports */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_PORTSTATE_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
+				   &entry->value);
+
+			/* Port ID */
+			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
+					FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN);
+			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
+			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
+			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID,
+				   &entry->type);
+			put_unaligned_be16(len, &entry->len);
+			put_unaligned_be32(fc_host_port_id(lport->host),
+				   &entry->value);
+		}
+
 		break;
 	case FC_FDMI_DPRT:
 		len = sizeof(struct fc_fdmi_dprt);
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 1c7dd35cb7a0..d718a54bb0fb 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -482,10 +482,11 @@  enum fc_host_event_code  {
  * managed by the transport w/o driver interaction.
  */
 
+#define FC_VENDOR_IDENTIFIER	8
 #define FC_FC4_LIST_SIZE		32
 #define FC_SYMBOLIC_NAME_SIZE		256
 #define FC_VERSION_STRING_SIZE		64
-#define FC_SERIAL_NUMBER_SIZE		80
+#define FC_SERIAL_NUMBER_SIZE		64
 
 struct fc_host_attrs {
 	/* Fixed Attributes */
@@ -497,6 +498,10 @@  struct fc_host_attrs {
 	u32 supported_speeds;
 	u32 maxframe_size;
 	u16 max_npiv_vports;
+	u32 max_ct_payload;
+	u32 num_ports;
+	u32 num_discovered_ports;
+	u32 bootbios_state;
 	char serial_number[FC_SERIAL_NUMBER_SIZE];
 	char manufacturer[FC_SERIAL_NUMBER_SIZE];
 	char model[FC_SYMBOLIC_NAME_SIZE];
@@ -505,6 +510,9 @@  struct fc_host_attrs {
 	char driver_version[FC_VERSION_STRING_SIZE];
 	char firmware_version[FC_VERSION_STRING_SIZE];
 	char optionrom_version[FC_VERSION_STRING_SIZE];
+	char vendor_identifier[FC_VENDOR_IDENTIFIER];
+	char bootbios_version[FC_SYMBOLIC_NAME_SIZE];
+
 
 	/* Dynamic Attributes */
 	u32 port_id;
@@ -537,6 +545,9 @@  struct fc_host_attrs {
 
 	/* bsg support */
 	struct request_queue *rqst_q;
+
+	/* FDMI support version*/
+	u8 fdmi_version;
 };
 
 #define shost_to_fc_host(x) \
@@ -616,6 +627,18 @@  struct fc_host_attrs {
 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
 #define fc_host_dev_loss_tmo(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
+#define fc_host_max_ct_payload(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->max_ct_payload)
+#define fc_host_vendor_identifier(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->vendor_identifier)
+#define fc_host_num_discovered_ports(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->num_discovered_ports)
+#define fc_host_num_ports(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->num_ports)
+#define fc_host_bootbios_version(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->bootbios_version)
+#define fc_host_bootbios_state(x)  \
+	(((struct fc_host_attrs *)(x)->shost_data)->bootbios_state)
 
 /* The functions by which the transport class and the driver communicate */
 struct fc_function_template {