OSDN Git Service

qla2xxx: Add FDMI-2 functionality.
authorHimanshu Madhani <himanshu.madhani@qlogic.com>
Thu, 25 Sep 2014 09:16:46 +0000 (05:16 -0400)
committerChristoph Hellwig <hch@lst.de>
Thu, 25 Sep 2014 12:25:02 +0000 (14:25 +0200)
Add support for the FDMI-2 fabric switch feature.

Since FDMI-2 uses code from FDMI-1, some of the existing code
needed to be repaired to prevent fields from being overflowed.

Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_os.c

index 16fe519..868f4e5 100644 (file)
@@ -1014,7 +1014,7 @@ qla2x00_fw_version_show(struct device *dev,
        char fw_str[128];
 
        return scnprintf(buf, PAGE_SIZE, "%s\n",
-           ha->isp_ops->fw_version_str(vha, fw_str));
+           ha->isp_ops->fw_version_str(vha, fw_str, sizeof(fw_str)));
 }
 
 static ssize_t
@@ -1924,7 +1924,8 @@ qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
 {
        scsi_qla_host_t *vha = shost_priv(shost);
 
-       qla2x00_get_sym_node_name(vha, fc_host_symbolic_name(shost));
+       qla2x00_get_sym_node_name(vha, fc_host_symbolic_name(shost),
+           sizeof(fc_host_symbolic_name(shost)));
 }
 
 static void
index d60c1c6..28442d0 100644 (file)
@@ -20,9 +20,9 @@
  * |                              |                    | 0x1115-0x1116  |
  * |                              |                    | 0x111a-0x111b |
  * |                              |                    | 0x1155-0x1158  |
- * | Device Discovery             |       0x2095       | 0x2020-0x2022, |
+ * | Device Discovery             |       0x2016       | 0x2020-0x2022, |
  * |                              |                    | 0x2011-0x2012, |
- * |                              |                    | 0x2016         |
+ * |                              |                    | 0x2099-0x20a4  |
  * | Queue Command and IO tracing |       0x3059       | 0x3006-0x300b  |
  * |                              |                    | 0x3027-0x3028  |
  * |                              |                    | 0x303d-0x3041  |
index de5a9c4..e5baead 100644 (file)
@@ -2056,10 +2056,21 @@ static const char * const port_state_str[] = {
 
 #define CT_REJECT_RESPONSE     0x8001
 #define CT_ACCEPT_RESPONSE     0x8002
-#define CT_REASON_INVALID_COMMAND_CODE 0x01
-#define CT_REASON_CANNOT_PERFORM       0x09
-#define CT_REASON_COMMAND_UNSUPPORTED  0x0b
-#define CT_EXPL_ALREADY_REGISTERED     0x10
+#define CT_REASON_INVALID_COMMAND_CODE         0x01
+#define CT_REASON_CANNOT_PERFORM               0x09
+#define CT_REASON_COMMAND_UNSUPPORTED          0x0b
+#define CT_EXPL_ALREADY_REGISTERED             0x10
+#define CT_EXPL_HBA_ATTR_NOT_REGISTERED                0x11
+#define CT_EXPL_MULTIPLE_HBA_ATTR              0x12
+#define CT_EXPL_INVALID_HBA_BLOCK_LENGTH       0x13
+#define CT_EXPL_MISSING_REQ_HBA_ATTR           0x14
+#define CT_EXPL_PORT_NOT_REGISTERED_           0x15
+#define CT_EXPL_MISSING_HBA_ID_PORT_LIST       0x16
+#define CT_EXPL_HBA_NOT_REGISTERED             0x17
+#define CT_EXPL_PORT_ATTR_NOT_REGISTERED       0x20
+#define CT_EXPL_PORT_NOT_REGISTERED            0x21
+#define CT_EXPL_MULTIPLE_PORT_ATTR             0x22
+#define CT_EXPL_INVALID_PORT_BLOCK_LENGTH      0x23
 
 #define NS_N_PORT_TYPE 0x01
 #define NS_NL_PORT_TYPE        0x02
@@ -2116,33 +2127,40 @@ static const char * const port_state_str[] = {
  * HBA attribute types.
  */
 #define FDMI_HBA_ATTR_COUNT                    9
-#define FDMI_HBA_NODE_NAME                     1
-#define FDMI_HBA_MANUFACTURER                  2
-#define FDMI_HBA_SERIAL_NUMBER                 3
-#define FDMI_HBA_MODEL                         4
-#define FDMI_HBA_MODEL_DESCRIPTION             5
-#define FDMI_HBA_HARDWARE_VERSION              6
-#define FDMI_HBA_DRIVER_VERSION                        7
-#define FDMI_HBA_OPTION_ROM_VERSION            8
-#define FDMI_HBA_FIRMWARE_VERSION              9
+#define FDMIV2_HBA_ATTR_COUNT                  17
+#define FDMI_HBA_NODE_NAME                     0x1
+#define FDMI_HBA_MANUFACTURER                  0x2
+#define FDMI_HBA_SERIAL_NUMBER                 0x3
+#define FDMI_HBA_MODEL                         0x4
+#define FDMI_HBA_MODEL_DESCRIPTION             0x5
+#define FDMI_HBA_HARDWARE_VERSION              0x6
+#define FDMI_HBA_DRIVER_VERSION                        0x7
+#define FDMI_HBA_OPTION_ROM_VERSION            0x8
+#define FDMI_HBA_FIRMWARE_VERSION              0x9
 #define FDMI_HBA_OS_NAME_AND_VERSION           0xa
 #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH     0xb
+#define FDMI_HBA_NODE_SYMBOLIC_NAME            0xc
+#define FDMI_HBA_VENDOR_ID                     0xd
+#define FDMI_HBA_NUM_PORTS                     0xe
+#define FDMI_HBA_FABRIC_NAME                   0xf
+#define FDMI_HBA_BOOT_BIOS_NAME                        0x10
+#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER                0xe0
 
 struct ct_fdmi_hba_attr {
        uint16_t type;
        uint16_t len;
        union {
                uint8_t node_name[WWN_SIZE];
-               uint8_t manufacturer[32];
-               uint8_t serial_num[8];
+               uint8_t manufacturer[64];
+               uint8_t serial_num[32];
                uint8_t model[16];
                uint8_t model_desc[80];
-               uint8_t hw_version[16];
+               uint8_t hw_version[32];
                uint8_t driver_version[32];
                uint8_t orom_version[16];
-               uint8_t fw_version[16];
+               uint8_t fw_version[32];
                uint8_t os_version[128];
-               uint8_t max_ct_len[4];
+               uint32_t max_ct_len;
        } a;
 };
 
@@ -2151,16 +2169,56 @@ struct ct_fdmi_hba_attributes {
        struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT];
 };
 
+struct ct_fdmiv2_hba_attr {
+       uint16_t type;
+       uint16_t len;
+       union {
+               uint8_t node_name[WWN_SIZE];
+               uint8_t manufacturer[32];
+               uint8_t serial_num[32];
+               uint8_t model[16];
+               uint8_t model_desc[80];
+               uint8_t hw_version[16];
+               uint8_t driver_version[32];
+               uint8_t orom_version[16];
+               uint8_t fw_version[32];
+               uint8_t os_version[128];
+               uint32_t max_ct_len;
+               uint8_t sym_name[256];
+               uint32_t vendor_id;
+               uint32_t num_ports;
+               uint8_t fabric_name[WWN_SIZE];
+               uint8_t bios_name[32];
+               uint8_t vendor_indentifer[8];
+       } a;
+};
+
+struct ct_fdmiv2_hba_attributes {
+       uint32_t count;
+       struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT];
+};
+
 /*
  * Port attribute types.
  */
 #define FDMI_PORT_ATTR_COUNT           6
-#define FDMI_PORT_FC4_TYPES            1
-#define FDMI_PORT_SUPPORT_SPEED                2
-#define FDMI_PORT_CURRENT_SPEED                3
-#define FDMI_PORT_MAX_FRAME_SIZE       4
-#define FDMI_PORT_OS_DEVICE_NAME       5
-#define FDMI_PORT_HOST_NAME            6
+#define FDMIV2_PORT_ATTR_COUNT         16
+#define FDMI_PORT_FC4_TYPES            0x1
+#define FDMI_PORT_SUPPORT_SPEED                0x2
+#define FDMI_PORT_CURRENT_SPEED                0x3
+#define FDMI_PORT_MAX_FRAME_SIZE       0x4
+#define FDMI_PORT_OS_DEVICE_NAME       0x5
+#define FDMI_PORT_HOST_NAME            0x6
+#define FDMI_PORT_NODE_NAME            0x7
+#define FDMI_PORT_NAME                 0x8
+#define FDMI_PORT_SYM_NAME             0x9
+#define FDMI_PORT_TYPE                 0xa
+#define FDMI_PORT_SUPP_COS             0xb
+#define FDMI_PORT_FABRIC_NAME          0xc
+#define FDMI_PORT_FC4_TYPE             0xd
+#define FDMI_PORT_STATE                        0x101
+#define FDMI_PORT_COUNT                        0x102
+#define FDMI_PORT_ID                   0x103
 
 #define FDMI_PORT_SPEED_1GB            0x1
 #define FDMI_PORT_SPEED_2GB            0x2
@@ -2171,7 +2229,11 @@ struct ct_fdmi_hba_attributes {
 #define FDMI_PORT_SPEED_32GB           0x40
 #define FDMI_PORT_SPEED_UNKNOWN                0x8000
 
-struct ct_fdmi_port_attr {
+#define FC_CLASS_2     0x04
+#define FC_CLASS_3     0x08
+#define FC_CLASS_2_3   0x0C
+
+struct ct_fdmiv2_port_attr {
        uint16_t type;
        uint16_t len;
        union {
@@ -2181,12 +2243,40 @@ struct ct_fdmi_port_attr {
                uint32_t max_frame_size;
                uint8_t os_dev_name[32];
                uint8_t host_name[32];
+               uint8_t node_name[WWN_SIZE];
+               uint8_t port_name[WWN_SIZE];
+               uint8_t port_sym_name[128];
+               uint32_t port_type;
+               uint32_t port_supported_cos;
+               uint8_t fabric_name[WWN_SIZE];
+               uint8_t port_fc4_type[32];
+               uint32_t port_state;
+               uint32_t num_ports;
+               uint32_t port_id;
        } a;
 };
 
 /*
  * Port Attribute Block.
  */
+struct ct_fdmiv2_port_attributes {
+       uint32_t count;
+       struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT];
+};
+
+struct ct_fdmi_port_attr {
+       uint16_t type;
+       uint16_t len;
+       union {
+               uint8_t fc4_types[32];
+               uint32_t sup_speed;
+               uint32_t cur_speed;
+               uint32_t max_frame_size;
+               uint8_t os_dev_name[32];
+               uint8_t host_name[32];
+       } a;
+};
+
 struct ct_fdmi_port_attributes {
        uint32_t count;
        struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT];
@@ -2286,6 +2376,13 @@ struct ct_sns_req {
 
                struct {
                        uint8_t hba_identifier[8];
+                       uint32_t entry_count;
+                       uint8_t port_name[8];
+                       struct ct_fdmiv2_hba_attributes attrs;
+               } rhba2;
+
+               struct {
+                       uint8_t hba_identifier[8];
                        struct ct_fdmi_hba_attributes attrs;
                } rhat;
 
@@ -2296,6 +2393,11 @@ struct ct_sns_req {
 
                struct {
                        uint8_t port_name[8];
+                       struct ct_fdmiv2_port_attributes attrs;
+               } rpa2;
+
+               struct {
+                       uint8_t port_name[8];
                } dhba;
 
                struct {
@@ -2522,7 +2624,7 @@ struct isp_operations {
        int (*load_risc) (struct scsi_qla_host *, uint32_t *);
 
        char * (*pci_info_str) (struct scsi_qla_host *, char *);
-       char * (*fw_version_str) (struct scsi_qla_host *, char *);
+       char * (*fw_version_str)(struct scsi_qla_host *, char *, size_t);
 
        irq_handler_t intr_handler;
        void (*enable_intrs) (struct qla_hw_data *);
index 43ef0db..0f851de 100644 (file)
@@ -562,7 +562,7 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
 extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
-extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
+extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
@@ -614,7 +614,7 @@ extern void qlafx00_soft_reset(scsi_qla_host_t *);
 extern int qlafx00_chip_diag(scsi_qla_host_t *);
 extern void qlafx00_config_rings(struct scsi_qla_host *);
 extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *);
-extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *);
+extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *, size_t);
 extern irqreturn_t qlafx00_intr_handler(int, void *);
 extern void qlafx00_enable_intrs(struct qla_hw_data *);
 extern void qlafx00_disable_intrs(struct qla_hw_data *);
index a0df3b1..dccc4dc 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include "qla_def.h"
 #include "qla_target.h"
+#include <linux/utsname.h>
 
 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
@@ -143,10 +144,10 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
                        if (ct_rsp->header.response !=
                            __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
                                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
-                                   "%s failed rejected request on port_id: "
-                                   "%02x%02x%02x.\n", routine,
-                                   vha->d_id.b.domain, vha->d_id.b.area,
-                                   vha->d_id.b.al_pa);
+                                   "%s failed rejected request on port_id: %02x%02x%02x Compeltion status 0x%x, response 0x%x\n",
+                                   routine, vha->d_id.b.domain,
+                                   vha->d_id.b.area, vha->d_id.b.al_pa,
+                                   comp_status, ct_rsp->header.response);
                                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
                                    0x2078, (uint8_t *)&ct_rsp->header,
                                    sizeof(struct ct_rsp_hdr));
@@ -622,15 +623,16 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
 }
 
 void
-qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
+qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
 {
        struct qla_hw_data *ha = vha->hw;
 
        if (IS_QLAFX00(ha))
-               sprintf(snn, "%s FW:v%s DVR:v%s", ha->model_number,
+               snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number,
                    ha->mr.fw_version, qla2x00_version_str);
        else
-               sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
+               snprintf(snn, size,
+                   "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
                    ha->fw_major_version, ha->fw_minor_version,
                    ha->fw_subminor_version, qla2x00_version_str);
 }
@@ -670,7 +672,8 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
        memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
 
        /* Prepare the Symbolic Node Name */
-       qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
+       qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
+           sizeof(ct_req->req.rsnn_nn.sym_node_name));
 
        /* Calculate SNN length */
        ct_req->req.rsnn_nn.name_len =
@@ -1263,7 +1266,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        ms_iocb_entry_t *ms_pkt;
        struct ct_sns_req *ct_req;
        struct ct_sns_rsp *ct_rsp;
-       uint8_t *entries;
+       void *entries;
        struct ct_fdmi_hba_attr *eiter;
        struct qla_hw_data *ha = vha->hw;
 
@@ -1288,7 +1291,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        entries = ct_req->req.rhba.hba_identifier;
 
        /* Nodename. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
        eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
@@ -1298,11 +1301,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "NodeName = %8phN.\n", eiter->a.node_name);
 
        /* Manufacturer. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
        alen = strlen(QLA2XXX_MANUFACTURER);
-       strncpy(eiter->a.manufacturer, QLA2XXX_MANUFACTURER, alen + 1);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
+           "%s", "QLogic Corporation");
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1310,12 +1314,19 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Manufacturer = %s.\n", eiter->a.manufacturer);
 
        /* Serial number. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
-       sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
-       sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
+       if (IS_FWI2_CAPABLE(ha))
+               qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
+                   sizeof(eiter->a.serial_num));
+       else {
+               sn = ((ha->serial0 & 0x1f) << 16) |
+                       (ha->serial2 << 8) | ha->serial1;
+               snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
+                   "%c%05d", 'A' + sn / 100000, sn % 100000);
+       }
        alen = strlen(eiter->a.serial_num);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1323,11 +1334,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Serial no. = %s.\n", eiter->a.serial_num);
 
        /* Model name. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
-       strcpy(eiter->a.model, ha->model_number);
+       snprintf(eiter->a.model, sizeof(eiter->a.model),
+           "%s", ha->model_number);
        alen = strlen(eiter->a.model);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1335,11 +1347,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Model Name = %s.\n", eiter->a.model);
 
        /* Model description. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
-       strncpy(eiter->a.model_desc, ha->model_desc, 80);
+       snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
+           "%s", ha->model_desc);
        alen = strlen(eiter->a.model_desc);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1347,11 +1360,23 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Model Desc = %s.\n", eiter->a.model_desc);
 
        /* Hardware version. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
-       strcpy(eiter->a.hw_version, ha->adapter_id);
+       if (!IS_FWI2_CAPABLE(ha)) {
+               snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
+                   "HW:%s", ha->adapter_id);
+       } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
+                   sizeof(eiter->a.hw_version))) {
+               ;
+       } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
+                   sizeof(eiter->a.hw_version))) {
+               ;
+       } else {
+               snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
+                   "HW:%s", ha->adapter_id);
+       }
        alen = strlen(eiter->a.hw_version);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1359,11 +1384,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Hardware ver = %s.\n", eiter->a.hw_version);
 
        /* Driver version. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
-       strcpy(eiter->a.driver_version, qla2x00_version_str);
+       snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
+           "%s", qla2x00_version_str);
        alen = strlen(eiter->a.driver_version);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1371,11 +1397,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Driver ver = %s.\n", eiter->a.driver_version);
 
        /* Option ROM version. */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
-       strcpy(eiter->a.orom_version, "0.00");
+       snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
+           "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
        alen = strlen(eiter->a.orom_version);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1383,11 +1410,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
            "Optrom vers = %s.\n", eiter->a.orom_version);
 
        /* Firmware version */
-       eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+       eiter = entries + size;
        eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
-       ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
+       ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
+           sizeof(eiter->a.fw_version));
        alen = strlen(eiter->a.fw_version);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
@@ -1419,6 +1447,11 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
                        ql_dbg(ql_dbg_disc, vha, 0x2034,
                            "HBA already registered.\n");
                        rval = QLA_ALREADY_REGISTERED;
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0x20ad,
+                           "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
+                           ct_rsp->header.reason_code,
+                           ct_rsp->header.explanation_code);
                }
        } else {
                ql_dbg(ql_dbg_disc, vha, 0x2035,
@@ -1429,6 +1462,534 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
 }
 
 /**
+ * qla2x00_fdmi_rpa() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
+{
+       int rval, alen;
+       uint32_t size;
+       struct qla_hw_data *ha = vha->hw;
+       ms_iocb_entry_t *ms_pkt;
+       struct ct_sns_req *ct_req;
+       struct ct_sns_rsp *ct_rsp;
+       void *entries;
+       struct ct_fdmi_port_attr *eiter;
+       struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+       struct new_utsname *p_sysid = NULL;
+
+       /* Issue RPA */
+       /* Prepare common MS IOCB */
+       /*   Request size adjusted after CT preparation */
+       ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
+
+       /* Prepare CT request */
+       ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD,
+           RPA_RSP_SIZE);
+       ct_rsp = &ha->ct_sns->p.rsp;
+
+       /* Prepare FDMI command arguments -- attribute block, attributes. */
+       memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
+       size = WWN_SIZE + 4;
+
+       /* Attributes */
+       ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
+       entries = ct_req->req.rpa.port_name;
+
+       /* FC4 types. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
+       eiter->len = cpu_to_be16(4 + 32);
+       eiter->a.fc4_types[2] = 0x01;
+       size += 4 + 32;
+
+       ql_dbg(ql_dbg_disc, vha, 0x2039,
+           "FC4_TYPES=%02x %02x.\n",
+           eiter->a.fc4_types[2],
+           eiter->a.fc4_types[1]);
+
+       /* Supported speed. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+       eiter->len = cpu_to_be16(4 + 4);
+       if (IS_CNA_CAPABLE(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_10GB);
+       else if (IS_QLA27XX(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_32GB|
+                   FDMI_PORT_SPEED_16GB|
+                   FDMI_PORT_SPEED_8GB);
+       else if (IS_QLA2031(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_16GB|
+                   FDMI_PORT_SPEED_8GB|
+                   FDMI_PORT_SPEED_4GB);
+       else if (IS_QLA25XX(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_8GB|
+                   FDMI_PORT_SPEED_4GB|
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
+       else if (IS_QLA24XX_TYPE(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_4GB|
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
+       else if (IS_QLA23XX(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
+       else
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_1GB);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x203a,
+           "Supported_Speed=%x.\n", eiter->a.sup_speed);
+
+       /* Current speed. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+       eiter->len = cpu_to_be16(4 + 4);
+       switch (ha->link_data_rate) {
+       case PORT_SPEED_1GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_1GB);
+               break;
+       case PORT_SPEED_2GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_2GB);
+               break;
+       case PORT_SPEED_4GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_4GB);
+               break;
+       case PORT_SPEED_8GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_8GB);
+               break;
+       case PORT_SPEED_10GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_10GB);
+               break;
+       case PORT_SPEED_16GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_16GB);
+               break;
+       case PORT_SPEED_32GB:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_32GB);
+               break;
+       default:
+               eiter->a.cur_speed =
+                   cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
+               break;
+       }
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x203b,
+           "Current_Speed=%x.\n", eiter->a.cur_speed);
+
+       /* Max frame size. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+       eiter->len = cpu_to_be16(4 + 4);
+       eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
+           le16_to_cpu(icb24->frame_payload_size) :
+           le16_to_cpu(ha->init_cb->frame_payload_size);
+       eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x203c,
+           "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
+
+       /* OS device name. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+       snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
+           "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
+       alen = strlen(eiter->a.os_dev_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x204b,
+           "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
+
+       /* Hostname. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
+       p_sysid = utsname();
+       if (p_sysid) {
+               snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
+                   "%s", p_sysid->nodename);
+       } else {
+               snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
+                   "%s", fc_host_system_hostname(vha->host));
+       }
+       alen = strlen(eiter->a.host_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
+
+       /* Update MS request size. */
+       qla2x00_update_ms_fdmi_iocb(vha, size + 16);
+
+       ql_dbg(ql_dbg_disc, vha, 0x203e,
+           "RPA portname  %016llx, size = %d.\n",
+           wwn_to_u64(ct_req->req.rpa.port_name), size);
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
+           entries, size);
+
+       /* Execute MS IOCB */
+       rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
+           sizeof(ms_iocb_entry_t));
+       if (rval != QLA_SUCCESS) {
+               /*EMPTY*/
+               ql_dbg(ql_dbg_disc, vha, 0x2040,
+                   "RPA issue IOCB failed (%d).\n", rval);
+       } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
+           QLA_SUCCESS) {
+               rval = QLA_FUNCTION_FAILED;
+               if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+                   ct_rsp->header.explanation_code ==
+                   CT_EXPL_ALREADY_REGISTERED) {
+                       ql_dbg(ql_dbg_disc, vha, 0x20cd,
+                           "RPA already registered.\n");
+                       rval = QLA_ALREADY_REGISTERED;
+               }
+
+       } else {
+               ql_dbg(ql_dbg_disc, vha, 0x2041,
+                   "RPA exiting normally.\n");
+       }
+
+       return rval;
+}
+
+/**
+ * qla2x00_fdmiv2_rhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
+{
+       int rval, alen;
+       uint32_t size, sn;
+       ms_iocb_entry_t *ms_pkt;
+       struct ct_sns_req *ct_req;
+       struct ct_sns_rsp *ct_rsp;
+       void *entries;
+       struct ct_fdmiv2_hba_attr *eiter;
+       struct qla_hw_data *ha = vha->hw;
+       struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+       struct new_utsname *p_sysid = NULL;
+
+       /* Issue RHBA */
+       /* Prepare common MS IOCB */
+       /*   Request size adjusted after CT preparation */
+       ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
+
+       /* Prepare CT request */
+       ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD,
+           RHBA_RSP_SIZE);
+       ct_rsp = &ha->ct_sns->p.rsp;
+
+       /* Prepare FDMI command arguments -- attribute block, attributes. */
+       memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE);
+       ct_req->req.rhba2.entry_count = cpu_to_be32(1);
+       memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE);
+       size = 2 * WWN_SIZE + 4 + 4;
+
+       /* Attributes */
+       ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
+       entries = ct_req->req.rhba2.hba_identifier;
+
+       /* Nodename. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
+       eiter->len = cpu_to_be16(4 + WWN_SIZE);
+       memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
+       size += 4 + WWN_SIZE;
+
+       ql_dbg(ql_dbg_disc, vha, 0x207d,
+           "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name));
+
+       /* Manufacturer. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
+       snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
+           "%s", "QLogic Corporation");
+       eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0';
+       alen = strlen(eiter->a.manufacturer);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20a5,
+           "Manufacturer = %s.\n", eiter->a.manufacturer);
+
+       /* Serial number. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
+       if (IS_FWI2_CAPABLE(ha))
+               qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
+                   sizeof(eiter->a.serial_num));
+       else {
+               sn = ((ha->serial0 & 0x1f) << 16) |
+                       (ha->serial2 << 8) | ha->serial1;
+               snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
+                   "%c%05d", 'A' + sn / 100000, sn % 100000);
+       }
+       alen = strlen(eiter->a.serial_num);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20a6,
+           "Serial no. = %s.\n", eiter->a.serial_num);
+
+       /* Model name. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
+       snprintf(eiter->a.model, sizeof(eiter->a.model),
+           "%s", ha->model_number);
+       alen = strlen(eiter->a.model);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20a7,
+           "Model Name = %s.\n", eiter->a.model);
+
+       /* Model description. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
+       snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
+           "%s", ha->model_desc);
+       alen = strlen(eiter->a.model_desc);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20a8,
+           "Model Desc = %s.\n", eiter->a.model_desc);
+
+       /* Hardware version. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
+       if (!IS_FWI2_CAPABLE(ha)) {
+               snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
+                   "HW:%s", ha->adapter_id);
+       } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
+                   sizeof(eiter->a.hw_version))) {
+               ;
+       } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
+                   sizeof(eiter->a.hw_version))) {
+               ;
+       } else {
+               snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
+                   "HW:%s", ha->adapter_id);
+       }
+       alen = strlen(eiter->a.hw_version);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20a9,
+           "Hardware ver = %s.\n", eiter->a.hw_version);
+
+       /* Driver version. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
+       snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
+           "%s", qla2x00_version_str);
+       alen = strlen(eiter->a.driver_version);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20aa,
+           "Driver ver = %s.\n", eiter->a.driver_version);
+
+       /* Option ROM version. */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
+       snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
+           "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
+       alen = strlen(eiter->a.orom_version);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha , 0x20ab,
+           "Optrom version = %d.%02d.\n", eiter->a.orom_version[1],
+           eiter->a.orom_version[0]);
+
+       /* Firmware version */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
+       ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
+           sizeof(eiter->a.fw_version));
+       alen = strlen(eiter->a.fw_version);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20ac,
+           "Firmware vers = %s.\n", eiter->a.fw_version);
+
+       /* OS Name and Version */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
+       p_sysid = utsname();
+       if (p_sysid) {
+               snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
+                   "%s %s %s",
+                   p_sysid->sysname, p_sysid->release, p_sysid->version);
+       } else {
+               snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
+                   "%s %s", "Linux", fc_host_system_hostname(vha->host));
+       }
+       alen = strlen(eiter->a.os_version);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20ae,
+           "OS Name and Version = %s.\n", eiter->a.os_version);
+
+       /* MAX CT Payload Length */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
+       eiter->a.max_ct_len = IS_FWI2_CAPABLE(ha) ?
+           le16_to_cpu(icb24->frame_payload_size) :
+           le16_to_cpu(ha->init_cb->frame_payload_size);
+       eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20af,
+           "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len);
+
+       /* Node Sybolic Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
+       qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
+           sizeof(eiter->a.sym_name));
+       alen = strlen(eiter->a.sym_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b0,
+           "Symbolic Name = %s.\n", eiter->a.sym_name);
+
+       /* Vendor Id */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID);
+       eiter->a.vendor_id = cpu_to_be32(0x1077);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b1,
+           "Vendor Id = %x.\n", eiter->a.vendor_id);
+
+       /* Num Ports */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
+       eiter->a.num_ports = cpu_to_be32(1);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b2,
+           "Port Num = %x.\n", eiter->a.num_ports);
+
+       /* Fabric Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
+       memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
+       eiter->len = cpu_to_be16(4 + WWN_SIZE);
+       size += 4 + WWN_SIZE;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b3,
+           "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
+
+       /* BIOS Version */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
+       snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name),
+           "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
+       alen = strlen(eiter->a.bios_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b4,
+           "BIOS Name = %s\n", eiter->a.bios_name);
+
+       /* Vendor Identifier */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
+       snprintf(eiter->a.vendor_indentifer, sizeof(eiter->a.vendor_indentifer),
+           "%s", "QLGC");
+       alen = strlen(eiter->a.vendor_indentifer);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b1,
+           "Vendor Identifier = %s.\n", eiter->a.vendor_indentifer);
+
+       /* Update MS request size. */
+       qla2x00_update_ms_fdmi_iocb(vha, size + 16);
+
+       ql_dbg(ql_dbg_disc, vha, 0x20b5,
+           "RHBA identifier = %016llx.\n",
+           wwn_to_u64(ct_req->req.rhba2.hba_identifier));
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6,
+           entries, size);
+
+       /* Execute MS IOCB */
+       rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
+           sizeof(ms_iocb_entry_t));
+       if (rval != QLA_SUCCESS) {
+               /*EMPTY*/
+               ql_dbg(ql_dbg_disc, vha, 0x20b7,
+                   "RHBA issue IOCB failed (%d).\n", rval);
+       } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
+           QLA_SUCCESS) {
+               rval = QLA_FUNCTION_FAILED;
+
+               if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+                   ct_rsp->header.explanation_code ==
+                   CT_EXPL_ALREADY_REGISTERED) {
+                       ql_dbg(ql_dbg_disc, vha, 0x20b8,
+                           "HBA already registered.\n");
+                       rval = QLA_ALREADY_REGISTERED;
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0x2016,
+                           "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
+                           ct_rsp->header.reason_code,
+                           ct_rsp->header.explanation_code);
+               }
+       } else {
+               ql_dbg(ql_dbg_disc, vha, 0x20b9,
+                   "RHBA FDMI V2 exiting normally.\n");
+       }
+
+       return rval;
+}
+
+/**
  * qla2x00_fdmi_dhba() -
  * @ha: HA context
  *
@@ -1477,23 +2038,24 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
 }
 
 /**
- * qla2x00_fdmi_rpa() -
+ * qla2x00_fdmiv2_rpa() -
  * @ha: HA context
  *
  * Returns 0 on success.
  */
 static int
-qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
+qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
 {
        int rval, alen;
-       uint32_t size, max_frame_size;
+       uint32_t size;
        struct qla_hw_data *ha = vha->hw;
        ms_iocb_entry_t *ms_pkt;
        struct ct_sns_req *ct_req;
        struct ct_sns_rsp *ct_rsp;
-       uint8_t *entries;
-       struct ct_fdmi_port_attr *eiter;
+       void *entries;
+       struct ct_fdmiv2_port_attr *eiter;
        struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+       struct new_utsname *p_sysid = NULL;
 
        /* Issue RPA */
        /* Prepare common MS IOCB */
@@ -1505,147 +2067,258 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
        ct_rsp = &ha->ct_sns->p.rsp;
 
        /* Prepare FDMI command arguments -- attribute block, attributes. */
-       memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
+       memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE);
        size = WWN_SIZE + 4;
 
        /* Attributes */
-       ct_req->req.rpa.attrs.count =
-           __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
-       entries = ct_req->req.rpa.port_name;
+       ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
+       entries = ct_req->req.rpa2.port_name;
 
        /* FC4 types. */
-       eiter = (struct ct_fdmi_port_attr *) (entries + size);
-       eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
-       eiter->len = __constant_cpu_to_be16(4 + 32);
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
+       eiter->len = cpu_to_be16(4 + 32);
        eiter->a.fc4_types[2] = 0x01;
        size += 4 + 32;
 
-       ql_dbg(ql_dbg_disc, vha, 0x2039,
+       ql_dbg(ql_dbg_disc, vha, 0x20ba,
            "FC4_TYPES=%02x %02x.\n",
            eiter->a.fc4_types[2],
            eiter->a.fc4_types[1]);
 
        /* Supported speed. */
-       eiter = (struct ct_fdmi_port_attr *) (entries + size);
-       eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
-       eiter->len = __constant_cpu_to_be16(4 + 4);
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+       eiter->len = cpu_to_be16(4 + 4);
        if (IS_CNA_CAPABLE(ha))
-               eiter->a.sup_speed = __constant_cpu_to_be32(
+               eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_10GB);
        else if (IS_QLA27XX(ha))
-               eiter->a.sup_speed = __constant_cpu_to_be32(
-                   FDMI_PORT_SPEED_32GB|FDMI_PORT_SPEED_16GB|
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_32GB|
+                   FDMI_PORT_SPEED_16GB|
                    FDMI_PORT_SPEED_8GB);
+       else if (IS_QLA2031(ha))
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_16GB|
+                   FDMI_PORT_SPEED_8GB|
+                   FDMI_PORT_SPEED_4GB);
        else if (IS_QLA25XX(ha))
-               eiter->a.sup_speed = __constant_cpu_to_be32(
-                   FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
-                   FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_8GB|
+                   FDMI_PORT_SPEED_4GB|
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
        else if (IS_QLA24XX_TYPE(ha))
-               eiter->a.sup_speed = __constant_cpu_to_be32(
-                   FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
-                   FDMI_PORT_SPEED_4GB);
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_4GB|
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
        else if (IS_QLA23XX(ha))
-               eiter->a.sup_speed =__constant_cpu_to_be32(
-                   FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
+               eiter->a.sup_speed = cpu_to_be32(
+                   FDMI_PORT_SPEED_2GB|
+                   FDMI_PORT_SPEED_1GB);
        else
-               eiter->a.sup_speed = __constant_cpu_to_be32(
+               eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_1GB);
        size += 4 + 4;
 
-       ql_dbg(ql_dbg_disc, vha, 0x203a,
-           "Supported_Speed=%x.\n", eiter->a.sup_speed);
+       ql_dbg(ql_dbg_disc, vha, 0x20bb,
+           "Supported Port Speed = %x.\n", eiter->a.sup_speed);
 
        /* Current speed. */
-       eiter = (struct ct_fdmi_port_attr *) (entries + size);
-       eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
-       eiter->len = __constant_cpu_to_be16(4 + 4);
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+       eiter->len = cpu_to_be16(4 + 4);
        switch (ha->link_data_rate) {
        case PORT_SPEED_1GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB);
                break;
        case PORT_SPEED_2GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB);
                break;
        case PORT_SPEED_4GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB);
                break;
        case PORT_SPEED_8GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB);
                break;
        case PORT_SPEED_10GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB);
                break;
        case PORT_SPEED_16GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB);
                break;
        case PORT_SPEED_32GB:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_32GB);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB);
                break;
        default:
-               eiter->a.cur_speed =
-                   __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
+               eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
                break;
        }
        size += 4 + 4;
 
-       ql_dbg(ql_dbg_disc, vha, 0x203b,
-           "Current_Speed=%x.\n", eiter->a.cur_speed);
+       ql_dbg(ql_dbg_disc, vha, 0x20bc,
+           "Current_Speed = %x.\n", eiter->a.cur_speed);
 
        /* Max frame size. */
-       eiter = (struct ct_fdmi_port_attr *) (entries + size);
-       eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
-       eiter->len = __constant_cpu_to_be16(4 + 4);
-       max_frame_size = IS_FWI2_CAPABLE(ha) ?
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+       eiter->len = cpu_to_be16(4 + 4);
+       eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
            le16_to_cpu(icb24->frame_payload_size):
            le16_to_cpu(ha->init_cb->frame_payload_size);
-       eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
+       eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
        size += 4 + 4;
 
-       ql_dbg(ql_dbg_disc, vha, 0x203c,
-           "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
+       ql_dbg(ql_dbg_disc, vha, 0x20bc,
+           "Max_Frame_Size = %x.\n", eiter->a.max_frame_size);
 
        /* OS device name. */
-       eiter = (struct ct_fdmi_port_attr *) (entries + size);
-       eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
        alen = strlen(QLA2XXX_DRIVER_NAME);
-       strncpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME, alen + 1);
-       alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+       snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
+           "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
+       alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       ql_dbg(ql_dbg_disc, vha, 0x204b,
-           "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
+       ql_dbg(ql_dbg_disc, vha, 0x20be,
+           "OS_Device_Name = %s.\n", eiter->a.os_dev_name);
 
        /* Hostname. */
-       if (strlen(fc_host_system_hostname(vha->host))) {
-               ct_req->req.rpa.attrs.count =
-                   __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
-               eiter = (struct ct_fdmi_port_attr *) (entries + size);
-               eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
+       p_sysid = utsname();
+       if (p_sysid) {
+               snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
+                   "%s", p_sysid->nodename);
+       } else {
                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
                    "%s", fc_host_system_hostname(vha->host));
-               alen = strlen(eiter->a.host_name);
-               alen += (alen & 3) ? (4 - (alen & 3)) : 4;
-               eiter->len = cpu_to_be16(4 + alen);
-               size += 4 + alen;
-
-               ql_dbg(ql_dbg_disc, vha, 0x203d,
-                   "HostName=%s.\n", eiter->a.host_name);
        }
+       alen = strlen(eiter->a.host_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x203d,
+           "HostName=%s.\n", eiter->a.host_name);
+
+       /* Node Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
+       memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
+       eiter->len = cpu_to_be16(4 + WWN_SIZE);
+       size += 4 + WWN_SIZE;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c0,
+           "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name));
+
+       /* Port Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_NAME);
+       memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE);
+       eiter->len = cpu_to_be16(4 + WWN_SIZE);
+       size += 4 + WWN_SIZE;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c1,
+           "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name));
+
+       /* Port Symbolic Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
+       qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
+           sizeof(eiter->a.port_sym_name));
+       alen = strlen(eiter->a.port_sym_name);
+       alen += 4 - (alen & 3);
+       eiter->len = cpu_to_be16(4 + alen);
+       size += 4 + alen;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c2,
+           "port symbolic name = %s\n", eiter->a.port_sym_name);
+
+       /* Port Type */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
+       eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c3,
+           "Port Type = %x.\n", eiter->a.port_type);
+
+       /* Class of Service  */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
+       eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c4,
+           "Supported COS = %08x\n", eiter->a.port_supported_cos);
+
+       /* Port Fabric Name */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
+       memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
+       eiter->len = cpu_to_be16(4 + WWN_SIZE);
+       size += 4 + WWN_SIZE;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c5,
+           "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
+
+       /* FC4_type */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
+       eiter->a.port_fc4_type[0] = 0;
+       eiter->a.port_fc4_type[1] = 0;
+       eiter->a.port_fc4_type[2] = 1;
+       eiter->a.port_fc4_type[3] = 0;
+       eiter->len = cpu_to_be16(4 + 32);
+       size += 4 + 32;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c6,
+           "Port Active FC4 Type = %02x %02x.\n",
+           eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
+
+       /* Port State */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_STATE);
+       eiter->a.port_state = cpu_to_be32(1);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c7,
+           "Port State = %x.\n", eiter->a.port_state);
+
+       /* Number of Ports */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
+       eiter->a.num_ports = cpu_to_be32(1);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c8,
+           "Number of ports = %x.\n", eiter->a.num_ports);
+
+       /* Port Id */
+       eiter = entries + size;
+       eiter->type = cpu_to_be16(FDMI_PORT_ID);
+       eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
+       eiter->len = cpu_to_be16(4 + 4);
+       size += 4 + 4;
+
+       ql_dbg(ql_dbg_disc, vha, 0x20c8,
+           "Port Id = %x.\n", eiter->a.port_id);
 
        /* Update MS request size. */
        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
 
        ql_dbg(ql_dbg_disc, vha, 0x203e,
            "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
-       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
            entries, size);
 
        /* Execute MS IOCB */
@@ -1653,14 +2326,26 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               ql_dbg(ql_dbg_disc, vha, 0x2040,
-                   "RPA issue IOCB failed (%d).\n", rval);
+               ql_dbg(ql_dbg_disc, vha, 0x20cb,
+                   "RPA FDMI v2 issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
+               if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+                   ct_rsp->header.explanation_code ==
+                   CT_EXPL_ALREADY_REGISTERED) {
+                       ql_dbg(ql_dbg_disc, vha, 0x20ce,
+                           "RPA FDMI v2 already registered\n");
+                       rval = QLA_ALREADY_REGISTERED;
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0x2020,
+                           "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
+                           ct_rsp->header.reason_code,
+                           ct_rsp->header.explanation_code);
+               }
        } else {
-               ql_dbg(ql_dbg_disc, vha, 0x2041,
-                   "RPA exiting nornally.\n");
+               ql_dbg(ql_dbg_disc, vha, 0x20cc,
+                   "RPA FDMI V2 exiting normally.\n");
        }
 
        return rval;
@@ -1675,8 +2360,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
 int
 qla2x00_fdmi_register(scsi_qla_host_t *vha)
 {
-       int rval;
-       struct qla_hw_data *ha = vha->hw;
+       int rval = QLA_FUNCTION_FAILED;
+       struct qla_hw_data *ha = vha->hw;
 
        if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
            IS_QLAFX00(ha))
@@ -1686,6 +2371,26 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha)
        if (rval)
                return rval;
 
+       rval = qla2x00_fdmiv2_rhba(vha);
+       if (rval) {
+               if (rval != QLA_ALREADY_REGISTERED)
+                       goto try_fdmi;
+
+               rval = qla2x00_fdmi_dhba(vha);
+               if (rval)
+                       goto try_fdmi;
+
+               rval = qla2x00_fdmiv2_rhba(vha);
+               if (rval)
+                       goto try_fdmi;
+       }
+       rval = qla2x00_fdmiv2_rpa(vha);
+       if (rval)
+               goto try_fdmi;
+
+       goto out;
+
+try_fdmi:
        rval = qla2x00_fdmi_rhba(vha);
        if (rval) {
                if (rval != QLA_ALREADY_REGISTERED)
@@ -1700,7 +2405,7 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha)
                        return rval;
        }
        rval = qla2x00_fdmi_rpa(vha);
-
+out:
        return rval;
 }
 
index c54a53d..8086759 100644 (file)
@@ -695,11 +695,11 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str)
 }
 
 char *
-qlafx00_fw_version_str(struct scsi_qla_host *vha, char *str)
+qlafx00_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
 {
        struct qla_hw_data *ha = vha->hw;
 
-       sprintf(str, "%s", ha->mr.fw_version);
+       snprintf(str, size, "%s", ha->mr.fw_version);
        return str;
 }
 
index f937859..1b9864c 100644 (file)
@@ -548,14 +548,13 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
 }
 
 static char *
-qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
+qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
 {
        char un_str[10];
        struct qla_hw_data *ha = vha->hw;
 
-       sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
-           ha->fw_minor_version,
-           ha->fw_subminor_version);
+       snprintf(str, size, "%d.%02d.%02d ", ha->fw_major_version,
+           ha->fw_minor_version, ha->fw_subminor_version);
 
        if (ha->fw_attributes & BIT_9) {
                strcat(str, "FLX");
@@ -587,11 +586,11 @@ qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
 }
 
 static char *
-qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
+qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
 {
        struct qla_hw_data *ha = vha->hw;
 
-       sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
+       snprintf(str, size, "%d.%02d.%02d (%x)", ha->fw_major_version,
            ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
        return str;
 }
@@ -2925,7 +2924,7 @@ skip_dpc:
            pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info),
            pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-',
            base_vha->host_no,
-           ha->isp_ops->fw_version_str(base_vha, fw_str));
+           ha->isp_ops->fw_version_str(base_vha, fw_str, sizeof(fw_str)));
 
        qlt_add_target(ha, base_vha);