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