linux/drivers/scsi/qla2xxx/qla_gs.c
<<
>>
Prefs
   1/*
   2 * QLogic Fibre Channel HBA Driver
   3 * Copyright (c)  2003-2014 QLogic Corporation
   4 *
   5 * See LICENSE.qla2xxx for copyright and licensing details.
   6 */
   7#include "qla_def.h"
   8#include "qla_target.h"
   9#include <linux/utsname.h>
  10
  11static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
  12static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
  13static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
  14static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
  15static int qla2x00_sns_rft_id(scsi_qla_host_t *);
  16static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
  17static int qla_async_rftid(scsi_qla_host_t *, port_id_t *);
  18static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8);
  19static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);
  20static int qla_async_rsnn_nn(scsi_qla_host_t *);
  21
  22/**
  23 * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
  24 * @ha: HA context
  25 * @req_size: request size in bytes
  26 * @rsp_size: response size in bytes
  27 *
  28 * Returns a pointer to the @ha's ms_iocb.
  29 */
  30void *
  31qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
  32{
  33        struct qla_hw_data *ha = vha->hw;
  34        ms_iocb_entry_t *ms_pkt;
  35
  36        ms_pkt = (ms_iocb_entry_t *)arg->iocb;
  37        memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
  38
  39        ms_pkt->entry_type = MS_IOCB_TYPE;
  40        ms_pkt->entry_count = 1;
  41        SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
  42        ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
  43        ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
  44        ms_pkt->cmd_dsd_count = cpu_to_le16(1);
  45        ms_pkt->total_dsd_count = cpu_to_le16(2);
  46        ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
  47        ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
  48
  49        ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
  50        ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
  51        ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
  52
  53        ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
  54        ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
  55        ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
  56
  57        vha->qla_stats.control_requests++;
  58
  59        return (ms_pkt);
  60}
  61
  62/**
  63 * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
  64 * @ha: HA context
  65 * @req_size: request size in bytes
  66 * @rsp_size: response size in bytes
  67 *
  68 * Returns a pointer to the @ha's ms_iocb.
  69 */
  70void *
  71qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
  72{
  73        struct qla_hw_data *ha = vha->hw;
  74        struct ct_entry_24xx *ct_pkt;
  75
  76        ct_pkt = (struct ct_entry_24xx *)arg->iocb;
  77        memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
  78
  79        ct_pkt->entry_type = CT_IOCB_TYPE;
  80        ct_pkt->entry_count = 1;
  81        ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
  82        ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
  83        ct_pkt->cmd_dsd_count = cpu_to_le16(1);
  84        ct_pkt->rsp_dsd_count = cpu_to_le16(1);
  85        ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
  86        ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
  87
  88        ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
  89        ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
  90        ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
  91
  92        ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
  93        ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
  94        ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
  95        ct_pkt->vp_index = vha->vp_idx;
  96
  97        vha->qla_stats.control_requests++;
  98
  99        return (ct_pkt);
 100}
 101
 102/**
 103 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
 104 * @ct_req: CT request buffer
 105 * @cmd: GS command
 106 * @rsp_size: response size in bytes
 107 *
 108 * Returns a pointer to the intitialized @ct_req.
 109 */
 110static inline struct ct_sns_req *
 111qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
 112{
 113        memset(p, 0, sizeof(struct ct_sns_pkt));
 114
 115        p->p.req.header.revision = 0x01;
 116        p->p.req.header.gs_type = 0xFC;
 117        p->p.req.header.gs_subtype = 0x02;
 118        p->p.req.command = cpu_to_be16(cmd);
 119        p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
 120
 121        return &p->p.req;
 122}
 123
 124int
 125qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 126    struct ct_sns_rsp *ct_rsp, const char *routine)
 127{
 128        int rval;
 129        uint16_t comp_status;
 130        struct qla_hw_data *ha = vha->hw;
 131        bool lid_is_sns = false;
 132
 133        rval = QLA_FUNCTION_FAILED;
 134        if (ms_pkt->entry_status != 0) {
 135                ql_dbg(ql_dbg_disc, vha, 0x2031,
 136                    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
 137                    routine, ms_pkt->entry_status, vha->d_id.b.domain,
 138                    vha->d_id.b.area, vha->d_id.b.al_pa);
 139        } else {
 140                if (IS_FWI2_CAPABLE(ha))
 141                        comp_status = le16_to_cpu(
 142                            ((struct ct_entry_24xx *)ms_pkt)->comp_status);
 143                else
 144                        comp_status = le16_to_cpu(ms_pkt->status);
 145                switch (comp_status) {
 146                case CS_COMPLETE:
 147                case CS_DATA_UNDERRUN:
 148                case CS_DATA_OVERRUN:           /* Overrun? */
 149                        if (ct_rsp->header.response !=
 150                            cpu_to_be16(CT_ACCEPT_RESPONSE)) {
 151                                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
 152                                    "%s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x\n",
 153                                    routine, vha->d_id.b.domain,
 154                                    vha->d_id.b.area, vha->d_id.b.al_pa,
 155                                    comp_status, ct_rsp->header.response);
 156                                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
 157                                    0x2078, (uint8_t *)&ct_rsp->header,
 158                                    sizeof(struct ct_rsp_hdr));
 159                                rval = QLA_INVALID_COMMAND;
 160                        } else
 161                                rval = QLA_SUCCESS;
 162                        break;
 163                case CS_PORT_LOGGED_OUT:
 164                        if (IS_FWI2_CAPABLE(ha)) {
 165                                if (le16_to_cpu(ms_pkt->loop_id.extended) ==
 166                                    NPH_SNS)
 167                                        lid_is_sns = true;
 168                        } else {
 169                                if (le16_to_cpu(ms_pkt->loop_id.extended) ==
 170                                    SIMPLE_NAME_SERVER)
 171                                        lid_is_sns = true;
 172                        }
 173                        if (lid_is_sns) {
 174                                ql_dbg(ql_dbg_async, vha, 0x502b,
 175                                        "%s failed, Name server has logged out",
 176                                        routine);
 177                                rval = QLA_NOT_LOGGED_IN;
 178                                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 179                                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
 180                        }
 181                        break;
 182                case CS_TIMEOUT:
 183                        rval = QLA_FUNCTION_TIMEOUT;
 184                        /* fall through */
 185                default:
 186                        ql_dbg(ql_dbg_disc, vha, 0x2033,
 187                            "%s failed, completion status (%x) on port_id: "
 188                            "%02x%02x%02x.\n", routine, comp_status,
 189                            vha->d_id.b.domain, vha->d_id.b.area,
 190                            vha->d_id.b.al_pa);
 191                        break;
 192                }
 193        }
 194        return rval;
 195}
 196
 197/**
 198 * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
 199 * @ha: HA context
 200 * @fcport: fcport entry to updated
 201 *
 202 * Returns 0 on success.
 203 */
 204int
 205qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
 206{
 207        int             rval;
 208
 209        ms_iocb_entry_t *ms_pkt;
 210        struct ct_sns_req       *ct_req;
 211        struct ct_sns_rsp       *ct_rsp;
 212        struct qla_hw_data *ha = vha->hw;
 213        struct ct_arg arg;
 214
 215        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 216                return qla2x00_sns_ga_nxt(vha, fcport);
 217
 218        arg.iocb = ha->ms_iocb;
 219        arg.req_dma = ha->ct_sns_dma;
 220        arg.rsp_dma = ha->ct_sns_dma;
 221        arg.req_size = GA_NXT_REQ_SIZE;
 222        arg.rsp_size = GA_NXT_RSP_SIZE;
 223        arg.nport_handle = NPH_SNS;
 224
 225        /* Issue GA_NXT */
 226        /* Prepare common MS IOCB */
 227        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 228
 229        /* Prepare CT request */
 230        ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
 231            GA_NXT_RSP_SIZE);
 232        ct_rsp = &ha->ct_sns->p.rsp;
 233
 234        /* Prepare CT arguments -- port_id */
 235        ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
 236        ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
 237        ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
 238
 239        /* Execute MS IOCB */
 240        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 241            sizeof(ms_iocb_entry_t));
 242        if (rval != QLA_SUCCESS) {
 243                /*EMPTY*/
 244                ql_dbg(ql_dbg_disc, vha, 0x2062,
 245                    "GA_NXT issue IOCB failed (%d).\n", rval);
 246        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
 247            QLA_SUCCESS) {
 248                rval = QLA_FUNCTION_FAILED;
 249        } else {
 250                /* Populate fc_port_t entry. */
 251                fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
 252                fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
 253                fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
 254
 255                memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
 256                    WWN_SIZE);
 257                memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
 258                    WWN_SIZE);
 259
 260                fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
 261                    FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
 262
 263                if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
 264                    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
 265                        fcport->d_id.b.domain = 0xf0;
 266
 267                ql_dbg(ql_dbg_disc, vha, 0x2063,
 268                    "GA_NXT entry - nn %8phN pn %8phN "
 269                    "port_id=%02x%02x%02x.\n",
 270                    fcport->node_name, fcport->port_name,
 271                    fcport->d_id.b.domain, fcport->d_id.b.area,
 272                    fcport->d_id.b.al_pa);
 273        }
 274
 275        return (rval);
 276}
 277
 278static inline int
 279qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
 280{
 281        return vha->hw->max_fibre_devices * 4 + 16;
 282}
 283
 284/**
 285 * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
 286 * @ha: HA context
 287 * @list: switch info entries to populate
 288 *
 289 * NOTE: Non-Nx_Ports are not requested.
 290 *
 291 * Returns 0 on success.
 292 */
 293int
 294qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
 295{
 296        int             rval;
 297        uint16_t        i;
 298
 299        ms_iocb_entry_t *ms_pkt;
 300        struct ct_sns_req       *ct_req;
 301        struct ct_sns_rsp       *ct_rsp;
 302
 303        struct ct_sns_gid_pt_data *gid_data;
 304        struct qla_hw_data *ha = vha->hw;
 305        uint16_t gid_pt_rsp_size;
 306        struct ct_arg arg;
 307
 308        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 309                return qla2x00_sns_gid_pt(vha, list);
 310
 311        gid_data = NULL;
 312        gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
 313
 314        arg.iocb = ha->ms_iocb;
 315        arg.req_dma = ha->ct_sns_dma;
 316        arg.rsp_dma = ha->ct_sns_dma;
 317        arg.req_size = GID_PT_REQ_SIZE;
 318        arg.rsp_size = gid_pt_rsp_size;
 319        arg.nport_handle = NPH_SNS;
 320
 321        /* Issue GID_PT */
 322        /* Prepare common MS IOCB */
 323        ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 324
 325        /* Prepare CT request */
 326        ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
 327        ct_rsp = &ha->ct_sns->p.rsp;
 328
 329        /* Prepare CT arguments -- port_type */
 330        ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
 331
 332        /* Execute MS IOCB */
 333        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 334            sizeof(ms_iocb_entry_t));
 335        if (rval != QLA_SUCCESS) {
 336                /*EMPTY*/
 337                ql_dbg(ql_dbg_disc, vha, 0x2055,
 338                    "GID_PT issue IOCB failed (%d).\n", rval);
 339        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
 340            QLA_SUCCESS) {
 341                rval = QLA_FUNCTION_FAILED;
 342        } else {
 343                /* Set port IDs in switch info list. */
 344                for (i = 0; i < ha->max_fibre_devices; i++) {
 345                        gid_data = &ct_rsp->rsp.gid_pt.entries[i];
 346                        list[i].d_id.b.domain = gid_data->port_id[0];
 347                        list[i].d_id.b.area = gid_data->port_id[1];
 348                        list[i].d_id.b.al_pa = gid_data->port_id[2];
 349                        memset(list[i].fabric_port_name, 0, WWN_SIZE);
 350                        list[i].fp_speed = PORT_SPEED_UNKNOWN;
 351
 352                        /* Last one exit. */
 353                        if (gid_data->control_byte & BIT_7) {
 354                                list[i].d_id.b.rsvd_1 = gid_data->control_byte;
 355                                break;
 356                        }
 357                }
 358
 359                /*
 360                 * If we've used all available slots, then the switch is
 361                 * reporting back more devices than we can handle with this
 362                 * single call.  Return a failed status, and let GA_NXT handle
 363                 * the overload.
 364                 */
 365                if (i == ha->max_fibre_devices)
 366                        rval = QLA_FUNCTION_FAILED;
 367        }
 368
 369        return (rval);
 370}
 371
 372/**
 373 * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
 374 * @ha: HA context
 375 * @list: switch info entries to populate
 376 *
 377 * Returns 0 on success.
 378 */
 379int
 380qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 381{
 382        int             rval = QLA_SUCCESS;
 383        uint16_t        i;
 384
 385        ms_iocb_entry_t *ms_pkt;
 386        struct ct_sns_req       *ct_req;
 387        struct ct_sns_rsp       *ct_rsp;
 388        struct qla_hw_data *ha = vha->hw;
 389        struct ct_arg arg;
 390
 391        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 392                return qla2x00_sns_gpn_id(vha, list);
 393
 394        arg.iocb = ha->ms_iocb;
 395        arg.req_dma = ha->ct_sns_dma;
 396        arg.rsp_dma = ha->ct_sns_dma;
 397        arg.req_size = GPN_ID_REQ_SIZE;
 398        arg.rsp_size = GPN_ID_RSP_SIZE;
 399        arg.nport_handle = NPH_SNS;
 400
 401        for (i = 0; i < ha->max_fibre_devices; i++) {
 402                /* Issue GPN_ID */
 403                /* Prepare common MS IOCB */
 404                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 405
 406                /* Prepare CT request */
 407                ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
 408                    GPN_ID_RSP_SIZE);
 409                ct_rsp = &ha->ct_sns->p.rsp;
 410
 411                /* Prepare CT arguments -- port_id */
 412                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
 413                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
 414                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
 415
 416                /* Execute MS IOCB */
 417                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 418                    sizeof(ms_iocb_entry_t));
 419                if (rval != QLA_SUCCESS) {
 420                        /*EMPTY*/
 421                        ql_dbg(ql_dbg_disc, vha, 0x2056,
 422                            "GPN_ID issue IOCB failed (%d).\n", rval);
 423                        break;
 424                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
 425                    "GPN_ID") != QLA_SUCCESS) {
 426                        rval = QLA_FUNCTION_FAILED;
 427                        break;
 428                } else {
 429                        /* Save portname */
 430                        memcpy(list[i].port_name,
 431                            ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
 432                }
 433
 434                /* Last device exit. */
 435                if (list[i].d_id.b.rsvd_1 != 0)
 436                        break;
 437        }
 438
 439        return (rval);
 440}
 441
 442/**
 443 * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
 444 * @ha: HA context
 445 * @list: switch info entries to populate
 446 *
 447 * Returns 0 on success.
 448 */
 449int
 450qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 451{
 452        int             rval = QLA_SUCCESS;
 453        uint16_t        i;
 454        struct qla_hw_data *ha = vha->hw;
 455        ms_iocb_entry_t *ms_pkt;
 456        struct ct_sns_req       *ct_req;
 457        struct ct_sns_rsp       *ct_rsp;
 458        struct ct_arg arg;
 459
 460        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 461                return qla2x00_sns_gnn_id(vha, list);
 462
 463        arg.iocb = ha->ms_iocb;
 464        arg.req_dma = ha->ct_sns_dma;
 465        arg.rsp_dma = ha->ct_sns_dma;
 466        arg.req_size = GNN_ID_REQ_SIZE;
 467        arg.rsp_size = GNN_ID_RSP_SIZE;
 468        arg.nport_handle = NPH_SNS;
 469
 470        for (i = 0; i < ha->max_fibre_devices; i++) {
 471                /* Issue GNN_ID */
 472                /* Prepare common MS IOCB */
 473                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 474
 475                /* Prepare CT request */
 476                ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
 477                    GNN_ID_RSP_SIZE);
 478                ct_rsp = &ha->ct_sns->p.rsp;
 479
 480                /* Prepare CT arguments -- port_id */
 481                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
 482                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
 483                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
 484
 485                /* Execute MS IOCB */
 486                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
 487                    sizeof(ms_iocb_entry_t));
 488                if (rval != QLA_SUCCESS) {
 489                        /*EMPTY*/
 490                        ql_dbg(ql_dbg_disc, vha, 0x2057,
 491                            "GNN_ID issue IOCB failed (%d).\n", rval);
 492                        break;
 493                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
 494                    "GNN_ID") != QLA_SUCCESS) {
 495                        rval = QLA_FUNCTION_FAILED;
 496                        break;
 497                } else {
 498                        /* Save nodename */
 499                        memcpy(list[i].node_name,
 500                            ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
 501
 502                        ql_dbg(ql_dbg_disc, vha, 0x2058,
 503                            "GID_PT entry - nn %8phN pn %8phN "
 504                            "portid=%02x%02x%02x.\n",
 505                            list[i].node_name, list[i].port_name,
 506                            list[i].d_id.b.domain, list[i].d_id.b.area,
 507                            list[i].d_id.b.al_pa);
 508                }
 509
 510                /* Last device exit. */
 511                if (list[i].d_id.b.rsvd_1 != 0)
 512                        break;
 513        }
 514
 515        return (rval);
 516}
 517
 518static void qla2x00_async_sns_sp_done(void *s, int rc)
 519{
 520        struct srb *sp = s;
 521        struct scsi_qla_host *vha = sp->vha;
 522        struct ct_sns_pkt *ct_sns;
 523        struct qla_work_evt *e;
 524
 525        sp->rc = rc;
 526        if (rc == QLA_SUCCESS) {
 527                ql_dbg(ql_dbg_disc, vha, 0x204f,
 528                    "Async done-%s exiting normally.\n",
 529                    sp->name);
 530        } else if (rc == QLA_FUNCTION_TIMEOUT) {
 531                ql_dbg(ql_dbg_disc, vha, 0x204f,
 532                    "Async done-%s timeout\n", sp->name);
 533        } else {
 534                ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 535                memset(ct_sns, 0, sizeof(*ct_sns));
 536                sp->retry_count++;
 537                if (sp->retry_count > 3)
 538                        goto err;
 539
 540                ql_dbg(ql_dbg_disc, vha, 0x204f,
 541                    "Async done-%s fail rc %x.  Retry count %d\n",
 542                    sp->name, rc, sp->retry_count);
 543
 544                e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);
 545                if (!e)
 546                        goto err2;
 547
 548                del_timer(&sp->u.iocb_cmd.timer);
 549                e->u.iosb.sp = sp;
 550                qla2x00_post_work(vha, e);
 551                return;
 552        }
 553
 554err:
 555        e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
 556err2:
 557        if (!e) {
 558                /* please ignore kernel warning. otherwise, we have mem leak. */
 559                if (sp->u.iocb_cmd.u.ctarg.req) {
 560                        dma_free_coherent(&vha->hw->pdev->dev,
 561                            sizeof(struct ct_sns_pkt),
 562                            sp->u.iocb_cmd.u.ctarg.req,
 563                            sp->u.iocb_cmd.u.ctarg.req_dma);
 564                        sp->u.iocb_cmd.u.ctarg.req = NULL;
 565                }
 566
 567                if (sp->u.iocb_cmd.u.ctarg.rsp) {
 568                        dma_free_coherent(&vha->hw->pdev->dev,
 569                            sizeof(struct ct_sns_pkt),
 570                            sp->u.iocb_cmd.u.ctarg.rsp,
 571                            sp->u.iocb_cmd.u.ctarg.rsp_dma);
 572                        sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 573                }
 574
 575                sp->free(sp);
 576
 577                return;
 578        }
 579
 580        e->u.iosb.sp = sp;
 581        qla2x00_post_work(vha, e);
 582}
 583
 584/**
 585 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
 586 * @ha: HA context
 587 *
 588 * Returns 0 on success.
 589 */
 590int
 591qla2x00_rft_id(scsi_qla_host_t *vha)
 592{
 593        struct qla_hw_data *ha = vha->hw;
 594
 595        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 596                return qla2x00_sns_rft_id(vha);
 597
 598        return qla_async_rftid(vha, &vha->d_id);
 599}
 600
 601static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
 602{
 603        int rval = QLA_MEMORY_ALLOC_FAILED;
 604        struct ct_sns_req *ct_req;
 605        srb_t *sp;
 606        struct ct_sns_pkt *ct_sns;
 607
 608        if (!vha->flags.online)
 609                goto done;
 610
 611        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 612        if (!sp)
 613                goto done;
 614
 615        sp->type = SRB_CT_PTHRU_CMD;
 616        sp->name = "rft_id";
 617        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 618
 619        sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
 620            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
 621            GFP_KERNEL);
 622        if (!sp->u.iocb_cmd.u.ctarg.req) {
 623                ql_log(ql_log_warn, vha, 0xd041,
 624                    "%s: Failed to allocate ct_sns request.\n",
 625                    __func__);
 626                goto done_free_sp;
 627        }
 628
 629        sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
 630            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
 631            GFP_KERNEL);
 632        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 633                ql_log(ql_log_warn, vha, 0xd042,
 634                    "%s: Failed to allocate ct_sns request.\n",
 635                    __func__);
 636                goto done_free_sp;
 637        }
 638        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 639        memset(ct_sns, 0, sizeof(*ct_sns));
 640        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 641
 642        /* Prepare CT request */
 643        ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);
 644
 645        /* Prepare CT arguments -- port_id, FC-4 types */
 646        ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
 647        ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
 648        ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
 649        ct_req->req.rft_id.fc4_types[2] = 0x01;         /* FCP-3 */
 650
 651        if (vha->flags.nvme_enabled)
 652                ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
 653
 654        sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
 655        sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;
 656        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 657        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 658        sp->done = qla2x00_async_sns_sp_done;
 659
 660        rval = qla2x00_start_sp(sp);
 661        if (rval != QLA_SUCCESS) {
 662                ql_dbg(ql_dbg_disc, vha, 0x2043,
 663                    "RFT_ID issue IOCB failed (%d).\n", rval);
 664                goto done_free_sp;
 665        }
 666        ql_dbg(ql_dbg_disc, vha, 0xffff,
 667            "Async-%s - hdl=%x portid %06x.\n",
 668            sp->name, sp->handle, d_id->b24);
 669        return rval;
 670done_free_sp:
 671        sp->free(sp);
 672done:
 673        return rval;
 674}
 675
 676/**
 677 * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
 678 * @ha: HA context
 679 *
 680 * Returns 0 on success.
 681 */
 682int
 683qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
 684{
 685        struct qla_hw_data *ha = vha->hw;
 686
 687        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 688                ql_dbg(ql_dbg_disc, vha, 0x2046,
 689                    "RFF_ID call not supported on ISP2100/ISP2200.\n");
 690                return (QLA_SUCCESS);
 691        }
 692
 693        return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha),
 694            FC4_TYPE_FCP_SCSI);
 695}
 696
 697static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
 698    u8 fc4feature, u8 fc4type)
 699{
 700        int rval = QLA_MEMORY_ALLOC_FAILED;
 701        struct ct_sns_req *ct_req;
 702        srb_t *sp;
 703        struct ct_sns_pkt *ct_sns;
 704
 705        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 706        if (!sp)
 707                goto done;
 708
 709        sp->type = SRB_CT_PTHRU_CMD;
 710        sp->name = "rff_id";
 711        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 712
 713        sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
 714            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
 715            GFP_KERNEL);
 716        if (!sp->u.iocb_cmd.u.ctarg.req) {
 717                ql_log(ql_log_warn, vha, 0xd041,
 718                    "%s: Failed to allocate ct_sns request.\n",
 719                    __func__);
 720                goto done_free_sp;
 721        }
 722
 723        sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
 724            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
 725            GFP_KERNEL);
 726        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 727                ql_log(ql_log_warn, vha, 0xd042,
 728                    "%s: Failed to allocate ct_sns request.\n",
 729                    __func__);
 730                goto done_free_sp;
 731        }
 732        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 733        memset(ct_sns, 0, sizeof(*ct_sns));
 734        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 735
 736        /* Prepare CT request */
 737        ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);
 738
 739        /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
 740        ct_req->req.rff_id.port_id[0] = d_id->b.domain;
 741        ct_req->req.rff_id.port_id[1] = d_id->b.area;
 742        ct_req->req.rff_id.port_id[2] = d_id->b.al_pa;
 743        ct_req->req.rff_id.fc4_feature = fc4feature;
 744        ct_req->req.rff_id.fc4_type = fc4type;          /* SCSI - FCP */
 745
 746        sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;
 747        sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;
 748        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 749        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 750        sp->done = qla2x00_async_sns_sp_done;
 751
 752        rval = qla2x00_start_sp(sp);
 753        if (rval != QLA_SUCCESS) {
 754                ql_dbg(ql_dbg_disc, vha, 0x2047,
 755                    "RFF_ID issue IOCB failed (%d).\n", rval);
 756                goto done_free_sp;
 757        }
 758
 759        ql_dbg(ql_dbg_disc, vha, 0xffff,
 760            "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
 761            sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
 762        return rval;
 763
 764done_free_sp:
 765        sp->free(sp);
 766done:
 767        return rval;
 768}
 769
 770/**
 771 * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
 772 * @ha: HA context
 773 *
 774 * Returns 0 on success.
 775 */
 776int
 777qla2x00_rnn_id(scsi_qla_host_t *vha)
 778{
 779        struct qla_hw_data *ha = vha->hw;
 780
 781        if (IS_QLA2100(ha) || IS_QLA2200(ha))
 782                return qla2x00_sns_rnn_id(vha);
 783
 784        return  qla_async_rnnid(vha, &vha->d_id, vha->node_name);
 785}
 786
 787static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
 788        u8 *node_name)
 789{
 790        int rval = QLA_MEMORY_ALLOC_FAILED;
 791        struct ct_sns_req *ct_req;
 792        srb_t *sp;
 793        struct ct_sns_pkt *ct_sns;
 794
 795        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 796        if (!sp)
 797                goto done;
 798
 799        sp->type = SRB_CT_PTHRU_CMD;
 800        sp->name = "rnid";
 801        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 802
 803        sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
 804            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
 805            GFP_KERNEL);
 806        if (!sp->u.iocb_cmd.u.ctarg.req) {
 807                ql_log(ql_log_warn, vha, 0xd041,
 808                    "%s: Failed to allocate ct_sns request.\n",
 809                    __func__);
 810                goto done_free_sp;
 811        }
 812
 813        sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
 814            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
 815            GFP_KERNEL);
 816        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 817                ql_log(ql_log_warn, vha, 0xd042,
 818                    "%s: Failed to allocate ct_sns request.\n",
 819                    __func__);
 820                goto done_free_sp;
 821        }
 822        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 823        memset(ct_sns, 0, sizeof(*ct_sns));
 824        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 825
 826        /* Prepare CT request */
 827        ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
 828
 829        /* Prepare CT arguments -- port_id, node_name */
 830        ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
 831        ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
 832        ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
 833        memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
 834
 835        sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;
 836        sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;
 837        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 838
 839        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 840        sp->done = qla2x00_async_sns_sp_done;
 841
 842        rval = qla2x00_start_sp(sp);
 843        if (rval != QLA_SUCCESS) {
 844                ql_dbg(ql_dbg_disc, vha, 0x204d,
 845                    "RNN_ID issue IOCB failed (%d).\n", rval);
 846                goto done_free_sp;
 847        }
 848        ql_dbg(ql_dbg_disc, vha, 0xffff,
 849            "Async-%s - hdl=%x portid %06x\n",
 850            sp->name, sp->handle, d_id->b24);
 851
 852        return rval;
 853
 854done_free_sp:
 855        sp->free(sp);
 856done:
 857        return rval;
 858}
 859
 860void
 861qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
 862{
 863        struct qla_hw_data *ha = vha->hw;
 864
 865        if (IS_QLAFX00(ha))
 866                snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number,
 867                    ha->mr.fw_version, qla2x00_version_str);
 868        else
 869                snprintf(snn, size,
 870                    "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
 871                    ha->fw_major_version, ha->fw_minor_version,
 872                    ha->fw_subminor_version, qla2x00_version_str);
 873}
 874
 875/**
 876 * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
 877 * @ha: HA context
 878 *
 879 * Returns 0 on success.
 880 */
 881int
 882qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 883{
 884        struct qla_hw_data *ha = vha->hw;
 885
 886        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 887                ql_dbg(ql_dbg_disc, vha, 0x2050,
 888                    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
 889                return (QLA_SUCCESS);
 890        }
 891
 892        return qla_async_rsnn_nn(vha);
 893}
 894
 895static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
 896{
 897        int rval = QLA_MEMORY_ALLOC_FAILED;
 898        struct ct_sns_req *ct_req;
 899        srb_t *sp;
 900        struct ct_sns_pkt *ct_sns;
 901
 902        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 903        if (!sp)
 904                goto done;
 905
 906        sp->type = SRB_CT_PTHRU_CMD;
 907        sp->name = "rsnn_nn";
 908        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 909
 910        sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
 911            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
 912            GFP_KERNEL);
 913        if (!sp->u.iocb_cmd.u.ctarg.req) {
 914                ql_log(ql_log_warn, vha, 0xd041,
 915                    "%s: Failed to allocate ct_sns request.\n",
 916                    __func__);
 917                goto done_free_sp;
 918        }
 919
 920        sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
 921            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
 922            GFP_KERNEL);
 923        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 924                ql_log(ql_log_warn, vha, 0xd042,
 925                    "%s: Failed to allocate ct_sns request.\n",
 926                    __func__);
 927                goto done_free_sp;
 928        }
 929        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 930        memset(ct_sns, 0, sizeof(*ct_sns));
 931        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 932
 933        /* Prepare CT request */
 934        ct_req = qla2x00_prep_ct_req(ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE);
 935
 936        /* Prepare CT arguments -- node_name, symbolic node_name, size */
 937        memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
 938
 939        /* Prepare the Symbolic Node Name */
 940        qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
 941            sizeof(ct_req->req.rsnn_nn.sym_node_name));
 942        ct_req->req.rsnn_nn.name_len =
 943            (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
 944
 945
 946        sp->u.iocb_cmd.u.ctarg.req_size = 24 + 1 + ct_req->req.rsnn_nn.name_len;
 947        sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;
 948        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 949
 950        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 951        sp->done = qla2x00_async_sns_sp_done;
 952
 953        rval = qla2x00_start_sp(sp);
 954        if (rval != QLA_SUCCESS) {
 955                ql_dbg(ql_dbg_disc, vha, 0x2043,
 956                    "RFT_ID issue IOCB failed (%d).\n", rval);
 957                goto done_free_sp;
 958        }
 959        ql_dbg(ql_dbg_disc, vha, 0xffff,
 960            "Async-%s - hdl=%x.\n",
 961            sp->name, sp->handle);
 962
 963        return rval;
 964
 965done_free_sp:
 966        sp->free(sp);
 967done:
 968        return rval;
 969}
 970
 971/**
 972 * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
 973 * @ha: HA context
 974 * @cmd: GS command
 975 * @scmd_len: Subcommand length
 976 * @data_size: response size in bytes
 977 *
 978 * Returns a pointer to the @ha's sns_cmd.
 979 */
 980static inline struct sns_cmd_pkt *
 981qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
 982    uint16_t data_size)
 983{
 984        uint16_t                wc;
 985        struct sns_cmd_pkt      *sns_cmd;
 986        struct qla_hw_data *ha = vha->hw;
 987
 988        sns_cmd = ha->sns_cmd;
 989        memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
 990        wc = data_size / 2;                     /* Size in 16bit words. */
 991        sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
 992        sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
 993        sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
 994        sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
 995        sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
 996        wc = (data_size - 16) / 4;              /* Size in 32bit words. */
 997        sns_cmd->p.cmd.size = cpu_to_le16(wc);
 998
 999        vha->qla_stats.control_requests++;
1000
1001        return (sns_cmd);
1002}
1003
1004/**
1005 * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
1006 * @ha: HA context
1007 * @fcport: fcport entry to updated
1008 *
1009 * This command uses the old Exectute SNS Command mailbox routine.
1010 *
1011 * Returns 0 on success.
1012 */
1013static int
1014qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
1015{
1016        int             rval = QLA_SUCCESS;
1017        struct qla_hw_data *ha = vha->hw;
1018        struct sns_cmd_pkt      *sns_cmd;
1019
1020        /* Issue GA_NXT. */
1021        /* Prepare SNS command request. */
1022        sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
1023            GA_NXT_SNS_DATA_SIZE);
1024
1025        /* Prepare SNS command arguments -- port_id. */
1026        sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
1027        sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
1028        sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
1029
1030        /* Execute SNS command. */
1031        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
1032            sizeof(struct sns_cmd_pkt));
1033        if (rval != QLA_SUCCESS) {
1034                /*EMPTY*/
1035                ql_dbg(ql_dbg_disc, vha, 0x205f,
1036                    "GA_NXT Send SNS failed (%d).\n", rval);
1037        } else if (sns_cmd->p.gan_data[8] != 0x80 ||
1038            sns_cmd->p.gan_data[9] != 0x02) {
1039                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
1040                    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
1041                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
1042                    sns_cmd->p.gan_data, 16);
1043                rval = QLA_FUNCTION_FAILED;
1044        } else {
1045                /* Populate fc_port_t entry. */
1046                fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
1047                fcport->d_id.b.area = sns_cmd->p.gan_data[18];
1048                fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
1049
1050                memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
1051                memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
1052
1053                if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
1054                    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
1055                        fcport->d_id.b.domain = 0xf0;
1056
1057                ql_dbg(ql_dbg_disc, vha, 0x2061,
1058                    "GA_NXT entry - nn %8phN pn %8phN "
1059                    "port_id=%02x%02x%02x.\n",
1060                    fcport->node_name, fcport->port_name,
1061                    fcport->d_id.b.domain, fcport->d_id.b.area,
1062                    fcport->d_id.b.al_pa);
1063        }
1064
1065        return (rval);
1066}
1067
1068/**
1069 * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
1070 * @ha: HA context
1071 * @list: switch info entries to populate
1072 *
1073 * This command uses the old Exectute SNS Command mailbox routine.
1074 *
1075 * NOTE: Non-Nx_Ports are not requested.
1076 *
1077 * Returns 0 on success.
1078 */
1079static int
1080qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
1081{
1082        int             rval;
1083        struct qla_hw_data *ha = vha->hw;
1084        uint16_t        i;
1085        uint8_t         *entry;
1086        struct sns_cmd_pkt      *sns_cmd;
1087        uint16_t gid_pt_sns_data_size;
1088
1089        gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
1090
1091        /* Issue GID_PT. */
1092        /* Prepare SNS command request. */
1093        sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
1094            gid_pt_sns_data_size);
1095
1096        /* Prepare SNS command arguments -- port_type. */
1097        sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
1098
1099        /* Execute SNS command. */
1100        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
1101            sizeof(struct sns_cmd_pkt));
1102        if (rval != QLA_SUCCESS) {
1103                /*EMPTY*/
1104                ql_dbg(ql_dbg_disc, vha, 0x206d,
1105                    "GID_PT Send SNS failed (%d).\n", rval);
1106        } else if (sns_cmd->p.gid_data[8] != 0x80 ||
1107            sns_cmd->p.gid_data[9] != 0x02) {
1108                ql_dbg(ql_dbg_disc, vha, 0x202f,
1109                    "GID_PT failed, rejected request, gid_rsp:\n");
1110                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
1111                    sns_cmd->p.gid_data, 16);
1112                rval = QLA_FUNCTION_FAILED;
1113        } else {
1114                /* Set port IDs in switch info list. */
1115                for (i = 0; i < ha->max_fibre_devices; i++) {
1116                        entry = &sns_cmd->p.gid_data[(i * 4) + 16];
1117                        list[i].d_id.b.domain = entry[1];
1118                        list[i].d_id.b.area = entry[2];
1119                        list[i].d_id.b.al_pa = entry[3];
1120
1121                        /* Last one exit. */
1122                        if (entry[0] & BIT_7) {
1123                                list[i].d_id.b.rsvd_1 = entry[0];
1124                                break;
1125                        }
1126                }
1127
1128                /*
1129                 * If we've used all available slots, then the switch is
1130                 * reporting back more devices that we can handle with this
1131                 * single call.  Return a failed status, and let GA_NXT handle
1132                 * the overload.
1133                 */
1134                if (i == ha->max_fibre_devices)
1135                        rval = QLA_FUNCTION_FAILED;
1136        }
1137
1138        return (rval);
1139}
1140
1141/**
1142 * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
1143 * @ha: HA context
1144 * @list: switch info entries to populate
1145 *
1146 * This command uses the old Exectute SNS Command mailbox routine.
1147 *
1148 * Returns 0 on success.
1149 */
1150static int
1151qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
1152{
1153        int             rval = QLA_SUCCESS;
1154        struct qla_hw_data *ha = vha->hw;
1155        uint16_t        i;
1156        struct sns_cmd_pkt      *sns_cmd;
1157
1158        for (i = 0; i < ha->max_fibre_devices; i++) {
1159                /* Issue GPN_ID */
1160                /* Prepare SNS command request. */
1161                sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
1162                    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
1163
1164                /* Prepare SNS command arguments -- port_id. */
1165                sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
1166                sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
1167                sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
1168
1169                /* Execute SNS command. */
1170                rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
1171                    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
1172                if (rval != QLA_SUCCESS) {
1173                        /*EMPTY*/
1174                        ql_dbg(ql_dbg_disc, vha, 0x2032,
1175                            "GPN_ID Send SNS failed (%d).\n", rval);
1176                } else if (sns_cmd->p.gpn_data[8] != 0x80 ||
1177                    sns_cmd->p.gpn_data[9] != 0x02) {
1178                        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
1179                            "GPN_ID failed, rejected request, gpn_rsp:\n");
1180                        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
1181                            sns_cmd->p.gpn_data, 16);
1182                        rval = QLA_FUNCTION_FAILED;
1183                } else {
1184                        /* Save portname */
1185                        memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
1186                            WWN_SIZE);
1187                }
1188
1189                /* Last device exit. */
1190                if (list[i].d_id.b.rsvd_1 != 0)
1191                        break;
1192        }
1193
1194        return (rval);
1195}
1196
1197/**
1198 * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
1199 * @ha: HA context
1200 * @list: switch info entries to populate
1201 *
1202 * This command uses the old Exectute SNS Command mailbox routine.
1203 *
1204 * Returns 0 on success.
1205 */
1206static int
1207qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
1208{
1209        int             rval = QLA_SUCCESS;
1210        struct qla_hw_data *ha = vha->hw;
1211        uint16_t        i;
1212        struct sns_cmd_pkt      *sns_cmd;
1213
1214        for (i = 0; i < ha->max_fibre_devices; i++) {
1215                /* Issue GNN_ID */
1216                /* Prepare SNS command request. */
1217                sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
1218                    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
1219
1220                /* Prepare SNS command arguments -- port_id. */
1221                sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
1222                sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
1223                sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
1224
1225                /* Execute SNS command. */
1226                rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
1227                    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
1228                if (rval != QLA_SUCCESS) {
1229                        /*EMPTY*/
1230                        ql_dbg(ql_dbg_disc, vha, 0x203f,
1231                            "GNN_ID Send SNS failed (%d).\n", rval);
1232                } else if (sns_cmd->p.gnn_data[8] != 0x80 ||
1233                    sns_cmd->p.gnn_data[9] != 0x02) {
1234                        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
1235                            "GNN_ID failed, rejected request, gnn_rsp:\n");
1236                        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
1237                            sns_cmd->p.gnn_data, 16);
1238                        rval = QLA_FUNCTION_FAILED;
1239                } else {
1240                        /* Save nodename */
1241                        memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
1242                            WWN_SIZE);
1243
1244                        ql_dbg(ql_dbg_disc, vha, 0x206e,
1245                            "GID_PT entry - nn %8phN pn %8phN "
1246                            "port_id=%02x%02x%02x.\n",
1247                            list[i].node_name, list[i].port_name,
1248                            list[i].d_id.b.domain, list[i].d_id.b.area,
1249                            list[i].d_id.b.al_pa);
1250                }
1251
1252                /* Last device exit. */
1253                if (list[i].d_id.b.rsvd_1 != 0)
1254                        break;
1255        }
1256
1257        return (rval);
1258}
1259
1260/**
1261 * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1262 * @ha: HA context
1263 *
1264 * This command uses the old Exectute SNS Command mailbox routine.
1265 *
1266 * Returns 0 on success.
1267 */
1268static int
1269qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1270{
1271        int             rval;
1272        struct qla_hw_data *ha = vha->hw;
1273        struct sns_cmd_pkt      *sns_cmd;
1274
1275        /* Issue RFT_ID. */
1276        /* Prepare SNS command request. */
1277        sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1278            RFT_ID_SNS_DATA_SIZE);
1279
1280        /* Prepare SNS command arguments -- port_id, FC-4 types */
1281        sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1282        sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1283        sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1284
1285        sns_cmd->p.cmd.param[5] = 0x01;                 /* FCP-3 */
1286
1287        /* Execute SNS command. */
1288        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1289            sizeof(struct sns_cmd_pkt));
1290        if (rval != QLA_SUCCESS) {
1291                /*EMPTY*/
1292                ql_dbg(ql_dbg_disc, vha, 0x2060,
1293                    "RFT_ID Send SNS failed (%d).\n", rval);
1294        } else if (sns_cmd->p.rft_data[8] != 0x80 ||
1295            sns_cmd->p.rft_data[9] != 0x02) {
1296                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1297                    "RFT_ID failed, rejected request rft_rsp:\n");
1298                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1299                    sns_cmd->p.rft_data, 16);
1300                rval = QLA_FUNCTION_FAILED;
1301        } else {
1302                ql_dbg(ql_dbg_disc, vha, 0x2073,
1303                    "RFT_ID exiting normally.\n");
1304        }
1305
1306        return (rval);
1307}
1308
1309/**
1310 * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1311 * HBA.
1312 * @ha: HA context
1313 *
1314 * This command uses the old Exectute SNS Command mailbox routine.
1315 *
1316 * Returns 0 on success.
1317 */
1318static int
1319qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1320{
1321        int             rval;
1322        struct qla_hw_data *ha = vha->hw;
1323        struct sns_cmd_pkt      *sns_cmd;
1324
1325        /* Issue RNN_ID. */
1326        /* Prepare SNS command request. */
1327        sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1328            RNN_ID_SNS_DATA_SIZE);
1329
1330        /* Prepare SNS command arguments -- port_id, nodename. */
1331        sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1332        sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1333        sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1334
1335        sns_cmd->p.cmd.param[4] = vha->node_name[7];
1336        sns_cmd->p.cmd.param[5] = vha->node_name[6];
1337        sns_cmd->p.cmd.param[6] = vha->node_name[5];
1338        sns_cmd->p.cmd.param[7] = vha->node_name[4];
1339        sns_cmd->p.cmd.param[8] = vha->node_name[3];
1340        sns_cmd->p.cmd.param[9] = vha->node_name[2];
1341        sns_cmd->p.cmd.param[10] = vha->node_name[1];
1342        sns_cmd->p.cmd.param[11] = vha->node_name[0];
1343
1344        /* Execute SNS command. */
1345        rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1346            sizeof(struct sns_cmd_pkt));
1347        if (rval != QLA_SUCCESS) {
1348                /*EMPTY*/
1349                ql_dbg(ql_dbg_disc, vha, 0x204a,
1350                    "RNN_ID Send SNS failed (%d).\n", rval);
1351        } else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1352            sns_cmd->p.rnn_data[9] != 0x02) {
1353                ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1354                    "RNN_ID failed, rejected request, rnn_rsp:\n");
1355                ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1356                    sns_cmd->p.rnn_data, 16);
1357                rval = QLA_FUNCTION_FAILED;
1358        } else {
1359                ql_dbg(ql_dbg_disc, vha, 0x204c,
1360                    "RNN_ID exiting normally.\n");
1361        }
1362
1363        return (rval);
1364}
1365
1366/**
1367 * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1368 * @ha: HA context
1369 *
1370 * Returns 0 on success.
1371 */
1372int
1373qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1374{
1375        int ret, rval;
1376        uint16_t mb[MAILBOX_REGISTER_COUNT];
1377        struct qla_hw_data *ha = vha->hw;
1378        ret = QLA_SUCCESS;
1379        if (vha->flags.management_server_logged_in)
1380                return ret;
1381
1382        rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1383            0xfa, mb, BIT_1);
1384        if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1385                if (rval == QLA_MEMORY_ALLOC_FAILED)
1386                        ql_dbg(ql_dbg_disc, vha, 0x2085,
1387                            "Failed management_server login: loopid=%x "
1388                            "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1389                else
1390                        ql_dbg(ql_dbg_disc, vha, 0x2024,
1391                            "Failed management_server login: loopid=%x "
1392                            "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1393                            vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1394                            mb[7]);
1395                ret = QLA_FUNCTION_FAILED;
1396        } else
1397                vha->flags.management_server_logged_in = 1;
1398
1399        return ret;
1400}
1401
1402/**
1403 * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1404 * @ha: HA context
1405 * @req_size: request size in bytes
1406 * @rsp_size: response size in bytes
1407 *
1408 * Returns a pointer to the @ha's ms_iocb.
1409 */
1410void *
1411qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1412    uint32_t rsp_size)
1413{
1414        ms_iocb_entry_t *ms_pkt;
1415        struct qla_hw_data *ha = vha->hw;
1416        ms_pkt = ha->ms_iocb;
1417        memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1418
1419        ms_pkt->entry_type = MS_IOCB_TYPE;
1420        ms_pkt->entry_count = 1;
1421        SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1422        ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
1423        ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1424        ms_pkt->cmd_dsd_count = cpu_to_le16(1);
1425        ms_pkt->total_dsd_count = cpu_to_le16(2);
1426        ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1427        ms_pkt->req_bytecount = cpu_to_le32(req_size);
1428
1429        ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1430        ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1431        ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1432
1433        ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1434        ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1435        ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1436
1437        return ms_pkt;
1438}
1439
1440/**
1441 * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1442 * @ha: HA context
1443 * @req_size: request size in bytes
1444 * @rsp_size: response size in bytes
1445 *
1446 * Returns a pointer to the @ha's ms_iocb.
1447 */
1448void *
1449qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1450    uint32_t rsp_size)
1451{
1452        struct ct_entry_24xx *ct_pkt;
1453        struct qla_hw_data *ha = vha->hw;
1454
1455        ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1456        memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1457
1458        ct_pkt->entry_type = CT_IOCB_TYPE;
1459        ct_pkt->entry_count = 1;
1460        ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1461        ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1462        ct_pkt->cmd_dsd_count = cpu_to_le16(1);
1463        ct_pkt->rsp_dsd_count = cpu_to_le16(1);
1464        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1465        ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1466
1467        ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1468        ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1469        ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1470
1471        ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1472        ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1473        ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1474        ct_pkt->vp_index = vha->vp_idx;
1475
1476        return ct_pkt;
1477}
1478
1479static inline ms_iocb_entry_t *
1480qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1481{
1482        struct qla_hw_data *ha = vha->hw;
1483        ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1484        struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1485
1486        if (IS_FWI2_CAPABLE(ha)) {
1487                ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1488                ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1489        } else {
1490                ms_pkt->req_bytecount = cpu_to_le32(req_size);
1491                ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1492        }
1493
1494        return ms_pkt;
1495}
1496
1497/**
1498 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1499 * @ct_req: CT request buffer
1500 * @cmd: GS command
1501 * @rsp_size: response size in bytes
1502 *
1503 * Returns a pointer to the intitialized @ct_req.
1504 */
1505static inline struct ct_sns_req *
1506qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
1507    uint16_t rsp_size)
1508{
1509        memset(p, 0, sizeof(struct ct_sns_pkt));
1510
1511        p->p.req.header.revision = 0x01;
1512        p->p.req.header.gs_type = 0xFA;
1513        p->p.req.header.gs_subtype = 0x10;
1514        p->p.req.command = cpu_to_be16(cmd);
1515        p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1516
1517        return &p->p.req;
1518}
1519
1520/**
1521 * qla2x00_fdmi_rhba() -
1522 * @ha: HA context
1523 *
1524 * Returns 0 on success.
1525 */
1526static int
1527qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1528{
1529        int rval, alen;
1530        uint32_t size, sn;
1531
1532        ms_iocb_entry_t *ms_pkt;
1533        struct ct_sns_req *ct_req;
1534        struct ct_sns_rsp *ct_rsp;
1535        void *entries;
1536        struct ct_fdmi_hba_attr *eiter;
1537        struct qla_hw_data *ha = vha->hw;
1538
1539        /* Issue RHBA */
1540        /* Prepare common MS IOCB */
1541        /*   Request size adjusted after CT preparation */
1542        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1543
1544        /* Prepare CT request */
1545        ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
1546        ct_rsp = &ha->ct_sns->p.rsp;
1547
1548        /* Prepare FDMI command arguments -- attribute block, attributes. */
1549        memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1550        ct_req->req.rhba.entry_count = cpu_to_be32(1);
1551        memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1552        size = 2 * WWN_SIZE + 4 + 4;
1553
1554        /* Attributes */
1555        ct_req->req.rhba.attrs.count =
1556            cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1557        entries = ct_req->req.rhba.hba_identifier;
1558
1559        /* Nodename. */
1560        eiter = entries + size;
1561        eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1562        eiter->len = cpu_to_be16(4 + WWN_SIZE);
1563        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1564        size += 4 + WWN_SIZE;
1565
1566        ql_dbg(ql_dbg_disc, vha, 0x2025,
1567            "NodeName = %8phN.\n", eiter->a.node_name);
1568
1569        /* Manufacturer. */
1570        eiter = entries + size;
1571        eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1572        alen = strlen(QLA2XXX_MANUFACTURER);
1573        snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1574            "%s", "QLogic Corporation");
1575        alen += 4 - (alen & 3);
1576        eiter->len = cpu_to_be16(4 + alen);
1577        size += 4 + alen;
1578
1579        ql_dbg(ql_dbg_disc, vha, 0x2026,
1580            "Manufacturer = %s.\n", eiter->a.manufacturer);
1581
1582        /* Serial number. */
1583        eiter = entries + size;
1584        eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1585        if (IS_FWI2_CAPABLE(ha))
1586                qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
1587                    sizeof(eiter->a.serial_num));
1588        else {
1589                sn = ((ha->serial0 & 0x1f) << 16) |
1590                        (ha->serial2 << 8) | ha->serial1;
1591                snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
1592                    "%c%05d", 'A' + sn / 100000, sn % 100000);
1593        }
1594        alen = strlen(eiter->a.serial_num);
1595        alen += 4 - (alen & 3);
1596        eiter->len = cpu_to_be16(4 + alen);
1597        size += 4 + alen;
1598
1599        ql_dbg(ql_dbg_disc, vha, 0x2027,
1600            "Serial no. = %s.\n", eiter->a.serial_num);
1601
1602        /* Model name. */
1603        eiter = entries + size;
1604        eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
1605        snprintf(eiter->a.model, sizeof(eiter->a.model),
1606            "%s", ha->model_number);
1607        alen = strlen(eiter->a.model);
1608        alen += 4 - (alen & 3);
1609        eiter->len = cpu_to_be16(4 + alen);
1610        size += 4 + alen;
1611
1612        ql_dbg(ql_dbg_disc, vha, 0x2028,
1613            "Model Name = %s.\n", eiter->a.model);
1614
1615        /* Model description. */
1616        eiter = entries + size;
1617        eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1618        snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
1619            "%s", ha->model_desc);
1620        alen = strlen(eiter->a.model_desc);
1621        alen += 4 - (alen & 3);
1622        eiter->len = cpu_to_be16(4 + alen);
1623        size += 4 + alen;
1624
1625        ql_dbg(ql_dbg_disc, vha, 0x2029,
1626            "Model Desc = %s.\n", eiter->a.model_desc);
1627
1628        /* Hardware version. */
1629        eiter = entries + size;
1630        eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1631        if (!IS_FWI2_CAPABLE(ha)) {
1632                snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1633                    "HW:%s", ha->adapter_id);
1634        } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
1635                    sizeof(eiter->a.hw_version))) {
1636                ;
1637        } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
1638                    sizeof(eiter->a.hw_version))) {
1639                ;
1640        } else {
1641                snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1642                    "HW:%s", ha->adapter_id);
1643        }
1644        alen = strlen(eiter->a.hw_version);
1645        alen += 4 - (alen & 3);
1646        eiter->len = cpu_to_be16(4 + alen);
1647        size += 4 + alen;
1648
1649        ql_dbg(ql_dbg_disc, vha, 0x202a,
1650            "Hardware ver = %s.\n", eiter->a.hw_version);
1651
1652        /* Driver version. */
1653        eiter = entries + size;
1654        eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1655        snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
1656            "%s", qla2x00_version_str);
1657        alen = strlen(eiter->a.driver_version);
1658        alen += 4 - (alen & 3);
1659        eiter->len = cpu_to_be16(4 + alen);
1660        size += 4 + alen;
1661
1662        ql_dbg(ql_dbg_disc, vha, 0x202b,
1663            "Driver ver = %s.\n", eiter->a.driver_version);
1664
1665        /* Option ROM version. */
1666        eiter = entries + size;
1667        eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1668        snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
1669            "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1670        alen = strlen(eiter->a.orom_version);
1671        alen += 4 - (alen & 3);
1672        eiter->len = cpu_to_be16(4 + alen);
1673        size += 4 + alen;
1674
1675        ql_dbg(ql_dbg_disc, vha , 0x202c,
1676            "Optrom vers = %s.\n", eiter->a.orom_version);
1677
1678        /* Firmware version */
1679        eiter = entries + size;
1680        eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1681        ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
1682            sizeof(eiter->a.fw_version));
1683        alen = strlen(eiter->a.fw_version);
1684        alen += 4 - (alen & 3);
1685        eiter->len = cpu_to_be16(4 + alen);
1686        size += 4 + alen;
1687
1688        ql_dbg(ql_dbg_disc, vha, 0x202d,
1689            "Firmware vers = %s.\n", eiter->a.fw_version);
1690
1691        /* Update MS request size. */
1692        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1693
1694        ql_dbg(ql_dbg_disc, vha, 0x202e,
1695            "RHBA identifier = %8phN size=%d.\n",
1696            ct_req->req.rhba.hba_identifier, size);
1697        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1698            entries, size);
1699
1700        /* Execute MS IOCB */
1701        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1702            sizeof(ms_iocb_entry_t));
1703        if (rval != QLA_SUCCESS) {
1704                /*EMPTY*/
1705                ql_dbg(ql_dbg_disc, vha, 0x2030,
1706                    "RHBA issue IOCB failed (%d).\n", rval);
1707        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1708            QLA_SUCCESS) {
1709                rval = QLA_FUNCTION_FAILED;
1710                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1711                    ct_rsp->header.explanation_code ==
1712                    CT_EXPL_ALREADY_REGISTERED) {
1713                        ql_dbg(ql_dbg_disc, vha, 0x2034,
1714                            "HBA already registered.\n");
1715                        rval = QLA_ALREADY_REGISTERED;
1716                } else {
1717                        ql_dbg(ql_dbg_disc, vha, 0x20ad,
1718                            "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
1719                            ct_rsp->header.reason_code,
1720                            ct_rsp->header.explanation_code);
1721                }
1722        } else {
1723                ql_dbg(ql_dbg_disc, vha, 0x2035,
1724                    "RHBA exiting normally.\n");
1725        }
1726
1727        return rval;
1728}
1729
1730/**
1731 * qla2x00_fdmi_rpa() -
1732 * @ha: HA context
1733 *
1734 * Returns 0 on success.
1735 */
1736static int
1737qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1738{
1739        int rval, alen;
1740        uint32_t size;
1741        struct qla_hw_data *ha = vha->hw;
1742        ms_iocb_entry_t *ms_pkt;
1743        struct ct_sns_req *ct_req;
1744        struct ct_sns_rsp *ct_rsp;
1745        void *entries;
1746        struct ct_fdmi_port_attr *eiter;
1747        struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1748        struct new_utsname *p_sysid = NULL;
1749
1750        /* Issue RPA */
1751        /* Prepare common MS IOCB */
1752        /*   Request size adjusted after CT preparation */
1753        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1754
1755        /* Prepare CT request */
1756        ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD,
1757            RPA_RSP_SIZE);
1758        ct_rsp = &ha->ct_sns->p.rsp;
1759
1760        /* Prepare FDMI command arguments -- attribute block, attributes. */
1761        memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1762        size = WWN_SIZE + 4;
1763
1764        /* Attributes */
1765        ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1766        entries = ct_req->req.rpa.port_name;
1767
1768        /* FC4 types. */
1769        eiter = entries + size;
1770        eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
1771        eiter->len = cpu_to_be16(4 + 32);
1772        eiter->a.fc4_types[2] = 0x01;
1773        size += 4 + 32;
1774
1775        ql_dbg(ql_dbg_disc, vha, 0x2039,
1776            "FC4_TYPES=%02x %02x.\n",
1777            eiter->a.fc4_types[2],
1778            eiter->a.fc4_types[1]);
1779
1780        /* Supported speed. */
1781        eiter = entries + size;
1782        eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1783        eiter->len = cpu_to_be16(4 + 4);
1784        if (IS_CNA_CAPABLE(ha))
1785                eiter->a.sup_speed = cpu_to_be32(
1786                    FDMI_PORT_SPEED_10GB);
1787        else if (IS_QLA27XX(ha))
1788                eiter->a.sup_speed = cpu_to_be32(
1789                    FDMI_PORT_SPEED_32GB|
1790                    FDMI_PORT_SPEED_16GB|
1791                    FDMI_PORT_SPEED_8GB);
1792        else if (IS_QLA2031(ha))
1793                eiter->a.sup_speed = cpu_to_be32(
1794                    FDMI_PORT_SPEED_16GB|
1795                    FDMI_PORT_SPEED_8GB|
1796                    FDMI_PORT_SPEED_4GB);
1797        else if (IS_QLA25XX(ha))
1798                eiter->a.sup_speed = cpu_to_be32(
1799                    FDMI_PORT_SPEED_8GB|
1800                    FDMI_PORT_SPEED_4GB|
1801                    FDMI_PORT_SPEED_2GB|
1802                    FDMI_PORT_SPEED_1GB);
1803        else if (IS_QLA24XX_TYPE(ha))
1804                eiter->a.sup_speed = cpu_to_be32(
1805                    FDMI_PORT_SPEED_4GB|
1806                    FDMI_PORT_SPEED_2GB|
1807                    FDMI_PORT_SPEED_1GB);
1808        else if (IS_QLA23XX(ha))
1809                eiter->a.sup_speed = cpu_to_be32(
1810                    FDMI_PORT_SPEED_2GB|
1811                    FDMI_PORT_SPEED_1GB);
1812        else
1813                eiter->a.sup_speed = cpu_to_be32(
1814                    FDMI_PORT_SPEED_1GB);
1815        size += 4 + 4;
1816
1817        ql_dbg(ql_dbg_disc, vha, 0x203a,
1818            "Supported_Speed=%x.\n", eiter->a.sup_speed);
1819
1820        /* Current speed. */
1821        eiter = entries + size;
1822        eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1823        eiter->len = cpu_to_be16(4 + 4);
1824        switch (ha->link_data_rate) {
1825        case PORT_SPEED_1GB:
1826                eiter->a.cur_speed =
1827                    cpu_to_be32(FDMI_PORT_SPEED_1GB);
1828                break;
1829        case PORT_SPEED_2GB:
1830                eiter->a.cur_speed =
1831                    cpu_to_be32(FDMI_PORT_SPEED_2GB);
1832                break;
1833        case PORT_SPEED_4GB:
1834                eiter->a.cur_speed =
1835                    cpu_to_be32(FDMI_PORT_SPEED_4GB);
1836                break;
1837        case PORT_SPEED_8GB:
1838                eiter->a.cur_speed =
1839                    cpu_to_be32(FDMI_PORT_SPEED_8GB);
1840                break;
1841        case PORT_SPEED_10GB:
1842                eiter->a.cur_speed =
1843                    cpu_to_be32(FDMI_PORT_SPEED_10GB);
1844                break;
1845        case PORT_SPEED_16GB:
1846                eiter->a.cur_speed =
1847                    cpu_to_be32(FDMI_PORT_SPEED_16GB);
1848                break;
1849        case PORT_SPEED_32GB:
1850                eiter->a.cur_speed =
1851                    cpu_to_be32(FDMI_PORT_SPEED_32GB);
1852                break;
1853        default:
1854                eiter->a.cur_speed =
1855                    cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1856                break;
1857        }
1858        size += 4 + 4;
1859
1860        ql_dbg(ql_dbg_disc, vha, 0x203b,
1861            "Current_Speed=%x.\n", eiter->a.cur_speed);
1862
1863        /* Max frame size. */
1864        eiter = entries + size;
1865        eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1866        eiter->len = cpu_to_be16(4 + 4);
1867        eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
1868            le16_to_cpu(icb24->frame_payload_size) :
1869            le16_to_cpu(ha->init_cb->frame_payload_size);
1870        eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
1871        size += 4 + 4;
1872
1873        ql_dbg(ql_dbg_disc, vha, 0x203c,
1874            "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1875
1876        /* OS device name. */
1877        eiter = entries + size;
1878        eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1879        snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
1880            "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
1881        alen = strlen(eiter->a.os_dev_name);
1882        alen += 4 - (alen & 3);
1883        eiter->len = cpu_to_be16(4 + alen);
1884        size += 4 + alen;
1885
1886        ql_dbg(ql_dbg_disc, vha, 0x204b,
1887            "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1888
1889        /* Hostname. */
1890        eiter = entries + size;
1891        eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
1892        p_sysid = utsname();
1893        if (p_sysid) {
1894                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1895                    "%s", p_sysid->nodename);
1896        } else {
1897                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1898                    "%s", fc_host_system_hostname(vha->host));
1899        }
1900        alen = strlen(eiter->a.host_name);
1901        alen += 4 - (alen & 3);
1902        eiter->len = cpu_to_be16(4 + alen);
1903        size += 4 + alen;
1904
1905        ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
1906
1907        /* Update MS request size. */
1908        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1909
1910        ql_dbg(ql_dbg_disc, vha, 0x203e,
1911            "RPA portname  %016llx, size = %d.\n",
1912            wwn_to_u64(ct_req->req.rpa.port_name), size);
1913        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1914            entries, size);
1915
1916        /* Execute MS IOCB */
1917        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1918            sizeof(ms_iocb_entry_t));
1919        if (rval != QLA_SUCCESS) {
1920                /*EMPTY*/
1921                ql_dbg(ql_dbg_disc, vha, 0x2040,
1922                    "RPA issue IOCB failed (%d).\n", rval);
1923        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1924            QLA_SUCCESS) {
1925                rval = QLA_FUNCTION_FAILED;
1926                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1927                    ct_rsp->header.explanation_code ==
1928                    CT_EXPL_ALREADY_REGISTERED) {
1929                        ql_dbg(ql_dbg_disc, vha, 0x20cd,
1930                            "RPA already registered.\n");
1931                        rval = QLA_ALREADY_REGISTERED;
1932                }
1933
1934        } else {
1935                ql_dbg(ql_dbg_disc, vha, 0x2041,
1936                    "RPA exiting normally.\n");
1937        }
1938
1939        return rval;
1940}
1941
1942/**
1943 * qla2x00_fdmiv2_rhba() -
1944 * @ha: HA context
1945 *
1946 * Returns 0 on success.
1947 */
1948static int
1949qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
1950{
1951        int rval, alen;
1952        uint32_t size, sn;
1953        ms_iocb_entry_t *ms_pkt;
1954        struct ct_sns_req *ct_req;
1955        struct ct_sns_rsp *ct_rsp;
1956        void *entries;
1957        struct ct_fdmiv2_hba_attr *eiter;
1958        struct qla_hw_data *ha = vha->hw;
1959        struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1960        struct new_utsname *p_sysid = NULL;
1961
1962        /* Issue RHBA */
1963        /* Prepare common MS IOCB */
1964        /*   Request size adjusted after CT preparation */
1965        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1966
1967        /* Prepare CT request */
1968        ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD,
1969            RHBA_RSP_SIZE);
1970        ct_rsp = &ha->ct_sns->p.rsp;
1971
1972        /* Prepare FDMI command arguments -- attribute block, attributes. */
1973        memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE);
1974        ct_req->req.rhba2.entry_count = cpu_to_be32(1);
1975        memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE);
1976        size = 2 * WWN_SIZE + 4 + 4;
1977
1978        /* Attributes */
1979        ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
1980        entries = ct_req->req.rhba2.hba_identifier;
1981
1982        /* Nodename. */
1983        eiter = entries + size;
1984        eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1985        eiter->len = cpu_to_be16(4 + WWN_SIZE);
1986        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1987        size += 4 + WWN_SIZE;
1988
1989        ql_dbg(ql_dbg_disc, vha, 0x207d,
1990            "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name));
1991
1992        /* Manufacturer. */
1993        eiter = entries + size;
1994        eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1995        snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1996            "%s", "QLogic Corporation");
1997        eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0';
1998        alen = strlen(eiter->a.manufacturer);
1999        alen += 4 - (alen & 3);
2000        eiter->len = cpu_to_be16(4 + alen);
2001        size += 4 + alen;
2002
2003        ql_dbg(ql_dbg_disc, vha, 0x20a5,
2004            "Manufacturer = %s.\n", eiter->a.manufacturer);
2005
2006        /* Serial number. */
2007        eiter = entries + size;
2008        eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
2009        if (IS_FWI2_CAPABLE(ha))
2010                qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
2011                    sizeof(eiter->a.serial_num));
2012        else {
2013                sn = ((ha->serial0 & 0x1f) << 16) |
2014                        (ha->serial2 << 8) | ha->serial1;
2015                snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
2016                    "%c%05d", 'A' + sn / 100000, sn % 100000);
2017        }
2018        alen = strlen(eiter->a.serial_num);
2019        alen += 4 - (alen & 3);
2020        eiter->len = cpu_to_be16(4 + alen);
2021        size += 4 + alen;
2022
2023        ql_dbg(ql_dbg_disc, vha, 0x20a6,
2024            "Serial no. = %s.\n", eiter->a.serial_num);
2025
2026        /* Model name. */
2027        eiter = entries + size;
2028        eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
2029        snprintf(eiter->a.model, sizeof(eiter->a.model),
2030            "%s", ha->model_number);
2031        alen = strlen(eiter->a.model);
2032        alen += 4 - (alen & 3);
2033        eiter->len = cpu_to_be16(4 + alen);
2034        size += 4 + alen;
2035
2036        ql_dbg(ql_dbg_disc, vha, 0x20a7,
2037            "Model Name = %s.\n", eiter->a.model);
2038
2039        /* Model description. */
2040        eiter = entries + size;
2041        eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
2042        snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
2043            "%s", ha->model_desc);
2044        alen = strlen(eiter->a.model_desc);
2045        alen += 4 - (alen & 3);
2046        eiter->len = cpu_to_be16(4 + alen);
2047        size += 4 + alen;
2048
2049        ql_dbg(ql_dbg_disc, vha, 0x20a8,
2050            "Model Desc = %s.\n", eiter->a.model_desc);
2051
2052        /* Hardware version. */
2053        eiter = entries + size;
2054        eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
2055        if (!IS_FWI2_CAPABLE(ha)) {
2056                snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
2057                    "HW:%s", ha->adapter_id);
2058        } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
2059                    sizeof(eiter->a.hw_version))) {
2060                ;
2061        } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
2062                    sizeof(eiter->a.hw_version))) {
2063                ;
2064        } else {
2065                snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
2066                    "HW:%s", ha->adapter_id);
2067        }
2068        alen = strlen(eiter->a.hw_version);
2069        alen += 4 - (alen & 3);
2070        eiter->len = cpu_to_be16(4 + alen);
2071        size += 4 + alen;
2072
2073        ql_dbg(ql_dbg_disc, vha, 0x20a9,
2074            "Hardware ver = %s.\n", eiter->a.hw_version);
2075
2076        /* Driver version. */
2077        eiter = entries + size;
2078        eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
2079        snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
2080            "%s", qla2x00_version_str);
2081        alen = strlen(eiter->a.driver_version);
2082        alen += 4 - (alen & 3);
2083        eiter->len = cpu_to_be16(4 + alen);
2084        size += 4 + alen;
2085
2086        ql_dbg(ql_dbg_disc, vha, 0x20aa,
2087            "Driver ver = %s.\n", eiter->a.driver_version);
2088
2089        /* Option ROM version. */
2090        eiter = entries + size;
2091        eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
2092        snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
2093            "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
2094        alen = strlen(eiter->a.orom_version);
2095        alen += 4 - (alen & 3);
2096        eiter->len = cpu_to_be16(4 + alen);
2097        size += 4 + alen;
2098
2099        ql_dbg(ql_dbg_disc, vha , 0x20ab,
2100            "Optrom version = %d.%02d.\n", eiter->a.orom_version[1],
2101            eiter->a.orom_version[0]);
2102
2103        /* Firmware version */
2104        eiter = entries + size;
2105        eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
2106        ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
2107            sizeof(eiter->a.fw_version));
2108        alen = strlen(eiter->a.fw_version);
2109        alen += 4 - (alen & 3);
2110        eiter->len = cpu_to_be16(4 + alen);
2111        size += 4 + alen;
2112
2113        ql_dbg(ql_dbg_disc, vha, 0x20ac,
2114            "Firmware vers = %s.\n", eiter->a.fw_version);
2115
2116        /* OS Name and Version */
2117        eiter = entries + size;
2118        eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
2119        p_sysid = utsname();
2120        if (p_sysid) {
2121                snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
2122                    "%s %s %s",
2123                    p_sysid->sysname, p_sysid->release, p_sysid->version);
2124        } else {
2125                snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
2126                    "%s %s", "Linux", fc_host_system_hostname(vha->host));
2127        }
2128        alen = strlen(eiter->a.os_version);
2129        alen += 4 - (alen & 3);
2130        eiter->len = cpu_to_be16(4 + alen);
2131        size += 4 + alen;
2132
2133        ql_dbg(ql_dbg_disc, vha, 0x20ae,
2134            "OS Name and Version = %s.\n", eiter->a.os_version);
2135
2136        /* MAX CT Payload Length */
2137        eiter = entries + size;
2138        eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
2139        eiter->a.max_ct_len = IS_FWI2_CAPABLE(ha) ?
2140            le16_to_cpu(icb24->frame_payload_size) :
2141            le16_to_cpu(ha->init_cb->frame_payload_size);
2142        eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len);
2143        eiter->len = cpu_to_be16(4 + 4);
2144        size += 4 + 4;
2145
2146        ql_dbg(ql_dbg_disc, vha, 0x20af,
2147            "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len);
2148
2149        /* Node Sybolic Name */
2150        eiter = entries + size;
2151        eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
2152        qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
2153            sizeof(eiter->a.sym_name));
2154        alen = strlen(eiter->a.sym_name);
2155        alen += 4 - (alen & 3);
2156        eiter->len = cpu_to_be16(4 + alen);
2157        size += 4 + alen;
2158
2159        ql_dbg(ql_dbg_disc, vha, 0x20b0,
2160            "Symbolic Name = %s.\n", eiter->a.sym_name);
2161
2162        /* Vendor Id */
2163        eiter = entries + size;
2164        eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID);
2165        eiter->a.vendor_id = cpu_to_be32(0x1077);
2166        eiter->len = cpu_to_be16(4 + 4);
2167        size += 4 + 4;
2168
2169        ql_dbg(ql_dbg_disc, vha, 0x20b1,
2170            "Vendor Id = %x.\n", eiter->a.vendor_id);
2171
2172        /* Num Ports */
2173        eiter = entries + size;
2174        eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
2175        eiter->a.num_ports = cpu_to_be32(1);
2176        eiter->len = cpu_to_be16(4 + 4);
2177        size += 4 + 4;
2178
2179        ql_dbg(ql_dbg_disc, vha, 0x20b2,
2180            "Port Num = %x.\n", eiter->a.num_ports);
2181
2182        /* Fabric Name */
2183        eiter = entries + size;
2184        eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
2185        memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
2186        eiter->len = cpu_to_be16(4 + WWN_SIZE);
2187        size += 4 + WWN_SIZE;
2188
2189        ql_dbg(ql_dbg_disc, vha, 0x20b3,
2190            "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
2191
2192        /* BIOS Version */
2193        eiter = entries + size;
2194        eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
2195        snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name),
2196            "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
2197        alen = strlen(eiter->a.bios_name);
2198        alen += 4 - (alen & 3);
2199        eiter->len = cpu_to_be16(4 + alen);
2200        size += 4 + alen;
2201
2202        ql_dbg(ql_dbg_disc, vha, 0x20b4,
2203            "BIOS Name = %s\n", eiter->a.bios_name);
2204
2205        /* Vendor Identifier */
2206        eiter = entries + size;
2207        eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
2208        snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
2209            "%s", "QLGC");
2210        alen = strlen(eiter->a.vendor_identifier);
2211        alen += 4 - (alen & 3);
2212        eiter->len = cpu_to_be16(4 + alen);
2213        size += 4 + alen;
2214
2215        ql_dbg(ql_dbg_disc, vha, 0x201b,
2216            "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
2217
2218        /* Update MS request size. */
2219        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
2220
2221        ql_dbg(ql_dbg_disc, vha, 0x20b5,
2222            "RHBA identifier = %016llx.\n",
2223            wwn_to_u64(ct_req->req.rhba2.hba_identifier));
2224        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6,
2225            entries, size);
2226
2227        /* Execute MS IOCB */
2228        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2229            sizeof(ms_iocb_entry_t));
2230        if (rval != QLA_SUCCESS) {
2231                /*EMPTY*/
2232                ql_dbg(ql_dbg_disc, vha, 0x20b7,
2233                    "RHBA issue IOCB failed (%d).\n", rval);
2234        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
2235            QLA_SUCCESS) {
2236                rval = QLA_FUNCTION_FAILED;
2237
2238                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
2239                    ct_rsp->header.explanation_code ==
2240                    CT_EXPL_ALREADY_REGISTERED) {
2241                        ql_dbg(ql_dbg_disc, vha, 0x20b8,
2242                            "HBA already registered.\n");
2243                        rval = QLA_ALREADY_REGISTERED;
2244                } else {
2245                        ql_dbg(ql_dbg_disc, vha, 0x2016,
2246                            "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
2247                            ct_rsp->header.reason_code,
2248                            ct_rsp->header.explanation_code);
2249                }
2250        } else {
2251                ql_dbg(ql_dbg_disc, vha, 0x20b9,
2252                    "RHBA FDMI V2 exiting normally.\n");
2253        }
2254
2255        return rval;
2256}
2257
2258/**
2259 * qla2x00_fdmi_dhba() -
2260 * @ha: HA context
2261 *
2262 * Returns 0 on success.
2263 */
2264static int
2265qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
2266{
2267        int rval;
2268        struct qla_hw_data *ha = vha->hw;
2269        ms_iocb_entry_t *ms_pkt;
2270        struct ct_sns_req *ct_req;
2271        struct ct_sns_rsp *ct_rsp;
2272
2273        /* Issue RPA */
2274        /* Prepare common MS IOCB */
2275        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
2276            DHBA_RSP_SIZE);
2277
2278        /* Prepare CT request */
2279        ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
2280        ct_rsp = &ha->ct_sns->p.rsp;
2281
2282        /* Prepare FDMI command arguments -- portname. */
2283        memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
2284
2285        ql_dbg(ql_dbg_disc, vha, 0x2036,
2286            "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);
2287
2288        /* Execute MS IOCB */
2289        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2290            sizeof(ms_iocb_entry_t));
2291        if (rval != QLA_SUCCESS) {
2292                /*EMPTY*/
2293                ql_dbg(ql_dbg_disc, vha, 0x2037,
2294                    "DHBA issue IOCB failed (%d).\n", rval);
2295        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
2296            QLA_SUCCESS) {
2297                rval = QLA_FUNCTION_FAILED;
2298        } else {
2299                ql_dbg(ql_dbg_disc, vha, 0x2038,
2300                    "DHBA exiting normally.\n");
2301        }
2302
2303        return rval;
2304}
2305
2306/**
2307 * qla2x00_fdmiv2_rpa() -
2308 * @ha: HA context
2309 *
2310 * Returns 0 on success.
2311 */
2312static int
2313qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
2314{
2315        int rval, alen;
2316        uint32_t size;
2317        struct qla_hw_data *ha = vha->hw;
2318        ms_iocb_entry_t *ms_pkt;
2319        struct ct_sns_req *ct_req;
2320        struct ct_sns_rsp *ct_rsp;
2321        void *entries;
2322        struct ct_fdmiv2_port_attr *eiter;
2323        struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
2324        struct new_utsname *p_sysid = NULL;
2325
2326        /* Issue RPA */
2327        /* Prepare common MS IOCB */
2328        /*   Request size adjusted after CT preparation */
2329        ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
2330
2331        /* Prepare CT request */
2332        ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
2333        ct_rsp = &ha->ct_sns->p.rsp;
2334
2335        /* Prepare FDMI command arguments -- attribute block, attributes. */
2336        memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE);
2337        size = WWN_SIZE + 4;
2338
2339        /* Attributes */
2340        ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
2341        entries = ct_req->req.rpa2.port_name;
2342
2343        /* FC4 types. */
2344        eiter = entries + size;
2345        eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
2346        eiter->len = cpu_to_be16(4 + 32);
2347        eiter->a.fc4_types[2] = 0x01;
2348        size += 4 + 32;
2349
2350        ql_dbg(ql_dbg_disc, vha, 0x20ba,
2351            "FC4_TYPES=%02x %02x.\n",
2352            eiter->a.fc4_types[2],
2353            eiter->a.fc4_types[1]);
2354
2355        if (vha->flags.nvme_enabled) {
2356                eiter->a.fc4_types[6] = 1;      /* NVMe type 28h */
2357                ql_dbg(ql_dbg_disc, vha, 0x211f,
2358                    "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
2359                    eiter->a.fc4_types[6]);
2360        }
2361
2362        /* Supported speed. */
2363        eiter = entries + size;
2364        eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
2365        eiter->len = cpu_to_be16(4 + 4);
2366        if (IS_CNA_CAPABLE(ha))
2367                eiter->a.sup_speed = cpu_to_be32(
2368                    FDMI_PORT_SPEED_10GB);
2369        else if (IS_QLA27XX(ha))
2370                eiter->a.sup_speed = cpu_to_be32(
2371                    FDMI_PORT_SPEED_32GB|
2372                    FDMI_PORT_SPEED_16GB|
2373                    FDMI_PORT_SPEED_8GB);
2374        else if (IS_QLA2031(ha))
2375                eiter->a.sup_speed = cpu_to_be32(
2376                    FDMI_PORT_SPEED_16GB|
2377                    FDMI_PORT_SPEED_8GB|
2378                    FDMI_PORT_SPEED_4GB);
2379        else if (IS_QLA25XX(ha))
2380                eiter->a.sup_speed = cpu_to_be32(
2381                    FDMI_PORT_SPEED_8GB|
2382                    FDMI_PORT_SPEED_4GB|
2383                    FDMI_PORT_SPEED_2GB|
2384                    FDMI_PORT_SPEED_1GB);
2385        else if (IS_QLA24XX_TYPE(ha))
2386                eiter->a.sup_speed = cpu_to_be32(
2387                    FDMI_PORT_SPEED_4GB|
2388                    FDMI_PORT_SPEED_2GB|
2389                    FDMI_PORT_SPEED_1GB);
2390        else if (IS_QLA23XX(ha))
2391                eiter->a.sup_speed = cpu_to_be32(
2392                    FDMI_PORT_SPEED_2GB|
2393                    FDMI_PORT_SPEED_1GB);
2394        else
2395                eiter->a.sup_speed = cpu_to_be32(
2396                    FDMI_PORT_SPEED_1GB);
2397        size += 4 + 4;
2398
2399        ql_dbg(ql_dbg_disc, vha, 0x20bb,
2400            "Supported Port Speed = %x.\n", eiter->a.sup_speed);
2401
2402        /* Current speed. */
2403        eiter = entries + size;
2404        eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
2405        eiter->len = cpu_to_be16(4 + 4);
2406        switch (ha->link_data_rate) {
2407        case PORT_SPEED_1GB:
2408                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB);
2409                break;
2410        case PORT_SPEED_2GB:
2411                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB);
2412                break;
2413        case PORT_SPEED_4GB:
2414                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB);
2415                break;
2416        case PORT_SPEED_8GB:
2417                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB);
2418                break;
2419        case PORT_SPEED_10GB:
2420                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB);
2421                break;
2422        case PORT_SPEED_16GB:
2423                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB);
2424                break;
2425        case PORT_SPEED_32GB:
2426                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB);
2427                break;
2428        default:
2429                eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
2430                break;
2431        }
2432        size += 4 + 4;
2433
2434        ql_dbg(ql_dbg_disc, vha, 0x2017,
2435            "Current_Speed = %x.\n", eiter->a.cur_speed);
2436
2437        /* Max frame size. */
2438        eiter = entries + size;
2439        eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
2440        eiter->len = cpu_to_be16(4 + 4);
2441        eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
2442            le16_to_cpu(icb24->frame_payload_size):
2443            le16_to_cpu(ha->init_cb->frame_payload_size);
2444        eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
2445        size += 4 + 4;
2446
2447        ql_dbg(ql_dbg_disc, vha, 0x20bc,
2448            "Max_Frame_Size = %x.\n", eiter->a.max_frame_size);
2449
2450        /* OS device name. */
2451        eiter = entries + size;
2452        eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
2453        alen = strlen(QLA2XXX_DRIVER_NAME);
2454        snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
2455            "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
2456        alen += 4 - (alen & 3);
2457        eiter->len = cpu_to_be16(4 + alen);
2458        size += 4 + alen;
2459
2460        ql_dbg(ql_dbg_disc, vha, 0x20be,
2461            "OS_Device_Name = %s.\n", eiter->a.os_dev_name);
2462
2463        /* Hostname. */
2464        eiter = entries + size;
2465        eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
2466        p_sysid = utsname();
2467        if (p_sysid) {
2468                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2469                    "%s", p_sysid->nodename);
2470        } else {
2471                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2472                    "%s", fc_host_system_hostname(vha->host));
2473        }
2474        alen = strlen(eiter->a.host_name);
2475        alen += 4 - (alen & 3);
2476        eiter->len = cpu_to_be16(4 + alen);
2477        size += 4 + alen;
2478
2479        ql_dbg(ql_dbg_disc, vha, 0x201a,
2480            "HostName=%s.\n", eiter->a.host_name);
2481
2482        /* Node Name */
2483        eiter = entries + size;
2484        eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
2485        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
2486        eiter->len = cpu_to_be16(4 + WWN_SIZE);
2487        size += 4 + WWN_SIZE;
2488
2489        ql_dbg(ql_dbg_disc, vha, 0x20c0,
2490            "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name));
2491
2492        /* Port Name */
2493        eiter = entries + size;
2494        eiter->type = cpu_to_be16(FDMI_PORT_NAME);
2495        memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE);
2496        eiter->len = cpu_to_be16(4 + WWN_SIZE);
2497        size += 4 + WWN_SIZE;
2498
2499        ql_dbg(ql_dbg_disc, vha, 0x20c1,
2500            "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name));
2501
2502        /* Port Symbolic Name */
2503        eiter = entries + size;
2504        eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
2505        qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
2506            sizeof(eiter->a.port_sym_name));
2507        alen = strlen(eiter->a.port_sym_name);
2508        alen += 4 - (alen & 3);
2509        eiter->len = cpu_to_be16(4 + alen);
2510        size += 4 + alen;
2511
2512        ql_dbg(ql_dbg_disc, vha, 0x20c2,
2513            "port symbolic name = %s\n", eiter->a.port_sym_name);
2514
2515        /* Port Type */
2516        eiter = entries + size;
2517        eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
2518        eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
2519        eiter->len = cpu_to_be16(4 + 4);
2520        size += 4 + 4;
2521
2522        ql_dbg(ql_dbg_disc, vha, 0x20c3,
2523            "Port Type = %x.\n", eiter->a.port_type);
2524
2525        /* Class of Service  */
2526        eiter = entries + size;
2527        eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
2528        eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
2529        eiter->len = cpu_to_be16(4 + 4);
2530        size += 4 + 4;
2531
2532        ql_dbg(ql_dbg_disc, vha, 0x20c4,
2533            "Supported COS = %08x\n", eiter->a.port_supported_cos);
2534
2535        /* Port Fabric Name */
2536        eiter = entries + size;
2537        eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
2538        memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
2539        eiter->len = cpu_to_be16(4 + WWN_SIZE);
2540        size += 4 + WWN_SIZE;
2541
2542        ql_dbg(ql_dbg_disc, vha, 0x20c5,
2543            "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
2544
2545        /* FC4_type */
2546        eiter = entries + size;
2547        eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
2548        eiter->a.port_fc4_type[0] = 0;
2549        eiter->a.port_fc4_type[1] = 0;
2550        eiter->a.port_fc4_type[2] = 1;
2551        eiter->a.port_fc4_type[3] = 0;
2552        eiter->len = cpu_to_be16(4 + 32);
2553        size += 4 + 32;
2554
2555        ql_dbg(ql_dbg_disc, vha, 0x20c6,
2556            "Port Active FC4 Type = %02x %02x.\n",
2557            eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
2558
2559        if (vha->flags.nvme_enabled) {
2560                eiter->a.port_fc4_type[4] = 0;
2561                eiter->a.port_fc4_type[5] = 0;
2562                eiter->a.port_fc4_type[6] = 1;  /* NVMe type 28h */
2563                ql_dbg(ql_dbg_disc, vha, 0x2120,
2564                    "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
2565                    eiter->a.port_fc4_type[6]);
2566        }
2567
2568        /* Port State */
2569        eiter = entries + size;
2570        eiter->type = cpu_to_be16(FDMI_PORT_STATE);
2571        eiter->a.port_state = cpu_to_be32(1);
2572        eiter->len = cpu_to_be16(4 + 4);
2573        size += 4 + 4;
2574
2575        ql_dbg(ql_dbg_disc, vha, 0x20c7,
2576            "Port State = %x.\n", eiter->a.port_state);
2577
2578        /* Number of Ports */
2579        eiter = entries + size;
2580        eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
2581        eiter->a.num_ports = cpu_to_be32(1);
2582        eiter->len = cpu_to_be16(4 + 4);
2583        size += 4 + 4;
2584
2585        ql_dbg(ql_dbg_disc, vha, 0x20c8,
2586            "Number of ports = %x.\n", eiter->a.num_ports);
2587
2588        /* Port Id */
2589        eiter = entries + size;
2590        eiter->type = cpu_to_be16(FDMI_PORT_ID);
2591        eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
2592        eiter->len = cpu_to_be16(4 + 4);
2593        size += 4 + 4;
2594
2595        ql_dbg(ql_dbg_disc, vha, 0x201c,
2596            "Port Id = %x.\n", eiter->a.port_id);
2597
2598        /* Update MS request size. */
2599        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
2600
2601        ql_dbg(ql_dbg_disc, vha, 0x2018,
2602            "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
2603        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
2604            entries, size);
2605
2606        /* Execute MS IOCB */
2607        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2608            sizeof(ms_iocb_entry_t));
2609        if (rval != QLA_SUCCESS) {
2610                /*EMPTY*/
2611                ql_dbg(ql_dbg_disc, vha, 0x20cb,
2612                    "RPA FDMI v2 issue IOCB failed (%d).\n", rval);
2613        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
2614            QLA_SUCCESS) {
2615                rval = QLA_FUNCTION_FAILED;
2616                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
2617                    ct_rsp->header.explanation_code ==
2618                    CT_EXPL_ALREADY_REGISTERED) {
2619                        ql_dbg(ql_dbg_disc, vha, 0x20ce,
2620                            "RPA FDMI v2 already registered\n");
2621                        rval = QLA_ALREADY_REGISTERED;
2622                } else {
2623                        ql_dbg(ql_dbg_disc, vha, 0x2020,
2624                            "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
2625                            ct_rsp->header.reason_code,
2626                            ct_rsp->header.explanation_code);
2627                }
2628        } else {
2629                ql_dbg(ql_dbg_disc, vha, 0x20cc,
2630                    "RPA FDMI V2 exiting normally.\n");
2631        }
2632
2633        return rval;
2634}
2635
2636/**
2637 * qla2x00_fdmi_register() -
2638 * @ha: HA context
2639 *
2640 * Returns 0 on success.
2641 */
2642int
2643qla2x00_fdmi_register(scsi_qla_host_t *vha)
2644{
2645        int rval = QLA_FUNCTION_FAILED;
2646        struct qla_hw_data *ha = vha->hw;
2647
2648        if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
2649            IS_QLAFX00(ha))
2650                return QLA_FUNCTION_FAILED;
2651
2652        rval = qla2x00_mgmt_svr_login(vha);
2653        if (rval)
2654                return rval;
2655
2656        rval = qla2x00_fdmiv2_rhba(vha);
2657        if (rval) {
2658                if (rval != QLA_ALREADY_REGISTERED)
2659                        goto try_fdmi;
2660
2661                rval = qla2x00_fdmi_dhba(vha);
2662                if (rval)
2663                        goto try_fdmi;
2664
2665                rval = qla2x00_fdmiv2_rhba(vha);
2666                if (rval)
2667                        goto try_fdmi;
2668        }
2669        rval = qla2x00_fdmiv2_rpa(vha);
2670        if (rval)
2671                goto try_fdmi;
2672
2673        goto out;
2674
2675try_fdmi:
2676        rval = qla2x00_fdmi_rhba(vha);
2677        if (rval) {
2678                if (rval != QLA_ALREADY_REGISTERED)
2679                        return rval;
2680
2681                rval = qla2x00_fdmi_dhba(vha);
2682                if (rval)
2683                        return rval;
2684
2685                rval = qla2x00_fdmi_rhba(vha);
2686                if (rval)
2687                        return rval;
2688        }
2689        rval = qla2x00_fdmi_rpa(vha);
2690out:
2691        return rval;
2692}
2693
2694/**
2695 * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
2696 * @ha: HA context
2697 * @list: switch info entries to populate
2698 *
2699 * Returns 0 on success.
2700 */
2701int
2702qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
2703{
2704        int             rval = QLA_SUCCESS;
2705        uint16_t        i;
2706        struct qla_hw_data *ha = vha->hw;
2707        ms_iocb_entry_t *ms_pkt;
2708        struct ct_sns_req       *ct_req;
2709        struct ct_sns_rsp       *ct_rsp;
2710        struct ct_arg arg;
2711
2712        if (!IS_IIDMA_CAPABLE(ha))
2713                return QLA_FUNCTION_FAILED;
2714
2715        arg.iocb = ha->ms_iocb;
2716        arg.req_dma = ha->ct_sns_dma;
2717        arg.rsp_dma = ha->ct_sns_dma;
2718        arg.req_size = GFPN_ID_REQ_SIZE;
2719        arg.rsp_size = GFPN_ID_RSP_SIZE;
2720        arg.nport_handle = NPH_SNS;
2721
2722        for (i = 0; i < ha->max_fibre_devices; i++) {
2723                /* Issue GFPN_ID */
2724                /* Prepare common MS IOCB */
2725                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
2726
2727                /* Prepare CT request */
2728                ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
2729                    GFPN_ID_RSP_SIZE);
2730                ct_rsp = &ha->ct_sns->p.rsp;
2731
2732                /* Prepare CT arguments -- port_id */
2733                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2734                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2735                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2736
2737                /* Execute MS IOCB */
2738                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2739                    sizeof(ms_iocb_entry_t));
2740                if (rval != QLA_SUCCESS) {
2741                        /*EMPTY*/
2742                        ql_dbg(ql_dbg_disc, vha, 0x2023,
2743                            "GFPN_ID issue IOCB failed (%d).\n", rval);
2744                        break;
2745                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2746                    "GFPN_ID") != QLA_SUCCESS) {
2747                        rval = QLA_FUNCTION_FAILED;
2748                        break;
2749                } else {
2750                        /* Save fabric portname */
2751                        memcpy(list[i].fabric_port_name,
2752                            ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
2753                }
2754
2755                /* Last device exit. */
2756                if (list[i].d_id.b.rsvd_1 != 0)
2757                        break;
2758        }
2759
2760        return (rval);
2761}
2762
2763
2764static inline struct ct_sns_req *
2765qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
2766    uint16_t rsp_size)
2767{
2768        memset(p, 0, sizeof(struct ct_sns_pkt));
2769
2770        p->p.req.header.revision = 0x01;
2771        p->p.req.header.gs_type = 0xFA;
2772        p->p.req.header.gs_subtype = 0x01;
2773        p->p.req.command = cpu_to_be16(cmd);
2774        p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
2775
2776        return &p->p.req;
2777}
2778
2779/**
2780 * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
2781 * @ha: HA context
2782 * @list: switch info entries to populate
2783 *
2784 * Returns 0 on success.
2785 */
2786int
2787qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
2788{
2789        int             rval;
2790        uint16_t        i;
2791        struct qla_hw_data *ha = vha->hw;
2792        ms_iocb_entry_t *ms_pkt;
2793        struct ct_sns_req       *ct_req;
2794        struct ct_sns_rsp       *ct_rsp;
2795        struct ct_arg arg;
2796
2797        if (!IS_IIDMA_CAPABLE(ha))
2798                return QLA_FUNCTION_FAILED;
2799        if (!ha->flags.gpsc_supported)
2800                return QLA_FUNCTION_FAILED;
2801
2802        rval = qla2x00_mgmt_svr_login(vha);
2803        if (rval)
2804                return rval;
2805
2806        arg.iocb = ha->ms_iocb;
2807        arg.req_dma = ha->ct_sns_dma;
2808        arg.rsp_dma = ha->ct_sns_dma;
2809        arg.req_size = GPSC_REQ_SIZE;
2810        arg.rsp_size = GPSC_RSP_SIZE;
2811        arg.nport_handle = vha->mgmt_svr_loop_id;
2812
2813        for (i = 0; i < ha->max_fibre_devices; i++) {
2814                /* Issue GFPN_ID */
2815                /* Prepare common MS IOCB */
2816                ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
2817
2818                /* Prepare CT request */
2819                ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
2820                    GPSC_RSP_SIZE);
2821                ct_rsp = &ha->ct_sns->p.rsp;
2822
2823                /* Prepare CT arguments -- port_name */
2824                memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
2825                    WWN_SIZE);
2826
2827                /* Execute MS IOCB */
2828                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2829                    sizeof(ms_iocb_entry_t));
2830                if (rval != QLA_SUCCESS) {
2831                        /*EMPTY*/
2832                        ql_dbg(ql_dbg_disc, vha, 0x2059,
2833                            "GPSC issue IOCB failed (%d).\n", rval);
2834                } else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2835                    "GPSC")) != QLA_SUCCESS) {
2836                        /* FM command unsupported? */
2837                        if (rval == QLA_INVALID_COMMAND &&
2838                            (ct_rsp->header.reason_code ==
2839                                CT_REASON_INVALID_COMMAND_CODE ||
2840                             ct_rsp->header.reason_code ==
2841                                CT_REASON_COMMAND_UNSUPPORTED)) {
2842                                ql_dbg(ql_dbg_disc, vha, 0x205a,
2843                                    "GPSC command unsupported, disabling "
2844                                    "query.\n");
2845                                ha->flags.gpsc_supported = 0;
2846                                rval = QLA_FUNCTION_FAILED;
2847                                break;
2848                        }
2849                        rval = QLA_FUNCTION_FAILED;
2850                } else {
2851                        /* Save port-speed */
2852                        switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
2853                        case BIT_15:
2854                                list[i].fp_speed = PORT_SPEED_1GB;
2855                                break;
2856                        case BIT_14:
2857                                list[i].fp_speed = PORT_SPEED_2GB;
2858                                break;
2859                        case BIT_13:
2860                                list[i].fp_speed = PORT_SPEED_4GB;
2861                                break;
2862                        case BIT_12:
2863                                list[i].fp_speed = PORT_SPEED_10GB;
2864                                break;
2865                        case BIT_11:
2866                                list[i].fp_speed = PORT_SPEED_8GB;
2867                                break;
2868                        case BIT_10:
2869                                list[i].fp_speed = PORT_SPEED_16GB;
2870                                break;
2871                        case BIT_8:
2872                                list[i].fp_speed = PORT_SPEED_32GB;
2873                                break;
2874                        }
2875
2876                        ql_dbg(ql_dbg_disc, vha, 0x205b,
2877                            "GPSC ext entry - fpn "
2878                            "%8phN speeds=%04x speed=%04x.\n",
2879                            list[i].fabric_port_name,
2880                            be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
2881                            be16_to_cpu(ct_rsp->rsp.gpsc.speed));
2882                }
2883
2884                /* Last device exit. */
2885                if (list[i].d_id.b.rsvd_1 != 0)
2886                        break;
2887        }
2888
2889        return (rval);
2890}
2891
2892/**
2893 * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
2894 *
2895 * @ha: HA context
2896 * @list: switch info entries to populate
2897 *
2898 */
2899void
2900qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
2901{
2902        int             rval;
2903        uint16_t        i;
2904
2905        ms_iocb_entry_t *ms_pkt;
2906        struct ct_sns_req       *ct_req;
2907        struct ct_sns_rsp       *ct_rsp;
2908        struct qla_hw_data *ha = vha->hw;
2909        uint8_t fcp_scsi_features = 0;
2910        struct ct_arg arg;
2911
2912        for (i = 0; i < ha->max_fibre_devices; i++) {
2913                /* Set default FC4 Type as UNKNOWN so the default is to
2914                 * Process this port */
2915                list[i].fc4_type = FC4_TYPE_UNKNOWN;
2916
2917                /* Do not attempt GFF_ID if we are not FWI_2 capable */
2918                if (!IS_FWI2_CAPABLE(ha))
2919                        continue;
2920
2921                arg.iocb = ha->ms_iocb;
2922                arg.req_dma = ha->ct_sns_dma;
2923                arg.rsp_dma = ha->ct_sns_dma;
2924                arg.req_size = GFF_ID_REQ_SIZE;
2925                arg.rsp_size = GFF_ID_RSP_SIZE;
2926                arg.nport_handle = NPH_SNS;
2927
2928                /* Prepare common MS IOCB */
2929                ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
2930
2931                /* Prepare CT request */
2932                ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
2933                    GFF_ID_RSP_SIZE);
2934                ct_rsp = &ha->ct_sns->p.rsp;
2935
2936                /* Prepare CT arguments -- port_id */
2937                ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2938                ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2939                ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2940
2941                /* Execute MS IOCB */
2942                rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2943                   sizeof(ms_iocb_entry_t));
2944
2945                if (rval != QLA_SUCCESS) {
2946                        ql_dbg(ql_dbg_disc, vha, 0x205c,
2947                            "GFF_ID issue IOCB failed (%d).\n", rval);
2948                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2949                               "GFF_ID") != QLA_SUCCESS) {
2950                        ql_dbg(ql_dbg_disc, vha, 0x205d,
2951                            "GFF_ID IOCB status had a failure status code.\n");
2952                } else {
2953                        fcp_scsi_features =
2954                           ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2955                        fcp_scsi_features &= 0x0f;
2956
2957                        if (fcp_scsi_features)
2958                                list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2959                        else
2960                                list[i].fc4_type = FC4_TYPE_OTHER;
2961
2962                        list[i].fc4f_nvme =
2963                            ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
2964                        list[i].fc4f_nvme &= 0xf;
2965                }
2966
2967                /* Last device exit. */
2968                if (list[i].d_id.b.rsvd_1 != 0)
2969                        break;
2970        }
2971}
2972
2973/* GID_PN completion processing. */
2974void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
2975{
2976        fc_port_t *fcport = ea->fcport;
2977
2978        ql_dbg(ql_dbg_disc, vha, 0x201d,
2979            "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
2980            __func__, fcport->port_name, fcport->disc_state,
2981            fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
2982            fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
2983
2984        if (fcport->disc_state == DSC_DELETE_PEND)
2985                return;
2986
2987        if (ea->sp->gen2 != fcport->login_gen) {
2988                /* PLOGI/PRLI/LOGO came in while cmd was out.*/
2989                ql_dbg(ql_dbg_disc, vha, 0x201e,
2990                    "%s %8phC generation changed rscn %d|%d n",
2991                    __func__, fcport->port_name, fcport->last_rscn_gen,
2992                    fcport->rscn_gen);
2993                return;
2994        }
2995
2996        if (!ea->rc) {
2997                if (ea->sp->gen1 == fcport->rscn_gen) {
2998                        fcport->scan_state = QLA_FCPORT_FOUND;
2999                        fcport->flags |= FCF_FABRIC_DEVICE;
3000
3001                        if (fcport->d_id.b24 == ea->id.b24) {
3002                                /* cable plugged into the same place */
3003                                switch (vha->host->active_mode) {
3004                                case MODE_TARGET:
3005                                        if (fcport->fw_login_state ==
3006                                            DSC_LS_PRLI_COMP) {
3007                                                u16 data[2];
3008                                                /*
3009                                                 * Late RSCN was delivered.
3010                                                 * Remote port already login'ed.
3011                                                 */
3012                                                ql_dbg(ql_dbg_disc, vha, 0x201f,
3013                                                    "%s %d %8phC post adisc\n",
3014                                                    __func__, __LINE__,
3015                                                    fcport->port_name);
3016                                                data[0] = data[1] = 0;
3017                                                qla2x00_post_async_adisc_work(
3018                                                    vha, fcport, data);
3019                                        }
3020                                        break;
3021                                case MODE_INITIATOR:
3022                                case MODE_DUAL:
3023                                default:
3024                                        ql_dbg(ql_dbg_disc, vha, 0x201f,
3025                                            "%s %d %8phC post %s\n", __func__,
3026                                            __LINE__, fcport->port_name,
3027                                            (atomic_read(&fcport->state) ==
3028                                            FCS_ONLINE) ? "adisc" : "gnl");
3029
3030                                        if (atomic_read(&fcport->state) ==
3031                                            FCS_ONLINE) {
3032                                                u16 data[2];
3033
3034                                                data[0] = data[1] = 0;
3035                                                qla2x00_post_async_adisc_work(
3036                                                    vha, fcport, data);
3037                                        } else {
3038                                                qla24xx_post_gnl_work(vha,
3039                                                    fcport);
3040                                        }
3041                                        break;
3042                                }
3043                        } else { /* fcport->d_id.b24 != ea->id.b24 */
3044                                fcport->d_id.b24 = ea->id.b24;
3045                                fcport->id_changed = 1;
3046                                if (fcport->deleted != QLA_SESS_DELETED) {
3047                                        ql_dbg(ql_dbg_disc, vha, 0x2021,
3048                                            "%s %d %8phC post del sess\n",
3049                                            __func__, __LINE__, fcport->port_name);
3050                                        qlt_schedule_sess_for_deletion(fcport);
3051                                }
3052                        }
3053                } else { /* ea->sp->gen1 != fcport->rscn_gen */
3054                        ql_dbg(ql_dbg_disc, vha, 0x2022,
3055                            "%s %d %8phC post gidpn\n",
3056                            __func__, __LINE__, fcport->port_name);
3057                        /* rscn came in while cmd was out */
3058                        qla24xx_post_gidpn_work(vha, fcport);
3059                }
3060        } else { /* ea->rc */
3061                /* cable pulled */
3062                if (ea->sp->gen1 == fcport->rscn_gen) {
3063                        if (ea->sp->gen2 == fcport->login_gen) {
3064                                ql_dbg(ql_dbg_disc, vha, 0x2042,
3065                                    "%s %d %8phC post del sess\n", __func__,
3066                                    __LINE__, fcport->port_name);
3067                                qlt_schedule_sess_for_deletion(fcport);
3068                        } else {
3069                                ql_dbg(ql_dbg_disc, vha, 0x2045,
3070                                    "%s %d %8phC login\n", __func__, __LINE__,
3071                                    fcport->port_name);
3072                                qla24xx_fcport_handle_login(vha, fcport);
3073                        }
3074                } else {
3075                        ql_dbg(ql_dbg_disc, vha, 0x2049,
3076                            "%s %d %8phC post gidpn\n", __func__, __LINE__,
3077                            fcport->port_name);
3078                        qla24xx_post_gidpn_work(vha, fcport);
3079                }
3080        }
3081} /* gidpn_event */
3082
3083static void qla2x00_async_gidpn_sp_done(void *s, int res)
3084{
3085        struct srb *sp = s;
3086        struct scsi_qla_host *vha = sp->vha;
3087        fc_port_t *fcport = sp->fcport;
3088        u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
3089        struct event_arg ea;
3090
3091        fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
3092
3093        memset(&ea, 0, sizeof(ea));
3094        ea.fcport = fcport;
3095        ea.id.b.domain = id[0];
3096        ea.id.b.area = id[1];
3097        ea.id.b.al_pa = id[2];
3098        ea.sp = sp;
3099        ea.rc = res;
3100        ea.event = FCME_GIDPN_DONE;
3101
3102        if (res == QLA_FUNCTION_TIMEOUT) {
3103                ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
3104                    "Async done-%s WWPN %8phC timed out.\n",
3105                    sp->name, fcport->port_name);
3106                qla24xx_post_gidpn_work(sp->vha, fcport);
3107                sp->free(sp);
3108                return;
3109        } else if (res) {
3110                ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
3111                    "Async done-%s fail res %x, WWPN %8phC\n",
3112                    sp->name, res, fcport->port_name);
3113        } else {
3114                ql_dbg(ql_dbg_disc, vha, 0x204f,
3115                    "Async done-%s good WWPN %8phC ID %3phC\n",
3116                    sp->name, fcport->port_name, id);
3117        }
3118
3119        qla2x00_fcport_event_handler(vha, &ea);
3120
3121        sp->free(sp);
3122}
3123
3124int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
3125{
3126        int rval = QLA_FUNCTION_FAILED;
3127        struct ct_sns_req       *ct_req;
3128        srb_t *sp;
3129
3130        if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
3131                return rval;
3132
3133        fcport->disc_state = DSC_GID_PN;
3134        fcport->scan_state = QLA_FCPORT_SCAN;
3135        sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
3136        if (!sp)
3137                goto done;
3138
3139        fcport->flags |= FCF_ASYNC_SENT;
3140        sp->type = SRB_CT_PTHRU_CMD;
3141        sp->name = "gidpn";
3142        sp->gen1 = fcport->rscn_gen;
3143        sp->gen2 = fcport->login_gen;
3144
3145        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3146
3147        /* CT_IU preamble  */
3148        ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GID_PN_CMD,
3149                GID_PN_RSP_SIZE);
3150
3151        /* GIDPN req */
3152        memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
3153                WWN_SIZE);
3154
3155        /* req & rsp use the same buffer */
3156        sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
3157        sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
3158        sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
3159        sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
3160        sp->u.iocb_cmd.u.ctarg.req_size = GID_PN_REQ_SIZE;
3161        sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_RSP_SIZE;
3162        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
3163
3164        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3165        sp->done = qla2x00_async_gidpn_sp_done;
3166
3167        rval = qla2x00_start_sp(sp);
3168        if (rval != QLA_SUCCESS)
3169                goto done_free_sp;
3170
3171        ql_dbg(ql_dbg_disc, vha, 0x20a4,
3172            "Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
3173            sp->name, fcport->port_name,
3174            sp->handle, fcport->loop_id, fcport->d_id.b.domain,
3175            fcport->d_id.b.area, fcport->d_id.b.al_pa);
3176        return rval;
3177
3178done_free_sp:
3179        sp->free(sp);
3180        fcport->flags &= ~FCF_ASYNC_SENT;
3181done:
3182        fcport->flags &= ~FCF_ASYNC_ACTIVE;
3183        return rval;
3184}
3185
3186int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
3187{
3188        struct qla_work_evt *e;
3189        int ls;
3190
3191        ls = atomic_read(&vha->loop_state);
3192        if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
3193                test_bit(UNLOADING, &vha->dpc_flags))
3194                return 0;
3195
3196        e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
3197        if (!e)
3198                return QLA_FUNCTION_FAILED;
3199
3200        e->u.fcport.fcport = fcport;
3201        fcport->flags |= FCF_ASYNC_ACTIVE;
3202        return qla2x00_post_work(vha, e);
3203}
3204
3205int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
3206{
3207        struct qla_work_evt *e;
3208
3209        e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
3210        if (!e)
3211                return QLA_FUNCTION_FAILED;
3212
3213        e->u.fcport.fcport = fcport;
3214        fcport->flags |= FCF_ASYNC_ACTIVE;
3215        return qla2x00_post_work(vha, e);
3216}
3217
3218void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
3219{
3220        struct fc_port *fcport = ea->fcport;
3221
3222        ql_dbg(ql_dbg_disc, vha, 0x20d8,
3223            "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
3224            __func__, fcport->port_name, fcport->disc_state,
3225            fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
3226            ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);
3227
3228        if (fcport->disc_state == DSC_DELETE_PEND)
3229                return;
3230
3231        if (ea->sp->gen2 != fcport->login_gen) {
3232                /* target side must have changed it. */
3233                ql_dbg(ql_dbg_disc, vha, 0x20d3,
3234                    "%s %8phC generation changed\n",
3235                    __func__, fcport->port_name);
3236                return;
3237        } else if (ea->sp->gen1 != fcport->rscn_gen) {
3238                ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
3239                    __func__, __LINE__, fcport->port_name);
3240                qla24xx_post_gidpn_work(vha, fcport);
3241                return;
3242        }
3243
3244        qla24xx_post_upd_fcport_work(vha, ea->fcport);
3245}
3246
3247static void qla24xx_async_gpsc_sp_done(void *s, int res)
3248{
3249        struct srb *sp = s;
3250        struct scsi_qla_host *vha = sp->vha;
3251        struct qla_hw_data *ha = vha->hw;
3252        fc_port_t *fcport = sp->fcport;
3253        struct ct_sns_rsp       *ct_rsp;
3254        struct event_arg ea;
3255
3256        ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
3257
3258        ql_dbg(ql_dbg_disc, vha, 0x2053,
3259            "Async done-%s res %x, WWPN %8phC \n",
3260            sp->name, res, fcport->port_name);
3261
3262        fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
3263
3264        if (res == (DID_ERROR << 16)) {
3265                /* entry status error */
3266                goto done;
3267        } else if (res) {
3268                if ((ct_rsp->header.reason_code ==
3269                         CT_REASON_INVALID_COMMAND_CODE) ||
3270                        (ct_rsp->header.reason_code ==
3271                        CT_REASON_COMMAND_UNSUPPORTED)) {
3272                        ql_dbg(ql_dbg_disc, vha, 0x2019,
3273                            "GPSC command unsupported, disabling query.\n");
3274                        ha->flags.gpsc_supported = 0;
3275                        res = QLA_SUCCESS;
3276                }
3277        } else {
3278                switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
3279                case BIT_15:
3280                        fcport->fp_speed = PORT_SPEED_1GB;
3281                        break;
3282                case BIT_14:
3283                        fcport->fp_speed = PORT_SPEED_2GB;
3284                        break;
3285                case BIT_13:
3286                        fcport->fp_speed = PORT_SPEED_4GB;
3287                        break;
3288                case BIT_12:
3289                        fcport->fp_speed = PORT_SPEED_10GB;
3290                        break;
3291                case BIT_11:
3292                        fcport->fp_speed = PORT_SPEED_8GB;
3293                        break;
3294                case BIT_10:
3295                        fcport->fp_speed = PORT_SPEED_16GB;
3296                        break;
3297                case BIT_8:
3298                        fcport->fp_speed = PORT_SPEED_32GB;
3299                        break;
3300                }
3301
3302                ql_dbg(ql_dbg_disc, vha, 0x2054,
3303                    "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
3304                    sp->name, fcport->fabric_port_name,
3305                    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
3306                    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
3307        }
3308done:
3309        memset(&ea, 0, sizeof(ea));
3310        ea.event = FCME_GPSC_DONE;
3311        ea.rc = res;
3312        ea.fcport = fcport;
3313        ea.sp = sp;
3314        qla2x00_fcport_event_handler(vha, &ea);
3315
3316        sp->free(sp);
3317}
3318
3319int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
3320{
3321        int rval = QLA_FUNCTION_FAILED;
3322        struct ct_sns_req       *ct_req;
3323        srb_t *sp;
3324
3325        if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
3326                return rval;
3327
3328        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
3329        if (!sp)
3330                goto done;
3331
3332        fcport->flags |= FCF_ASYNC_SENT;
3333        sp->type = SRB_CT_PTHRU_CMD;
3334        sp->name = "gpsc";
3335        sp->gen1 = fcport->rscn_gen;
3336        sp->gen2 = fcport->login_gen;
3337
3338        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3339
3340        /* CT_IU preamble  */
3341        ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
3342                GPSC_RSP_SIZE);
3343
3344        /* GPSC req */
3345        memcpy(ct_req->req.gpsc.port_name, fcport->fabric_port_name,
3346                WWN_SIZE);
3347
3348        sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
3349        sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
3350        sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
3351        sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
3352        sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;
3353        sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
3354        sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
3355
3356        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3357        sp->done = qla24xx_async_gpsc_sp_done;
3358
3359        rval = qla2x00_start_sp(sp);
3360        if (rval != QLA_SUCCESS)
3361                goto done_free_sp;
3362
3363        ql_dbg(ql_dbg_disc, vha, 0x205e,
3364            "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
3365            sp->name, fcport->port_name, sp->handle,
3366            fcport->loop_id, fcport->d_id.b.domain,
3367            fcport->d_id.b.area, fcport->d_id.b.al_pa);
3368        return rval;
3369
3370done_free_sp:
3371        sp->free(sp);
3372        fcport->flags &= ~FCF_ASYNC_SENT;
3373done:
3374        fcport->flags &= ~FCF_ASYNC_ACTIVE;
3375        return rval;
3376}
3377
3378int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
3379{
3380        struct qla_work_evt *e;
3381
3382        if (test_bit(UNLOADING, &vha->dpc_flags))
3383                return 0;
3384
3385        e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
3386        if (!e)
3387                return QLA_FUNCTION_FAILED;
3388
3389        e->u.gpnid.id = *id;
3390        return qla2x00_post_work(vha, e);
3391}
3392
3393void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
3394{
3395        if (sp->u.iocb_cmd.u.ctarg.req) {
3396                dma_free_coherent(&vha->hw->pdev->dev,
3397                        sizeof(struct ct_sns_pkt),
3398                        sp->u.iocb_cmd.u.ctarg.req,
3399                        sp->u.iocb_cmd.u.ctarg.req_dma);
3400                sp->u.iocb_cmd.u.ctarg.req = NULL;
3401        }
3402        if (sp->u.iocb_cmd.u.ctarg.rsp) {
3403                dma_free_coherent(&vha->hw->pdev->dev,
3404                        sizeof(struct ct_sns_pkt),
3405                        sp->u.iocb_cmd.u.ctarg.rsp,
3406                        sp->u.iocb_cmd.u.ctarg.rsp_dma);
3407                sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3408        }
3409
3410        sp->free(sp);
3411}
3412
3413void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
3414{
3415        fc_port_t *fcport, *conflict, *t;
3416        u16 data[2];
3417
3418        ql_dbg(ql_dbg_disc, vha, 0xffff,
3419            "%s %d port_id: %06x\n",
3420            __func__, __LINE__, ea->id.b24);
3421
3422        if (ea->rc) {
3423                /* cable is disconnected */
3424                list_for_each_entry_safe(fcport, t, &vha->vp_fcports, list) {
3425                        if (fcport->d_id.b24 == ea->id.b24) {
3426                                ql_dbg(ql_dbg_disc, vha, 0xffff,
3427                                    "%s %d %8phC DS %d\n",
3428                                    __func__, __LINE__,
3429                                    fcport->port_name,
3430                                    fcport->disc_state);
3431                                fcport->scan_state = QLA_FCPORT_SCAN;
3432                                switch (fcport->disc_state) {
3433                                case DSC_DELETED:
3434                                case DSC_DELETE_PEND:
3435                                        break;
3436                                default:
3437                                        ql_dbg(ql_dbg_disc, vha, 0xffff,
3438                                            "%s %d %8phC post del sess\n",
3439                                            __func__, __LINE__,
3440                                            fcport->port_name);
3441                                        qlt_schedule_sess_for_deletion(fcport);
3442                                        break;
3443                                }
3444                        }
3445                }
3446        } else {
3447                /* cable is connected */
3448                fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
3449                if (fcport) {
3450                        list_for_each_entry_safe(conflict, t, &vha->vp_fcports,
3451                            list) {
3452                                if ((conflict->d_id.b24 == ea->id.b24) &&
3453                                    (fcport != conflict)) {
3454                                        /* 2 fcports with conflict Nport ID or
3455                                         * an existing fcport is having nport ID
3456                                         * conflict with new fcport.
3457                                         */
3458
3459                                        ql_dbg(ql_dbg_disc, vha, 0xffff,
3460                                            "%s %d %8phC DS %d\n",
3461                                            __func__, __LINE__,
3462                                            conflict->port_name,
3463                                            conflict->disc_state);
3464                                        conflict->scan_state = QLA_FCPORT_SCAN;
3465                                        switch (conflict->disc_state) {
3466                                        case DSC_DELETED:
3467                                        case DSC_DELETE_PEND:
3468                                                break;
3469                                        default:
3470                                                ql_dbg(ql_dbg_disc, vha, 0xffff,
3471                                                    "%s %d %8phC post del sess\n",
3472                                                    __func__, __LINE__,
3473                                                    conflict->port_name);
3474                                                qlt_schedule_sess_for_deletion
3475                                                        (conflict);
3476                                                break;
3477                                        }
3478                                }
3479                        }
3480
3481                        fcport->rscn_gen++;
3482                        fcport->scan_state = QLA_FCPORT_FOUND;
3483                        fcport->flags |= FCF_FABRIC_DEVICE;
3484                        switch (fcport->disc_state) {
3485                        case DSC_LOGIN_COMPLETE:
3486                                /* recheck session is still intact. */
3487                                ql_dbg(ql_dbg_disc, vha, 0x210d,
3488                                    "%s %d %8phC revalidate session with ADISC\n",
3489                                    __func__, __LINE__, fcport->port_name);
3490                                data[0] = data[1] = 0;
3491                                qla2x00_post_async_adisc_work(vha, fcport,
3492                                    data);
3493                                break;
3494                        case DSC_DELETED:
3495                                ql_dbg(ql_dbg_disc, vha, 0x210d,
3496                                    "%s %d %8phC login\n", __func__, __LINE__,
3497                                    fcport->port_name);
3498                                fcport->d_id = ea->id;
3499                                qla24xx_fcport_handle_login(vha, fcport);
3500                                break;
3501                        case DSC_DELETE_PEND:
3502                                fcport->d_id = ea->id;
3503                                break;
3504                        default:
3505                                fcport->d_id = ea->id;
3506                                break;
3507                        }
3508                } else {
3509                        list_for_each_entry_safe(conflict, t, &vha->vp_fcports,
3510                            list) {
3511                                if (conflict->d_id.b24 == ea->id.b24) {
3512                                        /* 2 fcports with conflict Nport ID or
3513                                         * an existing fcport is having nport ID
3514                                         * conflict with new fcport.
3515                                         */
3516                                        ql_dbg(ql_dbg_disc, vha, 0xffff,
3517                                            "%s %d %8phC DS %d\n",
3518                                            __func__, __LINE__,
3519                                            conflict->port_name,
3520                                            conflict->disc_state);
3521
3522                                        conflict->scan_state = QLA_FCPORT_SCAN;
3523                                        switch (conflict->disc_state) {
3524                                        case DSC_DELETED:
3525                                        case DSC_DELETE_PEND:
3526                                                break;
3527                                        default:
3528                                                ql_dbg(ql_dbg_disc, vha, 0xffff,
3529                                                    "%s %d %8phC post del sess\n",
3530                                                    __func__, __LINE__,
3531                                                    conflict->port_name);
3532                                                qlt_schedule_sess_for_deletion
3533                                                        (conflict);
3534                                                break;
3535                                        }
3536                                }
3537                        }
3538
3539                        /* create new fcport */
3540                        ql_dbg(ql_dbg_disc, vha, 0x2065,
3541                            "%s %d %8phC post new sess\n",
3542                            __func__, __LINE__, ea->port_name);
3543                        qla24xx_post_newsess_work(vha, &ea->id,
3544                            ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN);
3545                }
3546        }
3547}
3548
3549static void qla2x00_async_gpnid_sp_done(void *s, int res)
3550{
3551        struct srb *sp = s;
3552        struct scsi_qla_host *vha = sp->vha;
3553        struct ct_sns_req *ct_req =
3554            (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
3555        struct ct_sns_rsp *ct_rsp =
3556            (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
3557        struct event_arg ea;
3558        struct qla_work_evt *e;
3559        unsigned long flags;
3560
3561        if (res)
3562                ql_dbg(ql_dbg_disc, vha, 0x2066,
3563                    "Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n",
3564                    sp->name, res, sp->gen1, ct_req->req.port_id.port_id,
3565                    ct_rsp->rsp.gpn_id.port_name);
3566        else
3567                ql_dbg(ql_dbg_disc, vha, 0x2066,
3568                    "Async done-%s good rscn gen %d ID %3phC. %8phC\n",
3569                    sp->name, sp->gen1, ct_req->req.port_id.port_id,
3570                    ct_rsp->rsp.gpn_id.port_name);
3571
3572        memset(&ea, 0, sizeof(ea));
3573        memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
3574        ea.sp = sp;
3575        ea.id.b.domain = ct_req->req.port_id.port_id[0];
3576        ea.id.b.area = ct_req->req.port_id.port_id[1];
3577        ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
3578        ea.rc = res;
3579        ea.event = FCME_GPNID_DONE;
3580
3581        spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
3582        list_del(&sp->elem);
3583        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
3584
3585        if (res) {
3586                if (res == QLA_FUNCTION_TIMEOUT) {
3587                        qla24xx_post_gpnid_work(sp->vha, &ea.id);
3588                        sp->free(sp);
3589                        return;
3590                }
3591        } else if (sp->gen1) {
3592                /* There was another RSCN for this Nport ID */
3593                qla24xx_post_gpnid_work(sp->vha, &ea.id);
3594                sp->free(sp);
3595                return;
3596        }
3597
3598        qla2x00_fcport_event_handler(vha, &ea);
3599
3600        e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
3601        if (!e) {
3602                /* please ignore kernel warning. otherwise, we have mem leak. */
3603                if (sp->u.iocb_cmd.u.ctarg.req) {
3604                        dma_free_coherent(&vha->hw->pdev->dev,
3605                                sizeof(struct ct_sns_pkt),
3606                                sp->u.iocb_cmd.u.ctarg.req,
3607                                sp->u.iocb_cmd.u.ctarg.req_dma);
3608                        sp->u.iocb_cmd.u.ctarg.req = NULL;
3609                }
3610                if (sp->u.iocb_cmd.u.ctarg.rsp) {
3611                        dma_free_coherent(&vha->hw->pdev->dev,
3612                                sizeof(struct ct_sns_pkt),
3613                                sp->u.iocb_cmd.u.ctarg.rsp,
3614                                sp->u.iocb_cmd.u.ctarg.rsp_dma);
3615                        sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3616                }
3617
3618                sp->free(sp);
3619                return;
3620        }
3621
3622        e->u.iosb.sp = sp;
3623        qla2x00_post_work(vha, e);
3624}
3625
3626/* Get WWPN with Nport ID. */
3627int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
3628{
3629        int rval = QLA_FUNCTION_FAILED;
3630        struct ct_sns_req       *ct_req;
3631        srb_t *sp, *tsp;
3632        struct ct_sns_pkt *ct_sns;
3633        unsigned long flags;
3634
3635        if (!vha->flags.online)
3636                goto done;
3637
3638        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
3639        if (!sp)
3640                goto done;
3641
3642        sp->type = SRB_CT_PTHRU_CMD;
3643        sp->name = "gpnid";
3644        sp->u.iocb_cmd.u.ctarg.id = *id;
3645        sp->gen1 = 0;
3646        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3647
3648        spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
3649        list_for_each_entry(tsp, &vha->gpnid_list, elem) {
3650                if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
3651                        tsp->gen1++;
3652                        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
3653                        sp->free(sp);
3654                        goto done;
3655                }
3656        }
3657        list_add_tail(&sp->elem, &vha->gpnid_list);
3658        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
3659
3660        sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
3661                sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
3662                GFP_KERNEL);
3663        if (!sp->u.iocb_cmd.u.ctarg.req) {
3664                ql_log(ql_log_warn, vha, 0xd041,
3665                    "Failed to allocate ct_sns request.\n");
3666                goto done_free_sp;
3667        }
3668
3669        sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
3670                sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
3671                GFP_KERNEL);
3672        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
3673                ql_log(ql_log_warn, vha, 0xd042,
3674                    "Failed to allocate ct_sns request.\n");
3675                goto done_free_sp;
3676        }
3677
3678        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
3679        memset(ct_sns, 0, sizeof(*ct_sns));
3680
3681        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
3682        /* CT_IU preamble  */
3683        ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
3684
3685        /* GPN_ID req */
3686        ct_req->req.port_id.port_id[0] = id->b.domain;
3687        ct_req->req.port_id.port_id[1] = id->b.area;
3688        ct_req->req.port_id.port_id[2] = id->b.al_pa;
3689
3690        sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
3691        sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
3692        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
3693
3694        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3695        sp->done = qla2x00_async_gpnid_sp_done;
3696
3697        rval = qla2x00_start_sp(sp);
3698        if (rval != QLA_SUCCESS)
3699                goto done_free_sp;
3700
3701        ql_dbg(ql_dbg_disc, vha, 0x2067,
3702            "Async-%s hdl=%x ID %3phC.\n", sp->name,
3703            sp->handle, ct_req->req.port_id.port_id);
3704        return rval;
3705
3706done_free_sp:
3707        if (sp->u.iocb_cmd.u.ctarg.req) {
3708                dma_free_coherent(&vha->hw->pdev->dev,
3709                        sizeof(struct ct_sns_pkt),
3710                        sp->u.iocb_cmd.u.ctarg.req,
3711                        sp->u.iocb_cmd.u.ctarg.req_dma);
3712                sp->u.iocb_cmd.u.ctarg.req = NULL;
3713        }
3714        if (sp->u.iocb_cmd.u.ctarg.rsp) {
3715                dma_free_coherent(&vha->hw->pdev->dev,
3716                        sizeof(struct ct_sns_pkt),
3717                        sp->u.iocb_cmd.u.ctarg.rsp,
3718                        sp->u.iocb_cmd.u.ctarg.rsp_dma);
3719                sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3720        }
3721
3722        sp->free(sp);
3723done:
3724        return rval;
3725}
3726
3727void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
3728{
3729       fc_port_t *fcport = ea->fcport;
3730
3731       qla24xx_post_gnl_work(vha, fcport);
3732}
3733
3734void qla24xx_async_gffid_sp_done(void *s, int res)
3735{
3736       struct srb *sp = s;
3737       struct scsi_qla_host *vha = sp->vha;
3738       fc_port_t *fcport = sp->fcport;
3739       struct ct_sns_rsp *ct_rsp;
3740       struct event_arg ea;
3741
3742       ql_dbg(ql_dbg_disc, vha, 0x2133,
3743           "Async done-%s res %x ID %x. %8phC\n",
3744           sp->name, res, fcport->d_id.b24, fcport->port_name);
3745
3746       fcport->flags &= ~FCF_ASYNC_SENT;
3747       ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
3748       /*
3749        * FC-GS-7, 5.2.3.12 FC-4 Features - format
3750        * The format of the FC-4 Features object, as defined by the FC-4,
3751        * Shall be an array of 4-bit values, one for each type code value
3752        */
3753       if (!res) {
3754               if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
3755                       /* w1 b00:03 */
3756                       fcport->fc4_type =
3757                           ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
3758                       fcport->fc4_type &= 0xf;
3759               }
3760
3761               if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
3762                       /* w5 [00:03]/28h */
3763                       fcport->fc4f_nvme =
3764                           ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
3765                       fcport->fc4f_nvme &= 0xf;
3766               }
3767       }
3768
3769       memset(&ea, 0, sizeof(ea));
3770       ea.sp = sp;
3771       ea.fcport = sp->fcport;
3772       ea.rc = res;
3773       ea.event = FCME_GFFID_DONE;
3774
3775       qla2x00_fcport_event_handler(vha, &ea);
3776       sp->free(sp);
3777}
3778
3779/* Get FC4 Feature with Nport ID. */
3780int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
3781{
3782        int rval = QLA_FUNCTION_FAILED;
3783        struct ct_sns_req       *ct_req;
3784        srb_t *sp;
3785
3786        if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
3787                return rval;
3788
3789        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
3790        if (!sp)
3791                return rval;
3792
3793        fcport->flags |= FCF_ASYNC_SENT;
3794        sp->type = SRB_CT_PTHRU_CMD;
3795        sp->name = "gffid";
3796        sp->gen1 = fcport->rscn_gen;
3797        sp->gen2 = fcport->login_gen;
3798
3799        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3800
3801        /* CT_IU preamble  */
3802        ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
3803            GFF_ID_RSP_SIZE);
3804
3805        ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;
3806        ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;
3807        ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;
3808
3809        sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
3810        sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
3811        sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
3812        sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
3813        sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;
3814        sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
3815        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
3816
3817        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3818        sp->done = qla24xx_async_gffid_sp_done;
3819
3820        rval = qla2x00_start_sp(sp);
3821        if (rval != QLA_SUCCESS)
3822                goto done_free_sp;
3823
3824        ql_dbg(ql_dbg_disc, vha, 0x2132,
3825            "Async-%s hdl=%x  %8phC.\n", sp->name,
3826            sp->handle, fcport->port_name);
3827
3828        return rval;
3829done_free_sp:
3830        sp->free(sp);
3831        fcport->flags &= ~FCF_ASYNC_SENT;
3832        return rval;
3833}
3834
3835/* GPN_FT + GNN_FT*/
3836static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
3837{
3838        struct qla_hw_data *ha = vha->hw;
3839        scsi_qla_host_t *vp;
3840        unsigned long flags;
3841        u64 twwn;
3842        int rc = 0;
3843
3844        if (!ha->num_vhosts)
3845                return 0;
3846
3847        spin_lock_irqsave(&ha->vport_slock, flags);
3848        list_for_each_entry(vp, &ha->vp_list, list) {
3849                twwn = wwn_to_u64(vp->port_name);
3850                if (wwn == twwn) {
3851                        rc = 1;
3852                        break;
3853                }
3854        }
3855        spin_unlock_irqrestore(&ha->vport_slock, flags);
3856
3857        return rc;
3858}
3859
3860void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
3861{
3862        fc_port_t *fcport;
3863        u32 i, rc;
3864        bool found;
3865        u8 fc4type = sp->gen2;
3866        struct fab_scan_rp *rp;
3867        unsigned long flags;
3868
3869        ql_dbg(ql_dbg_disc, vha, 0xffff,
3870            "%s enter\n", __func__);
3871
3872        if (sp->gen1 != vha->hw->base_qpair->chip_reset) {
3873                ql_dbg(ql_dbg_disc, vha, 0xffff,
3874                    "%s scan stop due to chip reset %x/%x\n",
3875                    sp->name, sp->gen1, vha->hw->base_qpair->chip_reset);
3876                goto out;
3877        }
3878
3879        rc = sp->rc;
3880        if (rc) {
3881                vha->scan.scan_retry++;
3882                if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
3883                        set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
3884                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
3885                } else {
3886                        ql_dbg(ql_dbg_disc, vha, 0xffff,
3887                            "Fabric scan failed on all retries.\n");
3888                }
3889                goto out;
3890        }
3891        vha->scan.scan_retry = 0;
3892
3893        list_for_each_entry(fcport, &vha->vp_fcports, list)
3894                fcport->scan_state = QLA_FCPORT_SCAN;
3895
3896        for (i = 0; i < vha->hw->max_fibre_devices; i++) {
3897                u64 wwn;
3898
3899                rp = &vha->scan.l[i];
3900                found = false;
3901
3902                wwn = wwn_to_u64(rp->port_name);
3903                if (wwn == 0)
3904                        continue;
3905
3906                if (!memcmp(rp->port_name, vha->port_name, WWN_SIZE))
3907                        continue;
3908
3909                /* Bypass reserved domain fields. */
3910                if ((rp->id.b.domain & 0xf0) == 0xf0)
3911                        continue;
3912
3913                /* Bypass virtual ports of the same host. */
3914                if (qla2x00_is_a_vp(vha, wwn))
3915                        continue;
3916
3917                list_for_each_entry(fcport, &vha->vp_fcports, list) {
3918                        if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
3919                                continue;
3920                        fcport->scan_state = QLA_FCPORT_FOUND;
3921                        fcport->d_id.b24 = rp->id.b24;
3922                        found = true;
3923                        /*
3924                         * If device was not a fabric device before.
3925                         */
3926                        if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
3927                                qla2x00_clear_loop_id(fcport);
3928                                fcport->flags |= FCF_FABRIC_DEVICE;
3929                        }
3930                        break;
3931                }
3932
3933                if (!found) {
3934                        ql_dbg(ql_dbg_disc, vha, 0xffff,
3935                            "%s %d %8phC post new sess\n",
3936                            __func__, __LINE__, rp->port_name);
3937                        qla24xx_post_newsess_work(vha, &rp->id, rp->port_name,
3938                            rp->node_name, NULL, fc4type);
3939                }
3940        }
3941
3942        /*
3943         * Logout all previous fabric dev marked lost, except FCP2 devices.
3944         */
3945        list_for_each_entry(fcport, &vha->vp_fcports, list) {
3946                if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
3947                        continue;
3948
3949                if (fcport->scan_state != QLA_FCPORT_FOUND) {
3950                        if ((qla_dual_mode_enabled(vha) ||
3951                                qla_ini_mode_enabled(vha)) &&
3952                            atomic_read(&fcport->state) == FCS_ONLINE) {
3953                                qla2x00_mark_device_lost(vha, fcport,
3954                                    ql2xplogiabsentdevice, 0);
3955
3956                                if (fcport->loop_id != FC_NO_LOOP_ID &&
3957                                    (fcport->flags & FCF_FCP2_DEVICE) == 0) {
3958                                        ql_dbg(ql_dbg_disc, vha, 0x20f0,
3959                                            "%s %d %8phC post del sess\n",
3960                                            __func__, __LINE__,
3961                                            fcport->port_name);
3962
3963                                        qlt_schedule_sess_for_deletion(fcport);
3964                                        continue;
3965                                }
3966                        }
3967                } else
3968                        qla24xx_fcport_handle_login(vha, fcport);
3969        }
3970
3971out:
3972        qla24xx_sp_unmap(vha, sp);
3973        spin_lock_irqsave(&vha->work_lock, flags);
3974        vha->scan.scan_flags &= ~SF_SCANNING;
3975        spin_unlock_irqrestore(&vha->work_lock, flags);
3976
3977        if ((fc4type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled)
3978                qla24xx_async_gpnft(vha, FC4_TYPE_NVME);
3979}
3980
3981static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
3982{
3983        struct srb *sp = s;
3984        struct scsi_qla_host *vha = sp->vha;
3985        struct qla_work_evt *e;
3986        struct ct_sns_req *ct_req =
3987                (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
3988        struct ct_sns_gpnft_rsp *ct_rsp =
3989                (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
3990        struct ct_sns_gpn_ft_data *d;
3991        struct fab_scan_rp *rp;
3992        int i, j, k;
3993        u16 cmd = be16_to_cpu(ct_req->command);
3994
3995        /* gen2 field is holding the fc4type */
3996        ql_dbg(ql_dbg_disc, vha, 0xffff,
3997            "Async done-%s res %x FC4Type %x\n",
3998            sp->name, res, sp->gen2);
3999
4000        if (res) {
4001                unsigned long flags;
4002
4003                sp->free(sp);
4004                spin_lock_irqsave(&vha->work_lock, flags);
4005                vha->scan.scan_flags &= ~SF_SCANNING;
4006                vha->scan.scan_retry++;
4007                spin_unlock_irqrestore(&vha->work_lock, flags);
4008
4009                if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
4010                        set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4011                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4012                        qla2xxx_wake_dpc(vha);
4013                } else {
4014                        ql_dbg(ql_dbg_disc, sp->vha, 0xffff,
4015                            "Async done-%s rescan failed on all retries\n",
4016                            sp->name);
4017                }
4018                return;
4019        }
4020
4021        if (!res) {
4022                port_id_t id;
4023                u64 wwn;
4024
4025                j = 0;
4026                for (i = 0; i < vha->hw->max_fibre_devices; i++) {
4027                        d  = &ct_rsp->entries[i];
4028
4029                        id.b.rsvd_1 = 0;
4030                        id.b.domain = d->port_id[0];
4031                        id.b.area   = d->port_id[1];
4032                        id.b.al_pa  = d->port_id[2];
4033                        wwn = wwn_to_u64(d->port_name);
4034
4035                        if (id.b24 == 0 || wwn == 0)
4036                                continue;
4037
4038                        if (cmd == GPN_FT_CMD) {
4039                                rp = &vha->scan.l[j];
4040                                rp->id = id;
4041                                memcpy(rp->port_name, d->port_name, 8);
4042                                j++;
4043                        } else {/* GNN_FT_CMD */
4044                                for (k = 0; k < vha->hw->max_fibre_devices;
4045                                    k++) {
4046                                        rp = &vha->scan.l[k];
4047                                        if (id.b24 == rp->id.b24) {
4048                                                memcpy(rp->node_name,
4049                                                    d->port_name, 8);
4050                                                break;
4051                                        }
4052                                }
4053                        }
4054                }
4055        }
4056
4057        if (cmd == GPN_FT_CMD)
4058                e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT_DONE);
4059        else
4060                e = qla2x00_alloc_work(vha, QLA_EVT_GNNFT_DONE);
4061        if (!e) {
4062                /* please ignore kernel warning. Otherwise, we have mem leak. */
4063                if (sp->u.iocb_cmd.u.ctarg.req) {
4064                        dma_free_coherent(&vha->hw->pdev->dev,
4065                            sizeof(struct ct_sns_pkt),
4066                            sp->u.iocb_cmd.u.ctarg.req,
4067                            sp->u.iocb_cmd.u.ctarg.req_dma);
4068                        sp->u.iocb_cmd.u.ctarg.req = NULL;
4069                }
4070                if (sp->u.iocb_cmd.u.ctarg.rsp) {
4071                        dma_free_coherent(&vha->hw->pdev->dev,
4072                            sizeof(struct ct_sns_pkt),
4073                            sp->u.iocb_cmd.u.ctarg.rsp,
4074                            sp->u.iocb_cmd.u.ctarg.rsp_dma);
4075                        sp->u.iocb_cmd.u.ctarg.rsp = NULL;
4076                }
4077
4078                ql_dbg(ql_dbg_disc, vha, 0xffff,
4079                    "Async done-%s unable to alloc work element\n",
4080                    sp->name);
4081                sp->free(sp);
4082                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4083                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4084                return;
4085        }
4086
4087        sp->rc = res;
4088        e->u.iosb.sp = sp;
4089
4090        qla2x00_post_work(vha, e);
4091}
4092
4093/*
4094 * Get WWNN list for fc4_type
4095 *
4096 * It is assumed the same SRB is re-used from GPNFT to avoid
4097 * mem free & re-alloc
4098 */
4099static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
4100    u8 fc4_type)
4101{
4102        int rval = QLA_FUNCTION_FAILED;
4103        struct ct_sns_req *ct_req;
4104        struct ct_sns_pkt *ct_sns;
4105
4106        if (!vha->flags.online) {
4107                vha->scan.scan_flags &= ~SF_SCANNING;
4108                goto done_free_sp;
4109        }
4110
4111        if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
4112                ql_log(ql_log_warn, vha, 0xffff,
4113                    "%s: req %p rsp %p are not setup\n",
4114                    __func__, sp->u.iocb_cmd.u.ctarg.req,
4115                    sp->u.iocb_cmd.u.ctarg.rsp);
4116                vha->scan.scan_flags &= ~SF_SCANNING;
4117                WARN_ON(1);
4118                goto done_free_sp;
4119        }
4120        sp->type = SRB_CT_PTHRU_CMD;
4121        sp->name = "gnnft";
4122        sp->gen1 = vha->hw->base_qpair->chip_reset;
4123        sp->gen2 = fc4_type;
4124        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
4125
4126        memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
4127        memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
4128
4129        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
4130        /* CT_IU preamble  */
4131        ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
4132            sp->u.iocb_cmd.u.ctarg.rsp_size);
4133
4134        /* GPN_FT req */
4135        ct_req->req.gpn_ft.port_type = fc4_type;
4136
4137        sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
4138        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
4139
4140        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
4141        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
4142
4143        rval = qla2x00_start_sp(sp);
4144        if (rval != QLA_SUCCESS)
4145                goto done_free_sp;
4146
4147        ql_dbg(ql_dbg_disc, vha, 0xffff,
4148            "Async-%s hdl=%x FC4Type %x.\n", sp->name,
4149            sp->handle, ct_req->req.gpn_ft.port_type);
4150        return rval;
4151
4152done_free_sp:
4153        if (sp->u.iocb_cmd.u.ctarg.req) {
4154                dma_free_coherent(&vha->hw->pdev->dev,
4155                    sizeof(struct ct_sns_pkt),
4156                    sp->u.iocb_cmd.u.ctarg.req,
4157                    sp->u.iocb_cmd.u.ctarg.req_dma);
4158                sp->u.iocb_cmd.u.ctarg.req = NULL;
4159        }
4160        if (sp->u.iocb_cmd.u.ctarg.rsp) {
4161                dma_free_coherent(&vha->hw->pdev->dev,
4162                    sizeof(struct ct_sns_pkt),
4163                    sp->u.iocb_cmd.u.ctarg.rsp,
4164                    sp->u.iocb_cmd.u.ctarg.rsp_dma);
4165                sp->u.iocb_cmd.u.ctarg.rsp = NULL;
4166        }
4167
4168        sp->free(sp);
4169
4170        return rval;
4171} /* GNNFT */
4172
4173void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
4174{
4175        ql_dbg(ql_dbg_disc, vha, 0xffff,
4176            "%s enter\n", __func__);
4177        del_timer(&sp->u.iocb_cmd.timer);
4178        qla24xx_async_gnnft(vha, sp, sp->gen2);
4179}
4180
4181/* Get WWPN list for certain fc4_type */
4182int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
4183{
4184        int rval = QLA_FUNCTION_FAILED;
4185        struct ct_sns_req       *ct_req;
4186        srb_t *sp;
4187        struct ct_sns_pkt *ct_sns;
4188        u32 rspsz;
4189        unsigned long flags;
4190
4191        if (!vha->flags.online)
4192                return rval;
4193
4194        spin_lock_irqsave(&vha->work_lock, flags);
4195        if (vha->scan.scan_flags & SF_SCANNING) {
4196                spin_unlock_irqrestore(&vha->work_lock, flags);
4197                ql_dbg(ql_dbg_disc, vha, 0xffff, "scan active\n");
4198                return rval;
4199        }
4200        vha->scan.scan_flags |= SF_SCANNING;
4201        spin_unlock_irqrestore(&vha->work_lock, flags);
4202
4203        sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
4204        if (!sp) {
4205                vha->scan.scan_flags &= ~SF_SCANNING;
4206                return rval;
4207        }
4208
4209        sp->type = SRB_CT_PTHRU_CMD;
4210        sp->name = "gpnft";
4211        sp->gen1 = vha->hw->base_qpair->chip_reset;
4212        sp->gen2 = fc4_type;
4213        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
4214
4215        sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(&vha->hw->pdev->dev,
4216            sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
4217            GFP_KERNEL);
4218        if (!sp->u.iocb_cmd.u.ctarg.req) {
4219                ql_log(ql_log_warn, vha, 0xffff,
4220                    "Failed to allocate ct_sns request.\n");
4221                vha->scan.scan_flags &= ~SF_SCANNING;
4222                goto done_free_sp;
4223        }
4224
4225        rspsz = sizeof(struct ct_sns_gpnft_rsp) +
4226                ((vha->hw->max_fibre_devices - 1) *
4227                    sizeof(struct ct_sns_gpn_ft_data));
4228
4229        sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(&vha->hw->pdev->dev,
4230            rspsz, &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
4231        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
4232                ql_log(ql_log_warn, vha, 0xffff,
4233                    "Failed to allocate ct_sns request.\n");
4234                vha->scan.scan_flags &= ~SF_SCANNING;
4235                goto done_free_sp;
4236        }
4237
4238        memset(vha->scan.l, 0, vha->scan.size);
4239
4240        ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
4241        /* CT_IU preamble  */
4242        ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
4243
4244        /* GPN_FT req */
4245        ct_req->req.gpn_ft.port_type = fc4_type;
4246
4247        sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
4248        sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
4249        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
4250
4251        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
4252        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
4253
4254        rval = qla2x00_start_sp(sp);
4255        if (rval != QLA_SUCCESS) {
4256                vha->scan.scan_flags &= ~SF_SCANNING;
4257                goto done_free_sp;
4258        }
4259
4260        ql_dbg(ql_dbg_disc, vha, 0xffff,
4261            "Async-%s hdl=%x FC4Type %x.\n", sp->name,
4262            sp->handle, ct_req->req.gpn_ft.port_type);
4263        return rval;
4264
4265done_free_sp:
4266        if (sp->u.iocb_cmd.u.ctarg.req) {
4267                dma_free_coherent(&vha->hw->pdev->dev,
4268                    sizeof(struct ct_sns_pkt),
4269                    sp->u.iocb_cmd.u.ctarg.req,
4270                    sp->u.iocb_cmd.u.ctarg.req_dma);
4271                sp->u.iocb_cmd.u.ctarg.req = NULL;
4272        }
4273        if (sp->u.iocb_cmd.u.ctarg.rsp) {
4274                dma_free_coherent(&vha->hw->pdev->dev,
4275                    sizeof(struct ct_sns_pkt),
4276                    sp->u.iocb_cmd.u.ctarg.rsp,
4277                    sp->u.iocb_cmd.u.ctarg.rsp_dma);
4278                sp->u.iocb_cmd.u.ctarg.rsp = NULL;
4279        }
4280
4281        sp->free(sp);
4282
4283        return rval;
4284}
4285
4286void qla_scan_work_fn(struct work_struct *work)
4287{
4288        struct fab_scan *s = container_of(to_delayed_work(work),
4289            struct fab_scan, scan_work);
4290        struct scsi_qla_host *vha = container_of(s, struct scsi_qla_host,
4291            scan);
4292        unsigned long flags;
4293
4294        ql_dbg(ql_dbg_disc, vha, 0xffff,
4295            "%s: schedule loop resync\n", __func__);
4296        set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4297        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4298        qla2xxx_wake_dpc(vha);
4299        spin_lock_irqsave(&vha->work_lock, flags);
4300        vha->scan.scan_flags &= ~SF_QUEUED;
4301        spin_unlock_irqrestore(&vha->work_lock, flags);
4302}
4303
4304/* GNN_ID */
4305void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
4306{
4307        qla24xx_post_gnl_work(vha, ea->fcport);
4308}
4309
4310static void qla2x00_async_gnnid_sp_done(void *s, int res)
4311{
4312        struct srb *sp = s;
4313        struct scsi_qla_host *vha = sp->vha;
4314        fc_port_t *fcport = sp->fcport;
4315        u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
4316        struct event_arg ea;
4317        u64 wwnn;
4318
4319        fcport->flags &= ~FCF_ASYNC_SENT;
4320        wwnn = wwn_to_u64(node_name);
4321        if (wwnn)
4322                memcpy(fcport->node_name, node_name, WWN_SIZE);
4323
4324        memset(&ea, 0, sizeof(ea));
4325        ea.fcport = fcport;
4326        ea.sp = sp;
4327        ea.rc = res;
4328        ea.event = FCME_GNNID_DONE;
4329
4330        ql_dbg(ql_dbg_disc, vha, 0x204f,
4331            "Async done-%s res %x, WWPN %8phC %8phC\n",
4332            sp->name, res, fcport->port_name, fcport->node_name);
4333
4334        qla2x00_fcport_event_handler(vha, &ea);
4335
4336        sp->free(sp);
4337}
4338
4339int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
4340{
4341        int rval = QLA_FUNCTION_FAILED;
4342        struct ct_sns_req       *ct_req;
4343        srb_t *sp;
4344
4345        if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
4346                return rval;
4347
4348        fcport->disc_state = DSC_GNN_ID;
4349        sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
4350        if (!sp)
4351                goto done;
4352
4353        fcport->flags |= FCF_ASYNC_SENT;
4354        sp->type = SRB_CT_PTHRU_CMD;
4355        sp->name = "gnnid";
4356        sp->gen1 = fcport->rscn_gen;
4357        sp->gen2 = fcport->login_gen;
4358
4359        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
4360
4361        /* CT_IU preamble  */
4362        ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
4363            GNN_ID_RSP_SIZE);
4364
4365        /* GNN_ID req */
4366        ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
4367        ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
4368        ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
4369
4370
4371        /* req & rsp use the same buffer */
4372        sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
4373        sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
4374        sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
4375        sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
4376        sp->u.iocb_cmd.u.ctarg.req_size = GNN_ID_REQ_SIZE;
4377        sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
4378        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
4379
4380        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
4381        sp->done = qla2x00_async_gnnid_sp_done;
4382
4383        rval = qla2x00_start_sp(sp);
4384        if (rval != QLA_SUCCESS)
4385                goto done_free_sp;
4386        ql_dbg(ql_dbg_disc, vha, 0xffff,
4387            "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
4388            sp->name, fcport->port_name,
4389            sp->handle, fcport->loop_id, fcport->d_id.b24);
4390        return rval;
4391
4392done_free_sp:
4393        sp->free(sp);
4394        fcport->flags &= ~FCF_ASYNC_SENT;
4395done:
4396        return rval;
4397}
4398
4399int qla24xx_post_gnnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
4400{
4401        struct qla_work_evt *e;
4402        int ls;
4403
4404        ls = atomic_read(&vha->loop_state);
4405        if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
4406                test_bit(UNLOADING, &vha->dpc_flags))
4407                return 0;
4408
4409        e = qla2x00_alloc_work(vha, QLA_EVT_GNNID);
4410        if (!e)
4411                return QLA_FUNCTION_FAILED;
4412
4413        e->u.fcport.fcport = fcport;
4414        return qla2x00_post_work(vha, e);
4415}
4416
4417/* GPFN_ID */
4418void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
4419{
4420        fc_port_t *fcport = ea->fcport;
4421
4422        ql_dbg(ql_dbg_disc, vha, 0xffff,
4423            "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d\n",
4424            __func__, fcport->port_name, fcport->disc_state,
4425            fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
4426            fcport->rscn_gen, ea->sp->gen1, vha->fcport_count);
4427
4428        if (fcport->disc_state == DSC_DELETE_PEND)
4429                return;
4430
4431        if (ea->sp->gen2 != fcport->login_gen) {
4432                /* target side must have changed it. */
4433                ql_dbg(ql_dbg_disc, vha, 0x20d3,
4434                    "%s %8phC generation changed\n",
4435                    __func__, fcport->port_name);
4436                return;
4437        } else if (ea->sp->gen1 != fcport->rscn_gen) {
4438                ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
4439                    __func__, __LINE__, fcport->port_name);
4440                qla24xx_post_gidpn_work(vha, fcport);
4441                return;
4442        }
4443
4444        qla24xx_post_gpsc_work(vha, fcport);
4445}
4446
4447static void qla2x00_async_gfpnid_sp_done(void *s, int res)
4448{
4449        struct srb *sp = s;
4450        struct scsi_qla_host *vha = sp->vha;
4451        fc_port_t *fcport = sp->fcport;
4452        u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;
4453        struct event_arg ea;
4454        u64 wwn;
4455
4456        fcport->flags &= ~FCF_ASYNC_SENT;
4457        wwn = wwn_to_u64(fpn);
4458        if (wwn)
4459                memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);
4460
4461        memset(&ea, 0, sizeof(ea));
4462        ea.fcport = fcport;
4463        ea.sp = sp;
4464        ea.rc = res;
4465        ea.event = FCME_GFPNID_DONE;
4466
4467        ql_dbg(ql_dbg_disc, vha, 0x204f,
4468            "Async done-%s res %x, WWPN %8phC %8phC\n",
4469            sp->name, res, fcport->port_name, fcport->fabric_port_name);
4470
4471        qla2x00_fcport_event_handler(vha, &ea);
4472
4473        sp->free(sp);
4474}
4475
4476int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
4477{
4478        int rval = QLA_FUNCTION_FAILED;
4479        struct ct_sns_req       *ct_req;
4480        srb_t *sp;
4481
4482        if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
4483                return rval;
4484
4485        fcport->disc_state = DSC_GFPN_ID;
4486        sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
4487        if (!sp)
4488                goto done;
4489
4490        fcport->flags |= FCF_ASYNC_SENT;
4491        sp->type = SRB_CT_PTHRU_CMD;
4492        sp->name = "gfpnid";
4493        sp->gen1 = fcport->rscn_gen;
4494        sp->gen2 = fcport->login_gen;
4495
4496        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
4497
4498        /* CT_IU preamble  */
4499        ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
4500            GFPN_ID_RSP_SIZE);
4501
4502        /* GFPN_ID req */
4503        ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
4504        ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
4505        ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
4506
4507
4508        /* req & rsp use the same buffer */
4509        sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
4510        sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
4511        sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
4512        sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
4513        sp->u.iocb_cmd.u.ctarg.req_size = GFPN_ID_REQ_SIZE;
4514        sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
4515        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
4516
4517        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
4518        sp->done = qla2x00_async_gfpnid_sp_done;
4519
4520        rval = qla2x00_start_sp(sp);
4521        if (rval != QLA_SUCCESS)
4522                goto done_free_sp;
4523
4524        ql_dbg(ql_dbg_disc, vha, 0xffff,
4525            "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
4526            sp->name, fcport->port_name,
4527            sp->handle, fcport->loop_id, fcport->d_id.b24);
4528        return rval;
4529
4530done_free_sp:
4531        sp->free(sp);
4532        fcport->flags &= ~FCF_ASYNC_SENT;
4533done:
4534        return rval;
4535}
4536
4537int qla24xx_post_gfpnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
4538{
4539        struct qla_work_evt *e;
4540        int ls;
4541
4542        ls = atomic_read(&vha->loop_state);
4543        if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
4544                test_bit(UNLOADING, &vha->dpc_flags))
4545                return 0;
4546
4547        e = qla2x00_alloc_work(vha, QLA_EVT_GFPNID);
4548        if (!e)
4549                return QLA_FUNCTION_FAILED;
4550
4551        e->u.fcport.fcport = fcport;
4552        return qla2x00_post_work(vha, e);
4553}
4554