linux/drivers/scsi/qla2xxx/qla_gs.c
<<
>>
Prefs
   1/*
   2 * QLogic Fibre Channel HBA Driver
   3 * Copyright (c)  2003-2013 QLogic Corporation
   4 *
   5 * See LICENSE.qla2xxx for copyright and licensing details.
   6 */
   7#include "qla_def.h"
   8#include "qla_target.h"
   9
  10static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
  11static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
  12static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
  13static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
  14static int qla2x00_sns_rft_id(scsi_qla_host_t *);
  15static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
  16
  17/**
  18 * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
  19 * @ha: HA context
  20 * @req_size: request size in bytes
  21 * @rsp_size: response size in bytes
  22 *
  23 * Returns a pointer to the @ha's ms_iocb.
  24 */
  25void *
  26qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
  27{
  28        struct qla_hw_data *ha = vha->hw;
  29        ms_iocb_entry_t *ms_pkt;
  30
  31        ms_pkt = ha->ms_iocb;
  32        memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
  33
  34        ms_pkt->entry_type = MS_IOCB_TYPE;
  35        ms_pkt->entry_count = 1;
  36        SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
  37        ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
  38        ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
  39        ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
  40        ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
  41        ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
  42        ms_pkt->req_bytecount = cpu_to_le32(req_size);
  43
  44        ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  45        ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  46        ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
  47
  48        ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  49        ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  50        ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
  51
  52        return (ms_pkt);
  53}
  54
  55/**
  56 * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
  57 * @ha: HA context
  58 * @req_size: request size in bytes
  59 * @rsp_size: response size in bytes
  60 *
  61 * Returns a pointer to the @ha's ms_iocb.
  62 */
  63void *
  64qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
  65{
  66        struct qla_hw_data *ha = vha->hw;
  67        struct ct_entry_24xx *ct_pkt;
  68
  69        ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
  70        memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
  71
  72        ct_pkt->entry_type = CT_IOCB_TYPE;
  73        ct_pkt->entry_count = 1;
  74        ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
  75        ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
  76        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
  77        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
  78        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
  79        ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
  80
  81        ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  82        ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  83        ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
  84
  85        ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  86        ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  87        ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
  88        ct_pkt->vp_index = vha->vp_idx;
  89
  90        return (ct_pkt);
  91}
  92
  93/**
  94 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
  95 * @ct_req: CT request buffer
  96 * @cmd: GS command
  97 * @rsp_size: response size in bytes
  98 *
  99 * Returns a pointer to the intitialized @ct_req.
 100 */
 101static inline struct ct_sns_req *
 102qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
 103{
 104        memset(ct_req, 0, sizeof(struct ct_sns_pkt));
 105
 106        ct_req->header.revision = 0x01;
 107        ct_req->header.gs_type = 0xFC;
 108        ct_req->header.gs_subtype = 0x02;
 109        ct_req->command = cpu_to_be16(cmd);
 110        ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
 111
 112        return (ct_req);
 113}
 114
 115static int
 116qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 117    struct ct_sns_rsp *ct_rsp, const char *routine)
 118{
 119        int rval;
 120        uint16_t comp_status;
 121        struct qla_hw_data *ha = vha->hw;
 122
 123        rval = QLA_FUNCTION_FAILED;
 124        if (ms_pkt->entry_status != 0) {
 125                ql_dbg(ql_dbg_disc, vha, 0x2031,
 126                    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
 127                    routine, ms_pkt->entry_status, vha->d_id.b.domain,
 128                    vha->d_id.b.area, vha->d_id.b.al_pa);
 129        } else {
 130                if (IS_FWI2_CAPABLE(ha))
 131                        comp_status = le16_to_cpu(
 132                            ((struct ct_entry_24xx *)ms_pkt)->comp_status);
 133                else
 134                        comp_status = le16_to_cpu(ms_pkt->status);
 135                switch (comp_status) {
 136                case CS_COMPLETE:
 137                case CS_DATA_UNDERRUN:
 138                case CS_DATA_OVERRUN:           /* Overrun? */
 139                        if (ct_rsp->header.response !=
 140                            __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
 141                                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
 142                                    "%s failed rejected request on port_id: "
 143                                    "%02x%02x%02x.\n", routine,
 144                                    vha->d_id.b.domain, vha->d_id.b.area,
 145                                    vha->d_id.b.al_pa);
 146                                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
 147                                    0x2078, (uint8_t *)&ct_rsp->header,
 148                                    sizeof(struct ct_rsp_hdr));
 149                                rval = QLA_INVALID_COMMAND;
 150                        } else
 151                                rval = QLA_SUCCESS;
 152                        break;
 153                default:
 154                        ql_dbg(ql_dbg_disc, vha, 0x2033,
 155                            "%s failed, completion status (%x) on port_id: "
 156                            "%02x%02x%02x.\n", routine, comp_status,
 157                            vha->d_id.b.domain, vha->d_id.b.area,
 158                            vha->d_id.b.al_pa);
 159                        break;
 160                }
 161        }
 162        return rval;
 163}
 164
 165/**
 166 * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
 167 * @ha: HA context
 168 * @fcport: fcport entry to updated
 169 *
 170 * Returns 0 on success.
 171 */
 172int
 173qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
 174{
 175        int             rval;
 176
 177        ms_iocb_entry_t *ms_pkt;
 178        struct ct_sns_req       *ct_req;
 179        struct ct_sns_rsp       *ct_rsp;
 180        struct qla_hw_data *ha = vha->hw;
 181
 182        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 183                return qla2x00_sns_ga_nxt(vha, fcport);
 184
 185        /* Issue GA_NXT */
 186        /* Prepare common MS IOCB */
 187        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
 188            GA_NXT_RSP_SIZE);
 189
 190        /* Prepare CT request */
 191        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
 192            GA_NXT_RSP_SIZE);
 193        ct_rsp = &ha->ct_sns->p.rsp;
 194
 195        /* Prepare CT arguments -- port_id */
 196        ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
 197        ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
 198        ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
 199
 200        /* Execute MS IOCB */
 201        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 202            sizeof(ms_iocb_entry_t));
 203        if (rval != QLA_SUCCESS) {
 204                /*EMPTY*/
 205                ql_dbg(ql_dbg_disc, vha, 0x2062,
 206                    "GA_NXT issue IOCB failed (%d).\n", rval);
 207        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
 208            QLA_SUCCESS) {
 209                rval = QLA_FUNCTION_FAILED;
 210        } else {
 211                /* Populate fc_port_t entry. */
 212                fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
 213                fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
 214                fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
 215
 216                memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
 217                    WWN_SIZE);
 218                memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
 219                    WWN_SIZE);
 220
 221                fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
 222                    FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
 223
 224                if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
 225                    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
 226                        fcport->d_id.b.domain = 0xf0;
 227
 228                ql_dbg(ql_dbg_disc, vha, 0x2063,
 229                    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
 230                    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
 231                    "port_id=%02x%02x%02x.\n",
 232                    fcport->node_name[0], fcport->node_name[1],
 233                    fcport->node_name[2], fcport->node_name[3],
 234                    fcport->node_name[4], fcport->node_name[5],
 235                    fcport->node_name[6], fcport->node_name[7],
 236                    fcport->port_name[0], fcport->port_name[1],
 237                    fcport->port_name[2], fcport->port_name[3],
 238                    fcport->port_name[4], fcport->port_name[5],
 239                    fcport->port_name[6], fcport->port_name[7],
 240                    fcport->d_id.b.domain, fcport->d_id.b.area,
 241                    fcport->d_id.b.al_pa);
 242        }
 243
 244        return (rval);
 245}
 246
 247static inline int
 248qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
 249{
 250        return vha->hw->max_fibre_devices * 4 + 16;
 251}
 252
 253/**
 254 * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
 255 * @ha: HA context
 256 * @list: switch info entries to populate
 257 *
 258 * NOTE: Non-Nx_Ports are not requested.
 259 *
 260 * Returns 0 on success.
 261 */
 262int
 263qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
 264{
 265        int             rval;
 266        uint16_t        i;
 267
 268        ms_iocb_entry_t *ms_pkt;
 269        struct ct_sns_req       *ct_req;
 270        struct ct_sns_rsp       *ct_rsp;
 271
 272        struct ct_sns_gid_pt_data *gid_data;
 273        struct qla_hw_data *ha = vha->hw;
 274        uint16_t gid_pt_rsp_size;
 275
 276        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 277                return qla2x00_sns_gid_pt(vha, list);
 278
 279        gid_data = NULL;
 280        gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
 281        /* Issue GID_PT */
 282        /* Prepare common MS IOCB */
 283        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
 284            gid_pt_rsp_size);
 285
 286        /* Prepare CT request */
 287        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
 288            gid_pt_rsp_size);
 289        ct_rsp = &ha->ct_sns->p.rsp;
 290
 291        /* Prepare CT arguments -- port_type */
 292        ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
 293
 294        /* Execute MS IOCB */
 295        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 296            sizeof(ms_iocb_entry_t));
 297        if (rval != QLA_SUCCESS) {
 298                /*EMPTY*/
 299                ql_dbg(ql_dbg_disc, vha, 0x2055,
 300                    "GID_PT issue IOCB failed (%d).\n", rval);
 301        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
 302            QLA_SUCCESS) {
 303                rval = QLA_FUNCTION_FAILED;
 304        } else {
 305                /* Set port IDs in switch info list. */
 306                for (i = 0; i < ha->max_fibre_devices; i++) {
 307                        gid_data = &ct_rsp->rsp.gid_pt.entries[i];
 308                        list[i].d_id.b.domain = gid_data->port_id[0];
 309                        list[i].d_id.b.area = gid_data->port_id[1];
 310                        list[i].d_id.b.al_pa = gid_data->port_id[2];
 311                        memset(list[i].fabric_port_name, 0, WWN_SIZE);
 312                        list[i].fp_speed = PORT_SPEED_UNKNOWN;
 313
 314                        /* Last one exit. */
 315                        if (gid_data->control_byte & BIT_7) {
 316                                list[i].d_id.b.rsvd_1 = gid_data->control_byte;
 317                                break;
 318                        }
 319                }
 320
 321                /*
 322                 * If we've used all available slots, then the switch is
 323                 * reporting back more devices than we can handle with this
 324                 * single call.  Return a failed status, and let GA_NXT handle
 325                 * the overload.
 326                 */
 327                if (i == ha->max_fibre_devices)
 328                        rval = QLA_FUNCTION_FAILED;
 329        }
 330
 331        return (rval);
 332}
 333
 334/**
 335 * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
 336 * @ha: HA context
 337 * @list: switch info entries to populate
 338 *
 339 * Returns 0 on success.
 340 */
 341int
 342qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 343{
 344        int             rval = QLA_SUCCESS;
 345        uint16_t        i;
 346
 347        ms_iocb_entry_t *ms_pkt;
 348        struct ct_sns_req       *ct_req;
 349        struct ct_sns_rsp       *ct_rsp;
 350        struct qla_hw_data *ha = vha->hw;
 351
 352        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 353                return qla2x00_sns_gpn_id(vha, list);
 354
 355        for (i = 0; i < ha->max_fibre_devices; i++) {
 356                /* Issue GPN_ID */
 357                /* Prepare common MS IOCB */
 358                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
 359                    GPN_ID_RSP_SIZE);
 360
 361                /* Prepare CT request */
 362                ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
 363                    GPN_ID_RSP_SIZE);
 364                ct_rsp = &ha->ct_sns->p.rsp;
 365
 366                /* Prepare CT arguments -- port_id */
 367                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
 368                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
 369                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
 370
 371                /* Execute MS IOCB */
 372                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 373                    sizeof(ms_iocb_entry_t));
 374                if (rval != QLA_SUCCESS) {
 375                        /*EMPTY*/
 376                        ql_dbg(ql_dbg_disc, vha, 0x2056,
 377                            "GPN_ID issue IOCB failed (%d).\n", rval);
 378                        break;
 379                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
 380                    "GPN_ID") != QLA_SUCCESS) {
 381                        rval = QLA_FUNCTION_FAILED;
 382                        break;
 383                } else {
 384                        /* Save portname */
 385                        memcpy(list[i].port_name,
 386                            ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
 387                }
 388
 389                /* Last device exit. */
 390                if (list[i].d_id.b.rsvd_1 != 0)
 391                        break;
 392        }
 393
 394        return (rval);
 395}
 396
 397/**
 398 * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
 399 * @ha: HA context
 400 * @list: switch info entries to populate
 401 *
 402 * Returns 0 on success.
 403 */
 404int
 405qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 406{
 407        int             rval = QLA_SUCCESS;
 408        uint16_t        i;
 409        struct qla_hw_data *ha = vha->hw;
 410        ms_iocb_entry_t *ms_pkt;
 411        struct ct_sns_req       *ct_req;
 412        struct ct_sns_rsp       *ct_rsp;
 413
 414        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 415                return qla2x00_sns_gnn_id(vha, list);
 416
 417        for (i = 0; i < ha->max_fibre_devices; i++) {
 418                /* Issue GNN_ID */
 419                /* Prepare common MS IOCB */
 420                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
 421                    GNN_ID_RSP_SIZE);
 422
 423                /* Prepare CT request */
 424                ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
 425                    GNN_ID_RSP_SIZE);
 426                ct_rsp = &ha->ct_sns->p.rsp;
 427
 428                /* Prepare CT arguments -- port_id */
 429                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
 430                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
 431                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
 432
 433                /* Execute MS IOCB */
 434                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 435                    sizeof(ms_iocb_entry_t));
 436                if (rval != QLA_SUCCESS) {
 437                        /*EMPTY*/
 438                        ql_dbg(ql_dbg_disc, vha, 0x2057,
 439                            "GNN_ID issue IOCB failed (%d).\n", rval);
 440                        break;
 441                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
 442                    "GNN_ID") != QLA_SUCCESS) {
 443                        rval = QLA_FUNCTION_FAILED;
 444                        break;
 445                } else {
 446                        /* Save nodename */
 447                        memcpy(list[i].node_name,
 448                            ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
 449
 450                        ql_dbg(ql_dbg_disc, vha, 0x2058,
 451                            "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
 452                            "pn %02x%02x%02x%02x%02x%02x%02X%02x "
 453                            "portid=%02x%02x%02x.\n",
 454                            list[i].node_name[0], list[i].node_name[1],
 455                            list[i].node_name[2], list[i].node_name[3],
 456                            list[i].node_name[4], list[i].node_name[5],
 457                            list[i].node_name[6], list[i].node_name[7],
 458                            list[i].port_name[0], list[i].port_name[1],
 459                            list[i].port_name[2], list[i].port_name[3],
 460                            list[i].port_name[4], list[i].port_name[5],
 461                            list[i].port_name[6], list[i].port_name[7],
 462                            list[i].d_id.b.domain, list[i].d_id.b.area,
 463                            list[i].d_id.b.al_pa);
 464                }
 465
 466                /* Last device exit. */
 467                if (list[i].d_id.b.rsvd_1 != 0)
 468                        break;
 469        }
 470
 471        return (rval);
 472}
 473
 474/**
 475 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
 476 * @ha: HA context
 477 *
 478 * Returns 0 on success.
 479 */
 480int
 481qla2x00_rft_id(scsi_qla_host_t *vha)
 482{
 483        int             rval;
 484        struct qla_hw_data *ha = vha->hw;
 485        ms_iocb_entry_t *ms_pkt;
 486        struct ct_sns_req       *ct_req;
 487        struct ct_sns_rsp       *ct_rsp;
 488
 489        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 490                return qla2x00_sns_rft_id(vha);
 491
 492        /* Issue RFT_ID */
 493        /* Prepare common MS IOCB */
 494        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
 495            RFT_ID_RSP_SIZE);
 496
 497        /* Prepare CT request */
 498        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
 499            RFT_ID_RSP_SIZE);
 500        ct_rsp = &ha->ct_sns->p.rsp;
 501
 502        /* Prepare CT arguments -- port_id, FC-4 types */
 503        ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
 504        ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
 505        ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
 506
 507        ct_req->req.rft_id.fc4_types[2] = 0x01;         /* FCP-3 */
 508
 509        /* Execute MS IOCB */
 510        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 511            sizeof(ms_iocb_entry_t));
 512        if (rval != QLA_SUCCESS) {
 513                /*EMPTY*/
 514                ql_dbg(ql_dbg_disc, vha, 0x2043,
 515                    "RFT_ID issue IOCB failed (%d).\n", rval);
 516        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
 517            QLA_SUCCESS) {
 518                rval = QLA_FUNCTION_FAILED;
 519        } else {
 520                ql_dbg(ql_dbg_disc, vha, 0x2044,
 521                    "RFT_ID exiting normally.\n");
 522        }
 523
 524        return (rval);
 525}
 526
 527/**
 528 * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
 529 * @ha: HA context
 530 *
 531 * Returns 0 on success.
 532 */
 533int
 534qla2x00_rff_id(scsi_qla_host_t *vha)
 535{
 536        int             rval;
 537        struct qla_hw_data *ha = vha->hw;
 538        ms_iocb_entry_t *ms_pkt;
 539        struct ct_sns_req       *ct_req;
 540        struct ct_sns_rsp       *ct_rsp;
 541
 542        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 543                ql_dbg(ql_dbg_disc, vha, 0x2046,
 544                    "RFF_ID call not supported on ISP2100/ISP2200.\n");
 545                return (QLA_SUCCESS);
 546        }
 547
 548        /* Issue RFF_ID */
 549        /* Prepare common MS IOCB */
 550        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
 551            RFF_ID_RSP_SIZE);
 552
 553        /* Prepare CT request */
 554        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
 555            RFF_ID_RSP_SIZE);
 556        ct_rsp = &ha->ct_sns->p.rsp;
 557
 558        /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
 559        ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
 560        ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
 561        ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
 562
 563        qlt_rff_id(vha, ct_req);
 564
 565        ct_req->req.rff_id.fc4_type = 0x08;             /* SCSI - FCP */
 566
 567        /* Execute MS IOCB */
 568        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 569            sizeof(ms_iocb_entry_t));
 570        if (rval != QLA_SUCCESS) {
 571                /*EMPTY*/
 572                ql_dbg(ql_dbg_disc, vha, 0x2047,
 573                    "RFF_ID issue IOCB failed (%d).\n", rval);
 574        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
 575            QLA_SUCCESS) {
 576                rval = QLA_FUNCTION_FAILED;
 577        } else {
 578                ql_dbg(ql_dbg_disc, vha, 0x2048,
 579                    "RFF_ID exiting normally.\n");
 580        }
 581
 582        return (rval);
 583}
 584
 585/**
 586 * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
 587 * @ha: HA context
 588 *
 589 * Returns 0 on success.
 590 */
 591int
 592qla2x00_rnn_id(scsi_qla_host_t *vha)
 593{
 594        int             rval;
 595        struct qla_hw_data *ha = vha->hw;
 596        ms_iocb_entry_t *ms_pkt;
 597        struct ct_sns_req       *ct_req;
 598        struct ct_sns_rsp       *ct_rsp;
 599
 600        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 601                return qla2x00_sns_rnn_id(vha);
 602
 603        /* Issue RNN_ID */
 604        /* Prepare common MS IOCB */
 605        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
 606            RNN_ID_RSP_SIZE);
 607
 608        /* Prepare CT request */
 609        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
 610            RNN_ID_RSP_SIZE);
 611        ct_rsp = &ha->ct_sns->p.rsp;
 612
 613        /* Prepare CT arguments -- port_id, node_name */
 614        ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
 615        ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
 616        ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
 617
 618        memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
 619
 620        /* Execute MS IOCB */
 621        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 622            sizeof(ms_iocb_entry_t));
 623        if (rval != QLA_SUCCESS) {
 624                /*EMPTY*/
 625                ql_dbg(ql_dbg_disc, vha, 0x204d,
 626                    "RNN_ID issue IOCB failed (%d).\n", rval);
 627        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
 628            QLA_SUCCESS) {
 629                rval = QLA_FUNCTION_FAILED;
 630        } else {
 631                ql_dbg(ql_dbg_disc, vha, 0x204e,
 632                    "RNN_ID exiting normally.\n");
 633        }
 634
 635        return (rval);
 636}
 637
 638void
 639qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
 640{
 641        struct qla_hw_data *ha = vha->hw;
 642
 643        if (IS_QLAFX00(ha))
 644                sprintf(snn, "%s FW:v%s DVR:v%s", ha->model_number,
 645                    ha->mr.fw_version, qla2x00_version_str);
 646        else
 647                sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
 648                    ha->fw_major_version, ha->fw_minor_version,
 649                    ha->fw_subminor_version, qla2x00_version_str);
 650}
 651
 652/**
 653 * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
 654 * @ha: HA context
 655 *
 656 * Returns 0 on success.
 657 */
 658int
 659qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 660{
 661        int             rval;
 662        struct qla_hw_data *ha = vha->hw;
 663        ms_iocb_entry_t *ms_pkt;
 664        struct ct_sns_req       *ct_req;
 665        struct ct_sns_rsp       *ct_rsp;
 666
 667        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 668                ql_dbg(ql_dbg_disc, vha, 0x2050,
 669                    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
 670                return (QLA_SUCCESS);
 671        }
 672
 673        /* Issue RSNN_NN */
 674        /* Prepare common MS IOCB */
 675        /*   Request size adjusted after CT preparation */
 676        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
 677
 678        /* Prepare CT request */
 679        ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
 680            RSNN_NN_RSP_SIZE);
 681        ct_rsp = &ha->ct_sns->p.rsp;
 682
 683        /* Prepare CT arguments -- node_name, symbolic node_name, size */
 684        memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
 685
 686        /* Prepare the Symbolic Node Name */
 687        qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
 688
 689        /* Calculate SNN length */
 690        ct_req->req.rsnn_nn.name_len =
 691            (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
 692
 693        /* Update MS IOCB request */
 694        ms_pkt->req_bytecount =
 695            cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
 696        ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
 697
 698        /* Execute MS IOCB */
 699        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 700            sizeof(ms_iocb_entry_t));
 701        if (rval != QLA_SUCCESS) {
 702                /*EMPTY*/
 703                ql_dbg(ql_dbg_disc, vha, 0x2051,
 704                    "RSNN_NN issue IOCB failed (%d).\n", rval);
 705        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
 706            QLA_SUCCESS) {
 707                rval = QLA_FUNCTION_FAILED;
 708        } else {
 709                ql_dbg(ql_dbg_disc, vha, 0x2052,
 710                    "RSNN_NN exiting normally.\n");
 711        }
 712
 713        return (rval);
 714}
 715
 716/**
 717 * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
 718 * @ha: HA context
 719 * @cmd: GS command
 720 * @scmd_len: Subcommand length
 721 * @data_size: response size in bytes
 722 *
 723 * Returns a pointer to the @ha's sns_cmd.
 724 */
 725static inline struct sns_cmd_pkt *
 726qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
 727    uint16_t data_size)
 728{
 729        uint16_t                wc;
 730        struct sns_cmd_pkt      *sns_cmd;
 731        struct qla_hw_data *ha = vha->hw;
 732
 733        sns_cmd = ha->sns_cmd;
 734        memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
 735        wc = data_size / 2;                     /* Size in 16bit words. */
 736        sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
 737        sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
 738        sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
 739        sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
 740        sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
 741        wc = (data_size - 16) / 4;              /* Size in 32bit words. */
 742        sns_cmd->p.cmd.size = cpu_to_le16(wc);
 743
 744        return (sns_cmd);
 745}
 746
 747/**
 748 * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
 749 * @ha: HA context
 750 * @fcport: fcport entry to updated
 751 *
 752 * This command uses the old Exectute SNS Command mailbox routine.
 753 *
 754 * Returns 0 on success.
 755 */
 756static int
 757qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
 758{
 759        int             rval = QLA_SUCCESS;
 760        struct qla_hw_data *ha = vha->hw;
 761        struct sns_cmd_pkt      *sns_cmd;
 762
 763        /* Issue GA_NXT. */
 764        /* Prepare SNS command request. */
 765        sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
 766            GA_NXT_SNS_DATA_SIZE);
 767
 768        /* Prepare SNS command arguments -- port_id. */
 769        sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
 770        sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
 771        sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
 772
 773        /* Execute SNS command. */
 774        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
 775            sizeof(struct sns_cmd_pkt));
 776        if (rval != QLA_SUCCESS) {
 777                /*EMPTY*/
 778                ql_dbg(ql_dbg_disc, vha, 0x205f,
 779                    "GA_NXT Send SNS failed (%d).\n", rval);
 780        } else if (sns_cmd->p.gan_data[8] != 0x80 ||
 781            sns_cmd->p.gan_data[9] != 0x02) {
 782                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
 783                    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
 784                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
 785                    sns_cmd->p.gan_data, 16);
 786                rval = QLA_FUNCTION_FAILED;
 787        } else {
 788                /* Populate fc_port_t entry. */
 789                fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
 790                fcport->d_id.b.area = sns_cmd->p.gan_data[18];
 791                fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
 792
 793                memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
 794                memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
 795
 796                if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
 797                    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
 798                        fcport->d_id.b.domain = 0xf0;
 799
 800                ql_dbg(ql_dbg_disc, vha, 0x2061,
 801                    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
 802                    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
 803                    "port_id=%02x%02x%02x.\n",
 804                    fcport->node_name[0], fcport->node_name[1],
 805                    fcport->node_name[2], fcport->node_name[3],
 806                    fcport->node_name[4], fcport->node_name[5],
 807                    fcport->node_name[6], fcport->node_name[7],
 808                    fcport->port_name[0], fcport->port_name[1],
 809                    fcport->port_name[2], fcport->port_name[3],
 810                    fcport->port_name[4], fcport->port_name[5],
 811                    fcport->port_name[6], fcport->port_name[7],
 812                    fcport->d_id.b.domain, fcport->d_id.b.area,
 813                    fcport->d_id.b.al_pa);
 814        }
 815
 816        return (rval);
 817}
 818
 819/**
 820 * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
 821 * @ha: HA context
 822 * @list: switch info entries to populate
 823 *
 824 * This command uses the old Exectute SNS Command mailbox routine.
 825 *
 826 * NOTE: Non-Nx_Ports are not requested.
 827 *
 828 * Returns 0 on success.
 829 */
 830static int
 831qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
 832{
 833        int             rval;
 834        struct qla_hw_data *ha = vha->hw;
 835        uint16_t        i;
 836        uint8_t         *entry;
 837        struct sns_cmd_pkt      *sns_cmd;
 838        uint16_t gid_pt_sns_data_size;
 839
 840        gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
 841
 842        /* Issue GID_PT. */
 843        /* Prepare SNS command request. */
 844        sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
 845            gid_pt_sns_data_size);
 846
 847        /* Prepare SNS command arguments -- port_type. */
 848        sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
 849
 850        /* Execute SNS command. */
 851        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
 852            sizeof(struct sns_cmd_pkt));
 853        if (rval != QLA_SUCCESS) {
 854                /*EMPTY*/
 855                ql_dbg(ql_dbg_disc, vha, 0x206d,
 856                    "GID_PT Send SNS failed (%d).\n", rval);
 857        } else if (sns_cmd->p.gid_data[8] != 0x80 ||
 858            sns_cmd->p.gid_data[9] != 0x02) {
 859                ql_dbg(ql_dbg_disc, vha, 0x202f,
 860                    "GID_PT failed, rejected request, gid_rsp:\n");
 861                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
 862                    sns_cmd->p.gid_data, 16);
 863                rval = QLA_FUNCTION_FAILED;
 864        } else {
 865                /* Set port IDs in switch info list. */
 866                for (i = 0; i < ha->max_fibre_devices; i++) {
 867                        entry = &sns_cmd->p.gid_data[(i * 4) + 16];
 868                        list[i].d_id.b.domain = entry[1];
 869                        list[i].d_id.b.area = entry[2];
 870                        list[i].d_id.b.al_pa = entry[3];
 871
 872                        /* Last one exit. */
 873                        if (entry[0] & BIT_7) {
 874                                list[i].d_id.b.rsvd_1 = entry[0];
 875                                break;
 876                        }
 877                }
 878
 879                /*
 880                 * If we've used all available slots, then the switch is
 881                 * reporting back more devices that we can handle with this
 882                 * single call.  Return a failed status, and let GA_NXT handle
 883                 * the overload.
 884                 */
 885                if (i == ha->max_fibre_devices)
 886                        rval = QLA_FUNCTION_FAILED;
 887        }
 888
 889        return (rval);
 890}
 891
 892/**
 893 * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
 894 * @ha: HA context
 895 * @list: switch info entries to populate
 896 *
 897 * This command uses the old Exectute SNS Command mailbox routine.
 898 *
 899 * Returns 0 on success.
 900 */
 901static int
 902qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 903{
 904        int             rval = QLA_SUCCESS;
 905        struct qla_hw_data *ha = vha->hw;
 906        uint16_t        i;
 907        struct sns_cmd_pkt      *sns_cmd;
 908
 909        for (i = 0; i < ha->max_fibre_devices; i++) {
 910                /* Issue GPN_ID */
 911                /* Prepare SNS command request. */
 912                sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
 913                    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
 914
 915                /* Prepare SNS command arguments -- port_id. */
 916                sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
 917                sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
 918                sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
 919
 920                /* Execute SNS command. */
 921                rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
 922                    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
 923                if (rval != QLA_SUCCESS) {
 924                        /*EMPTY*/
 925                        ql_dbg(ql_dbg_disc, vha, 0x2032,
 926                            "GPN_ID Send SNS failed (%d).\n", rval);
 927                } else if (sns_cmd->p.gpn_data[8] != 0x80 ||
 928                    sns_cmd->p.gpn_data[9] != 0x02) {
 929                        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
 930                            "GPN_ID failed, rejected request, gpn_rsp:\n");
 931                        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
 932                            sns_cmd->p.gpn_data, 16);
 933                        rval = QLA_FUNCTION_FAILED;
 934                } else {
 935                        /* Save portname */
 936                        memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
 937                            WWN_SIZE);
 938                }
 939
 940                /* Last device exit. */
 941                if (list[i].d_id.b.rsvd_1 != 0)
 942                        break;
 943        }
 944
 945        return (rval);
 946}
 947
 948/**
 949 * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
 950 * @ha: HA context
 951 * @list: switch info entries to populate
 952 *
 953 * This command uses the old Exectute SNS Command mailbox routine.
 954 *
 955 * Returns 0 on success.
 956 */
 957static int
 958qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 959{
 960        int             rval = QLA_SUCCESS;
 961        struct qla_hw_data *ha = vha->hw;
 962        uint16_t        i;
 963        struct sns_cmd_pkt      *sns_cmd;
 964
 965        for (i = 0; i < ha->max_fibre_devices; i++) {
 966                /* Issue GNN_ID */
 967                /* Prepare SNS command request. */
 968                sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
 969                    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
 970
 971                /* Prepare SNS command arguments -- port_id. */
 972                sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
 973                sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
 974                sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
 975
 976                /* Execute SNS command. */
 977                rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
 978                    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
 979                if (rval != QLA_SUCCESS) {
 980                        /*EMPTY*/
 981                        ql_dbg(ql_dbg_disc, vha, 0x203f,
 982                            "GNN_ID Send SNS failed (%d).\n", rval);
 983                } else if (sns_cmd->p.gnn_data[8] != 0x80 ||
 984                    sns_cmd->p.gnn_data[9] != 0x02) {
 985                        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
 986                            "GNN_ID failed, rejected request, gnn_rsp:\n");
 987                        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
 988                            sns_cmd->p.gnn_data, 16);
 989                        rval = QLA_FUNCTION_FAILED;
 990                } else {
 991                        /* Save nodename */
 992                        memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
 993                            WWN_SIZE);
 994
 995                        ql_dbg(ql_dbg_disc, vha, 0x206e,
 996                            "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
 997                            "pn %02x%02x%02x%02x%02x%02x%02x%02x "
 998                            "port_id=%02x%02x%02x.\n",
 999                            list[i].node_name[0], list[i].node_name[1],
1000                            list[i].node_name[2], list[i].node_name[3],
1001                            list[i].node_name[4], list[i].node_name[5],
1002                            list[i].node_name[6], list[i].node_name[7],
1003                            list[i].port_name[0], list[i].port_name[1],
1004                            list[i].port_name[2], list[i].port_name[3],
1005                            list[i].port_name[4], list[i].port_name[5],
1006                            list[i].port_name[6], list[i].port_name[7],
1007                            list[i].d_id.b.domain, list[i].d_id.b.area,
1008                            list[i].d_id.b.al_pa);
1009                }
1010
1011                /* Last device exit. */
1012                if (list[i].d_id.b.rsvd_1 != 0)
1013                        break;
1014        }
1015
1016        return (rval);
1017}
1018
1019/**
1020 * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1021 * @ha: HA context
1022 *
1023 * This command uses the old Exectute SNS Command mailbox routine.
1024 *
1025 * Returns 0 on success.
1026 */
1027static int
1028qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1029{
1030        int             rval;
1031        struct qla_hw_data *ha = vha->hw;
1032        struct sns_cmd_pkt      *sns_cmd;
1033
1034        /* Issue RFT_ID. */
1035        /* Prepare SNS command request. */
1036        sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1037            RFT_ID_SNS_DATA_SIZE);
1038
1039        /* Prepare SNS command arguments -- port_id, FC-4 types */
1040        sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1041        sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1042        sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1043
1044        sns_cmd->p.cmd.param[5] = 0x01;                 /* FCP-3 */
1045
1046        /* Execute SNS command. */
1047        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1048            sizeof(struct sns_cmd_pkt));
1049        if (rval != QLA_SUCCESS) {
1050                /*EMPTY*/
1051                ql_dbg(ql_dbg_disc, vha, 0x2060,
1052                    "RFT_ID Send SNS failed (%d).\n", rval);
1053        } else if (sns_cmd->p.rft_data[8] != 0x80 ||
1054            sns_cmd->p.rft_data[9] != 0x02) {
1055                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1056                    "RFT_ID failed, rejected request rft_rsp:\n");
1057                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1058                    sns_cmd->p.rft_data, 16);
1059                rval = QLA_FUNCTION_FAILED;
1060        } else {
1061                ql_dbg(ql_dbg_disc, vha, 0x2073,
1062                    "RFT_ID exiting normally.\n");
1063        }
1064
1065        return (rval);
1066}
1067
1068/**
1069 * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1070 * HBA.
1071 * @ha: HA context
1072 *
1073 * This command uses the old Exectute SNS Command mailbox routine.
1074 *
1075 * Returns 0 on success.
1076 */
1077static int
1078qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1079{
1080        int             rval;
1081        struct qla_hw_data *ha = vha->hw;
1082        struct sns_cmd_pkt      *sns_cmd;
1083
1084        /* Issue RNN_ID. */
1085        /* Prepare SNS command request. */
1086        sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1087            RNN_ID_SNS_DATA_SIZE);
1088
1089        /* Prepare SNS command arguments -- port_id, nodename. */
1090        sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1091        sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1092        sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1093
1094        sns_cmd->p.cmd.param[4] = vha->node_name[7];
1095        sns_cmd->p.cmd.param[5] = vha->node_name[6];
1096        sns_cmd->p.cmd.param[6] = vha->node_name[5];
1097        sns_cmd->p.cmd.param[7] = vha->node_name[4];
1098        sns_cmd->p.cmd.param[8] = vha->node_name[3];
1099        sns_cmd->p.cmd.param[9] = vha->node_name[2];
1100        sns_cmd->p.cmd.param[10] = vha->node_name[1];
1101        sns_cmd->p.cmd.param[11] = vha->node_name[0];
1102
1103        /* Execute SNS command. */
1104        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1105            sizeof(struct sns_cmd_pkt));
1106        if (rval != QLA_SUCCESS) {
1107                /*EMPTY*/
1108                ql_dbg(ql_dbg_disc, vha, 0x204a,
1109                    "RNN_ID Send SNS failed (%d).\n", rval);
1110        } else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1111            sns_cmd->p.rnn_data[9] != 0x02) {
1112                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1113                    "RNN_ID failed, rejected request, rnn_rsp:\n");
1114                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1115                    sns_cmd->p.rnn_data, 16);
1116                rval = QLA_FUNCTION_FAILED;
1117        } else {
1118                ql_dbg(ql_dbg_disc, vha, 0x204c,
1119                    "RNN_ID exiting normally.\n");
1120        }
1121
1122        return (rval);
1123}
1124
1125/**
1126 * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1127 * @ha: HA context
1128 *
1129 * Returns 0 on success.
1130 */
1131static int
1132qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1133{
1134        int ret, rval;
1135        uint16_t mb[MAILBOX_REGISTER_COUNT];
1136        struct qla_hw_data *ha = vha->hw;
1137        ret = QLA_SUCCESS;
1138        if (vha->flags.management_server_logged_in)
1139                return ret;
1140
1141        rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1142            0xfa, mb, BIT_1);
1143        if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1144                if (rval == QLA_MEMORY_ALLOC_FAILED)
1145                        ql_dbg(ql_dbg_disc, vha, 0x2085,
1146                            "Failed management_server login: loopid=%x "
1147                            "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1148                else
1149                        ql_dbg(ql_dbg_disc, vha, 0x2024,
1150                            "Failed management_server login: loopid=%x "
1151                            "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1152                            vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1153                            mb[7]);
1154                ret = QLA_FUNCTION_FAILED;
1155        } else
1156                vha->flags.management_server_logged_in = 1;
1157
1158        return ret;
1159}
1160
1161/**
1162 * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1163 * @ha: HA context
1164 * @req_size: request size in bytes
1165 * @rsp_size: response size in bytes
1166 *
1167 * Returns a pointer to the @ha's ms_iocb.
1168 */
1169void *
1170qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1171    uint32_t rsp_size)
1172{
1173        ms_iocb_entry_t *ms_pkt;
1174        struct qla_hw_data *ha = vha->hw;
1175        ms_pkt = ha->ms_iocb;
1176        memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1177
1178        ms_pkt->entry_type = MS_IOCB_TYPE;
1179        ms_pkt->entry_count = 1;
1180        SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1181        ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
1182        ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1183        ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1184        ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
1185        ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1186        ms_pkt->req_bytecount = cpu_to_le32(req_size);
1187
1188        ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1189        ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1190        ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1191
1192        ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1193        ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1194        ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1195
1196        return ms_pkt;
1197}
1198
1199/**
1200 * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1201 * @ha: HA context
1202 * @req_size: request size in bytes
1203 * @rsp_size: response size in bytes
1204 *
1205 * Returns a pointer to the @ha's ms_iocb.
1206 */
1207void *
1208qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1209    uint32_t rsp_size)
1210{
1211        struct ct_entry_24xx *ct_pkt;
1212        struct qla_hw_data *ha = vha->hw;
1213
1214        ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1215        memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1216
1217        ct_pkt->entry_type = CT_IOCB_TYPE;
1218        ct_pkt->entry_count = 1;
1219        ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1220        ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1221        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1222        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1223        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1224        ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1225
1226        ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1227        ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1228        ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1229
1230        ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1231        ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1232        ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1233        ct_pkt->vp_index = vha->vp_idx;
1234
1235        return ct_pkt;
1236}
1237
1238static inline ms_iocb_entry_t *
1239qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1240{
1241        struct qla_hw_data *ha = vha->hw;
1242        ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1243        struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1244
1245        if (IS_FWI2_CAPABLE(ha)) {
1246                ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1247                ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1248        } else {
1249                ms_pkt->req_bytecount = cpu_to_le32(req_size);
1250                ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1251        }
1252
1253        return ms_pkt;
1254}
1255
1256/**
1257 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1258 * @ct_req: CT request buffer
1259 * @cmd: GS command
1260 * @rsp_size: response size in bytes
1261 *
1262 * Returns a pointer to the intitialized @ct_req.
1263 */
1264static inline struct ct_sns_req *
1265qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
1266    uint16_t rsp_size)
1267{
1268        memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1269
1270        ct_req->header.revision = 0x01;
1271        ct_req->header.gs_type = 0xFA;
1272        ct_req->header.gs_subtype = 0x10;
1273        ct_req->command = cpu_to_be16(cmd);
1274        ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1275
1276        return ct_req;
1277}
1278
1279/**
1280 * qla2x00_fdmi_rhba() -
1281 * @ha: HA context
1282 *
1283 * Returns 0 on success.
1284 */
1285static int
1286qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1287{
1288        int rval, alen;
1289        uint32_t size, sn;
1290
1291        ms_iocb_entry_t *ms_pkt;
1292        struct ct_sns_req *ct_req;
1293        struct ct_sns_rsp *ct_rsp;
1294        uint8_t *entries;
1295        struct ct_fdmi_hba_attr *eiter;
1296        struct qla_hw_data *ha = vha->hw;
1297
1298        /* Issue RHBA */
1299        /* Prepare common MS IOCB */
1300        /*   Request size adjusted after CT preparation */
1301        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1302
1303        /* Prepare CT request */
1304        ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
1305            RHBA_RSP_SIZE);
1306        ct_rsp = &ha->ct_sns->p.rsp;
1307
1308        /* Prepare FDMI command arguments -- attribute block, attributes. */
1309        memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1310        ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
1311        memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1312        size = 2 * WWN_SIZE + 4 + 4;
1313
1314        /* Attributes */
1315        ct_req->req.rhba.attrs.count =
1316            __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1317        entries = ct_req->req.rhba.hba_identifier;
1318
1319        /* Nodename. */
1320        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1321        eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
1322        eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
1323        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1324        size += 4 + WWN_SIZE;
1325
1326        ql_dbg(ql_dbg_disc, vha, 0x2025,
1327            "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1328            eiter->a.node_name[0], eiter->a.node_name[1],
1329            eiter->a.node_name[2], eiter->a.node_name[3],
1330            eiter->a.node_name[4], eiter->a.node_name[5],
1331            eiter->a.node_name[6], eiter->a.node_name[7]);
1332
1333        /* Manufacturer. */
1334        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1335        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
1336        alen = strlen(QLA2XXX_MANUFACTURER);
1337        strncpy(eiter->a.manufacturer, QLA2XXX_MANUFACTURER, alen + 1);
1338        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1339        eiter->len = cpu_to_be16(4 + alen);
1340        size += 4 + alen;
1341
1342        ql_dbg(ql_dbg_disc, vha, 0x2026,
1343            "Manufacturer = %s.\n", eiter->a.manufacturer);
1344
1345        /* Serial number. */
1346        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1347        eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1348        sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
1349        sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
1350        alen = strlen(eiter->a.serial_num);
1351        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1352        eiter->len = cpu_to_be16(4 + alen);
1353        size += 4 + alen;
1354
1355        ql_dbg(ql_dbg_disc, vha, 0x2027,
1356            "Serial no. = %s.\n", eiter->a.serial_num);
1357
1358        /* Model name. */
1359        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1360        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
1361        strcpy(eiter->a.model, ha->model_number);
1362        alen = strlen(eiter->a.model);
1363        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1364        eiter->len = cpu_to_be16(4 + alen);
1365        size += 4 + alen;
1366
1367        ql_dbg(ql_dbg_disc, vha, 0x2028,
1368            "Model Name = %s.\n", eiter->a.model);
1369
1370        /* Model description. */
1371        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1372        eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1373        if (ha->model_desc)
1374                strncpy(eiter->a.model_desc, ha->model_desc, 80);
1375        alen = strlen(eiter->a.model_desc);
1376        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1377        eiter->len = cpu_to_be16(4 + alen);
1378        size += 4 + alen;
1379
1380        ql_dbg(ql_dbg_disc, vha, 0x2029,
1381            "Model Desc = %s.\n", eiter->a.model_desc);
1382
1383        /* Hardware version. */
1384        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1385        eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1386        strcpy(eiter->a.hw_version, ha->adapter_id);
1387        alen = strlen(eiter->a.hw_version);
1388        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1389        eiter->len = cpu_to_be16(4 + alen);
1390        size += 4 + alen;
1391
1392        ql_dbg(ql_dbg_disc, vha, 0x202a,
1393            "Hardware ver = %s.\n", eiter->a.hw_version);
1394
1395        /* Driver version. */
1396        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1397        eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1398        strcpy(eiter->a.driver_version, qla2x00_version_str);
1399        alen = strlen(eiter->a.driver_version);
1400        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1401        eiter->len = cpu_to_be16(4 + alen);
1402        size += 4 + alen;
1403
1404        ql_dbg(ql_dbg_disc, vha, 0x202b,
1405            "Driver ver = %s.\n", eiter->a.driver_version);
1406
1407        /* Option ROM version. */
1408        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1409        eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1410        strcpy(eiter->a.orom_version, "0.00");
1411        alen = strlen(eiter->a.orom_version);
1412        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1413        eiter->len = cpu_to_be16(4 + alen);
1414        size += 4 + alen;
1415
1416        ql_dbg(ql_dbg_disc, vha , 0x202c,
1417            "Optrom vers = %s.\n", eiter->a.orom_version);
1418
1419        /* Firmware version */
1420        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1421        eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1422        ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
1423        alen = strlen(eiter->a.fw_version);
1424        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1425        eiter->len = cpu_to_be16(4 + alen);
1426        size += 4 + alen;
1427
1428        ql_dbg(ql_dbg_disc, vha, 0x202d,
1429            "Firmware vers = %s.\n", eiter->a.fw_version);
1430
1431        /* Update MS request size. */
1432        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1433
1434        ql_dbg(ql_dbg_disc, vha, 0x202e,
1435            "RHBA identifier = "
1436            "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
1437            ct_req->req.rhba.hba_identifier[0],
1438            ct_req->req.rhba.hba_identifier[1],
1439            ct_req->req.rhba.hba_identifier[2],
1440            ct_req->req.rhba.hba_identifier[3],
1441            ct_req->req.rhba.hba_identifier[4],
1442            ct_req->req.rhba.hba_identifier[5],
1443            ct_req->req.rhba.hba_identifier[6],
1444            ct_req->req.rhba.hba_identifier[7], size);
1445        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1446            entries, size);
1447
1448        /* Execute MS IOCB */
1449        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1450            sizeof(ms_iocb_entry_t));
1451        if (rval != QLA_SUCCESS) {
1452                /*EMPTY*/
1453                ql_dbg(ql_dbg_disc, vha, 0x2030,
1454                    "RHBA issue IOCB failed (%d).\n", rval);
1455        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1456            QLA_SUCCESS) {
1457                rval = QLA_FUNCTION_FAILED;
1458                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1459                    ct_rsp->header.explanation_code ==
1460                    CT_EXPL_ALREADY_REGISTERED) {
1461                        ql_dbg(ql_dbg_disc, vha, 0x2034,
1462                            "HBA already registered.\n");
1463                        rval = QLA_ALREADY_REGISTERED;
1464                }
1465        } else {
1466                ql_dbg(ql_dbg_disc, vha, 0x2035,
1467                    "RHBA exiting normally.\n");
1468        }
1469
1470        return rval;
1471}
1472
1473/**
1474 * qla2x00_fdmi_dhba() -
1475 * @ha: HA context
1476 *
1477 * Returns 0 on success.
1478 */
1479static int
1480qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
1481{
1482        int rval;
1483        struct qla_hw_data *ha = vha->hw;
1484        ms_iocb_entry_t *ms_pkt;
1485        struct ct_sns_req *ct_req;
1486        struct ct_sns_rsp *ct_rsp;
1487
1488        /* Issue RPA */
1489        /* Prepare common MS IOCB */
1490        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
1491            DHBA_RSP_SIZE);
1492
1493        /* Prepare CT request */
1494        ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
1495            DHBA_RSP_SIZE);
1496        ct_rsp = &ha->ct_sns->p.rsp;
1497
1498        /* Prepare FDMI command arguments -- portname. */
1499        memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
1500
1501        ql_dbg(ql_dbg_disc, vha, 0x2036,
1502            "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1503            ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
1504            ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
1505            ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
1506            ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
1507
1508        /* Execute MS IOCB */
1509        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1510            sizeof(ms_iocb_entry_t));
1511        if (rval != QLA_SUCCESS) {
1512                /*EMPTY*/
1513                ql_dbg(ql_dbg_disc, vha, 0x2037,
1514                    "DHBA issue IOCB failed (%d).\n", rval);
1515        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
1516            QLA_SUCCESS) {
1517                rval = QLA_FUNCTION_FAILED;
1518        } else {
1519                ql_dbg(ql_dbg_disc, vha, 0x2038,
1520                    "DHBA exiting normally.\n");
1521        }
1522
1523        return rval;
1524}
1525
1526/**
1527 * qla2x00_fdmi_rpa() -
1528 * @ha: HA context
1529 *
1530 * Returns 0 on success.
1531 */
1532static int
1533qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1534{
1535        int rval, alen;
1536        uint32_t size, max_frame_size;
1537        struct qla_hw_data *ha = vha->hw;
1538        ms_iocb_entry_t *ms_pkt;
1539        struct ct_sns_req *ct_req;
1540        struct ct_sns_rsp *ct_rsp;
1541        uint8_t *entries;
1542        struct ct_fdmi_port_attr *eiter;
1543        struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1544
1545        /* Issue RPA */
1546        /* Prepare common MS IOCB */
1547        /*   Request size adjusted after CT preparation */
1548        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1549
1550        /* Prepare CT request */
1551        ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
1552            RPA_RSP_SIZE);
1553        ct_rsp = &ha->ct_sns->p.rsp;
1554
1555        /* Prepare FDMI command arguments -- attribute block, attributes. */
1556        memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1557        size = WWN_SIZE + 4;
1558
1559        /* Attributes */
1560        ct_req->req.rpa.attrs.count =
1561            __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
1562        entries = ct_req->req.rpa.port_name;
1563
1564        /* FC4 types. */
1565        eiter = (struct ct_fdmi_port_attr *) (entries + size);
1566        eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
1567        eiter->len = __constant_cpu_to_be16(4 + 32);
1568        eiter->a.fc4_types[2] = 0x01;
1569        size += 4 + 32;
1570
1571        ql_dbg(ql_dbg_disc, vha, 0x2039,
1572            "FC4_TYPES=%02x %02x.\n",
1573            eiter->a.fc4_types[2],
1574            eiter->a.fc4_types[1]);
1575
1576        /* Supported speed. */
1577        eiter = (struct ct_fdmi_port_attr *) (entries + size);
1578        eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1579        eiter->len = __constant_cpu_to_be16(4 + 4);
1580        if (IS_CNA_CAPABLE(ha))
1581                eiter->a.sup_speed = __constant_cpu_to_be32(
1582                    FDMI_PORT_SPEED_10GB);
1583        else if (IS_QLA25XX(ha))
1584                eiter->a.sup_speed = __constant_cpu_to_be32(
1585                    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1586                    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
1587        else if (IS_QLA24XX_TYPE(ha))
1588                eiter->a.sup_speed = __constant_cpu_to_be32(
1589                    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1590                    FDMI_PORT_SPEED_4GB);
1591        else if (IS_QLA23XX(ha))
1592                eiter->a.sup_speed =__constant_cpu_to_be32(
1593                    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
1594        else
1595                eiter->a.sup_speed = __constant_cpu_to_be32(
1596                    FDMI_PORT_SPEED_1GB);
1597        size += 4 + 4;
1598
1599        ql_dbg(ql_dbg_disc, vha, 0x203a,
1600            "Supported_Speed=%x.\n", eiter->a.sup_speed);
1601
1602        /* Current speed. */
1603        eiter = (struct ct_fdmi_port_attr *) (entries + size);
1604        eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1605        eiter->len = __constant_cpu_to_be16(4 + 4);
1606        switch (ha->link_data_rate) {
1607        case PORT_SPEED_1GB:
1608                eiter->a.cur_speed =
1609                    __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
1610                break;
1611        case PORT_SPEED_2GB:
1612                eiter->a.cur_speed =
1613                    __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
1614                break;
1615        case PORT_SPEED_4GB:
1616                eiter->a.cur_speed =
1617                    __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
1618                break;
1619        case PORT_SPEED_8GB:
1620                eiter->a.cur_speed =
1621                    __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
1622                break;
1623        case PORT_SPEED_10GB:
1624                eiter->a.cur_speed =
1625                    __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
1626                break;
1627        case PORT_SPEED_16GB:
1628                eiter->a.cur_speed =
1629                    __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
1630                break;
1631        default:
1632                eiter->a.cur_speed =
1633                    __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1634                break;
1635        }
1636        size += 4 + 4;
1637
1638        ql_dbg(ql_dbg_disc, vha, 0x203b,
1639            "Current_Speed=%x.\n", eiter->a.cur_speed);
1640
1641        /* Max frame size. */
1642        eiter = (struct ct_fdmi_port_attr *) (entries + size);
1643        eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1644        eiter->len = __constant_cpu_to_be16(4 + 4);
1645        max_frame_size = IS_FWI2_CAPABLE(ha) ?
1646            le16_to_cpu(icb24->frame_payload_size):
1647            le16_to_cpu(ha->init_cb->frame_payload_size);
1648        eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
1649        size += 4 + 4;
1650
1651        ql_dbg(ql_dbg_disc, vha, 0x203c,
1652            "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1653
1654        /* OS device name. */
1655        eiter = (struct ct_fdmi_port_attr *) (entries + size);
1656        eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1657        alen = strlen(QLA2XXX_DRIVER_NAME);
1658        strncpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME, alen + 1);
1659        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1660        eiter->len = cpu_to_be16(4 + alen);
1661        size += 4 + alen;
1662
1663        ql_dbg(ql_dbg_disc, vha, 0x204b,
1664            "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1665
1666        /* Hostname. */
1667        if (strlen(fc_host_system_hostname(vha->host))) {
1668                ct_req->req.rpa.attrs.count =
1669                    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1670                eiter = (struct ct_fdmi_port_attr *) (entries + size);
1671                eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
1672                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1673                    "%s", fc_host_system_hostname(vha->host));
1674                alen = strlen(eiter->a.host_name);
1675                alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1676                eiter->len = cpu_to_be16(4 + alen);
1677                size += 4 + alen;
1678
1679                ql_dbg(ql_dbg_disc, vha, 0x203d,
1680                    "HostName=%s.\n", eiter->a.host_name);
1681        }
1682
1683        /* Update MS request size. */
1684        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1685
1686        ql_dbg(ql_dbg_disc, vha, 0x203e,
1687            "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
1688            ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
1689            ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
1690            ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
1691            ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
1692            size);
1693        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1694            entries, size);
1695
1696        /* Execute MS IOCB */
1697        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1698            sizeof(ms_iocb_entry_t));
1699        if (rval != QLA_SUCCESS) {
1700                /*EMPTY*/
1701                ql_dbg(ql_dbg_disc, vha, 0x2040,
1702                    "RPA issue IOCB failed (%d).\n", rval);
1703        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1704            QLA_SUCCESS) {
1705                rval = QLA_FUNCTION_FAILED;
1706        } else {
1707                ql_dbg(ql_dbg_disc, vha, 0x2041,
1708                    "RPA exiting nornally.\n");
1709        }
1710
1711        return rval;
1712}
1713
1714/**
1715 * qla2x00_fdmi_register() -
1716 * @ha: HA context
1717 *
1718 * Returns 0 on success.
1719 */
1720int
1721qla2x00_fdmi_register(scsi_qla_host_t *vha)
1722{
1723        int rval;
1724       struct qla_hw_data *ha = vha->hw;
1725
1726        if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
1727            IS_QLAFX00(ha))
1728                return QLA_FUNCTION_FAILED;
1729
1730        rval = qla2x00_mgmt_svr_login(vha);
1731        if (rval)
1732                return rval;
1733
1734        rval = qla2x00_fdmi_rhba(vha);
1735        if (rval) {
1736                if (rval != QLA_ALREADY_REGISTERED)
1737                        return rval;
1738
1739                rval = qla2x00_fdmi_dhba(vha);
1740                if (rval)
1741                        return rval;
1742
1743                rval = qla2x00_fdmi_rhba(vha);
1744                if (rval)
1745                        return rval;
1746        }
1747        rval = qla2x00_fdmi_rpa(vha);
1748
1749        return rval;
1750}
1751
1752/**
1753 * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
1754 * @ha: HA context
1755 * @list: switch info entries to populate
1756 *
1757 * Returns 0 on success.
1758 */
1759int
1760qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
1761{
1762        int             rval = QLA_SUCCESS;
1763        uint16_t        i;
1764        struct qla_hw_data *ha = vha->hw;
1765        ms_iocb_entry_t *ms_pkt;
1766        struct ct_sns_req       *ct_req;
1767        struct ct_sns_rsp       *ct_rsp;
1768
1769        if (!IS_IIDMA_CAPABLE(ha))
1770                return QLA_FUNCTION_FAILED;
1771
1772        for (i = 0; i < ha->max_fibre_devices; i++) {
1773                /* Issue GFPN_ID */
1774                /* Prepare common MS IOCB */
1775                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
1776                    GFPN_ID_RSP_SIZE);
1777
1778                /* Prepare CT request */
1779                ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
1780                    GFPN_ID_RSP_SIZE);
1781                ct_rsp = &ha->ct_sns->p.rsp;
1782
1783                /* Prepare CT arguments -- port_id */
1784                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
1785                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
1786                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
1787
1788                /* Execute MS IOCB */
1789                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1790                    sizeof(ms_iocb_entry_t));
1791                if (rval != QLA_SUCCESS) {
1792                        /*EMPTY*/
1793                        ql_dbg(ql_dbg_disc, vha, 0x2023,
1794                            "GFPN_ID issue IOCB failed (%d).\n", rval);
1795                        break;
1796                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1797                    "GFPN_ID") != QLA_SUCCESS) {
1798                        rval = QLA_FUNCTION_FAILED;
1799                        break;
1800                } else {
1801                        /* Save fabric portname */
1802                        memcpy(list[i].fabric_port_name,
1803                            ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
1804                }
1805
1806                /* Last device exit. */
1807                if (list[i].d_id.b.rsvd_1 != 0)
1808                        break;
1809        }
1810
1811        return (rval);
1812}
1813
1814static inline void *
1815qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1816    uint32_t rsp_size)
1817{
1818        struct ct_entry_24xx *ct_pkt;
1819        struct qla_hw_data *ha = vha->hw;
1820        ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1821        memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1822
1823        ct_pkt->entry_type = CT_IOCB_TYPE;
1824        ct_pkt->entry_count = 1;
1825        ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1826        ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1827        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1828        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1829        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1830        ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1831
1832        ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1833        ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1834        ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1835
1836        ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1837        ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1838        ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1839        ct_pkt->vp_index = vha->vp_idx;
1840
1841        return ct_pkt;
1842}
1843
1844
1845static inline struct ct_sns_req *
1846qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd,
1847    uint16_t rsp_size)
1848{
1849        memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1850
1851        ct_req->header.revision = 0x01;
1852        ct_req->header.gs_type = 0xFA;
1853        ct_req->header.gs_subtype = 0x01;
1854        ct_req->command = cpu_to_be16(cmd);
1855        ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1856
1857        return ct_req;
1858}
1859
1860/**
1861 * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
1862 * @ha: HA context
1863 * @list: switch info entries to populate
1864 *
1865 * Returns 0 on success.
1866 */
1867int
1868qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
1869{
1870        int             rval;
1871        uint16_t        i;
1872        struct qla_hw_data *ha = vha->hw;
1873        ms_iocb_entry_t *ms_pkt;
1874        struct ct_sns_req       *ct_req;
1875        struct ct_sns_rsp       *ct_rsp;
1876
1877        if (!IS_IIDMA_CAPABLE(ha))
1878                return QLA_FUNCTION_FAILED;
1879        if (!ha->flags.gpsc_supported)
1880                return QLA_FUNCTION_FAILED;
1881
1882        rval = qla2x00_mgmt_svr_login(vha);
1883        if (rval)
1884                return rval;
1885
1886        for (i = 0; i < ha->max_fibre_devices; i++) {
1887                /* Issue GFPN_ID */
1888                /* Prepare common MS IOCB */
1889                ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
1890                    GPSC_RSP_SIZE);
1891
1892                /* Prepare CT request */
1893                ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req,
1894                    GPSC_CMD, GPSC_RSP_SIZE);
1895                ct_rsp = &ha->ct_sns->p.rsp;
1896
1897                /* Prepare CT arguments -- port_name */
1898                memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
1899                    WWN_SIZE);
1900
1901                /* Execute MS IOCB */
1902                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1903                    sizeof(ms_iocb_entry_t));
1904                if (rval != QLA_SUCCESS) {
1905                        /*EMPTY*/
1906                        ql_dbg(ql_dbg_disc, vha, 0x2059,
1907                            "GPSC issue IOCB failed (%d).\n", rval);
1908                } else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1909                    "GPSC")) != QLA_SUCCESS) {
1910                        /* FM command unsupported? */
1911                        if (rval == QLA_INVALID_COMMAND &&
1912                            (ct_rsp->header.reason_code ==
1913                                CT_REASON_INVALID_COMMAND_CODE ||
1914                             ct_rsp->header.reason_code ==
1915                                CT_REASON_COMMAND_UNSUPPORTED)) {
1916                                ql_dbg(ql_dbg_disc, vha, 0x205a,
1917                                    "GPSC command unsupported, disabling "
1918                                    "query.\n");
1919                                ha->flags.gpsc_supported = 0;
1920                                rval = QLA_FUNCTION_FAILED;
1921                                break;
1922                        }
1923                        rval = QLA_FUNCTION_FAILED;
1924                } else {
1925                        /* Save port-speed */
1926                        switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
1927                        case BIT_15:
1928                                list[i].fp_speed = PORT_SPEED_1GB;
1929                                break;
1930                        case BIT_14:
1931                                list[i].fp_speed = PORT_SPEED_2GB;
1932                                break;
1933                        case BIT_13:
1934                                list[i].fp_speed = PORT_SPEED_4GB;
1935                                break;
1936                        case BIT_12:
1937                                list[i].fp_speed = PORT_SPEED_10GB;
1938                                break;
1939                        case BIT_11:
1940                                list[i].fp_speed = PORT_SPEED_8GB;
1941                                break;
1942                        case BIT_10:
1943                                list[i].fp_speed = PORT_SPEED_16GB;
1944                                break;
1945                        }
1946
1947                        ql_dbg(ql_dbg_disc, vha, 0x205b,
1948                            "GPSC ext entry - fpn "
1949                            "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
1950                            "speed=%04x.\n",
1951                            list[i].fabric_port_name[0],
1952                            list[i].fabric_port_name[1],
1953                            list[i].fabric_port_name[2],
1954                            list[i].fabric_port_name[3],
1955                            list[i].fabric_port_name[4],
1956                            list[i].fabric_port_name[5],
1957                            list[i].fabric_port_name[6],
1958                            list[i].fabric_port_name[7],
1959                            be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
1960                            be16_to_cpu(ct_rsp->rsp.gpsc.speed));
1961                }
1962
1963                /* Last device exit. */
1964                if (list[i].d_id.b.rsvd_1 != 0)
1965                        break;
1966        }
1967
1968        return (rval);
1969}
1970
1971/**
1972 * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
1973 *
1974 * @ha: HA context
1975 * @list: switch info entries to populate
1976 *
1977 */
1978void
1979qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
1980{
1981        int             rval;
1982        uint16_t        i;
1983
1984        ms_iocb_entry_t *ms_pkt;
1985        struct ct_sns_req       *ct_req;
1986        struct ct_sns_rsp       *ct_rsp;
1987        struct qla_hw_data *ha = vha->hw;
1988        uint8_t fcp_scsi_features = 0;
1989
1990        for (i = 0; i < ha->max_fibre_devices; i++) {
1991                /* Set default FC4 Type as UNKNOWN so the default is to
1992                 * Process this port */
1993                list[i].fc4_type = FC4_TYPE_UNKNOWN;
1994
1995                /* Do not attempt GFF_ID if we are not FWI_2 capable */
1996                if (!IS_FWI2_CAPABLE(ha))
1997                        continue;
1998
1999                /* Prepare common MS IOCB */
2000                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
2001                    GFF_ID_RSP_SIZE);
2002
2003                /* Prepare CT request */
2004                ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD,
2005                    GFF_ID_RSP_SIZE);
2006                ct_rsp = &ha->ct_sns->p.rsp;
2007
2008                /* Prepare CT arguments -- port_id */
2009                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2010                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2011                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2012
2013                /* Execute MS IOCB */
2014                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2015                   sizeof(ms_iocb_entry_t));
2016
2017                if (rval != QLA_SUCCESS) {
2018                        ql_dbg(ql_dbg_disc, vha, 0x205c,
2019                            "GFF_ID issue IOCB failed (%d).\n", rval);
2020                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2021                               "GFF_ID") != QLA_SUCCESS) {
2022                        ql_dbg(ql_dbg_disc, vha, 0x205d,
2023                            "GFF_ID IOCB status had a failure status code.\n");
2024                } else {
2025                        fcp_scsi_features =
2026                           ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2027                        fcp_scsi_features &= 0x0f;
2028
2029                        if (fcp_scsi_features)
2030                                list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2031                        else
2032                                list[i].fc4_type = FC4_TYPE_OTHER;
2033                }
2034
2035                /* Last device exit. */
2036                if (list[i].d_id.b.rsvd_1 != 0)
2037                        break;
2038        }
2039}
2040