diff options
author | Himanshu Madhani <himanshu.madhani@qlogic.com> | 2014-09-25 13:16:46 +0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-09-25 16:25:02 +0400 |
commit | df57cabac41fd54e8eb73f9de482f054eb0b98eb (patch) | |
tree | 2c136444c77d444667e5fc4e883d658aac52e7eb /drivers/scsi/qla2xxx/qla_gs.c | |
parent | e475f9c0a5a12dfc79647f5a9b222f20db5f61a5 (diff) | |
download | linux-df57cabac41fd54e8eb73f9de482f054eb0b98eb.tar.xz |
qla2xxx: Add FDMI-2 functionality.
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>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_gs.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 943 |
1 files changed, 824 insertions, 119 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index a0df3b1b3823..dccc4dcc39c8 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -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; } |