3980 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic Fibre Channel HBA Driver4 * Copyright (c) 2003-2014 QLogic Corporation5 */6#include "qla_def.h"7#include "qla_target.h"8#include <linux/utsname.h>9 10static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);11static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);12static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);13static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);14static int qla2x00_sns_rft_id(scsi_qla_host_t *);15static int qla2x00_sns_rnn_id(scsi_qla_host_t *);16static int qla_async_rftid(scsi_qla_host_t *, port_id_t *);17static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8);18static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);19static int qla_async_rsnn_nn(scsi_qla_host_t *);20 21 22 23/**24 * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.25 * @vha: HA context26 * @arg: CT arguments27 *28 * Returns a pointer to the @vha'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 put_unaligned_le64(arg->req_dma, &ms_pkt->req_dsd.address);50 ms_pkt->req_dsd.length = ms_pkt->req_bytecount;51 52 put_unaligned_le64(arg->rsp_dma, &ms_pkt->rsp_dsd.address);53 ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;54 55 vha->qla_stats.control_requests++;56 57 return (ms_pkt);58}59 60/**61 * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.62 * @vha: HA context63 * @arg: CT arguments64 *65 * Returns a pointer to the @ha's ms_iocb.66 */67void *68qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)69{70 struct qla_hw_data *ha = vha->hw;71 struct ct_entry_24xx *ct_pkt;72 73 ct_pkt = (struct ct_entry_24xx *)arg->iocb;74 memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));75 76 ct_pkt->entry_type = CT_IOCB_TYPE;77 ct_pkt->entry_count = 1;78 ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);79 ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);80 ct_pkt->cmd_dsd_count = cpu_to_le16(1);81 ct_pkt->rsp_dsd_count = cpu_to_le16(1);82 ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);83 ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);84 85 put_unaligned_le64(arg->req_dma, &ct_pkt->dsd[0].address);86 ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;87 88 put_unaligned_le64(arg->rsp_dma, &ct_pkt->dsd[1].address);89 ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;90 ct_pkt->vp_index = vha->vp_idx;91 92 vha->qla_stats.control_requests++;93 94 return (ct_pkt);95}96 97/**98 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.99 * @p: CT request buffer100 * @cmd: GS command101 * @rsp_size: response size in bytes102 *103 * Returns a pointer to the intitialized @ct_req.104 */105static inline struct ct_sns_req *106qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)107{108 memset(p, 0, sizeof(struct ct_sns_pkt));109 110 p->p.req.header.revision = 0x01;111 p->p.req.header.gs_type = 0xFC;112 p->p.req.header.gs_subtype = 0x02;113 p->p.req.command = cpu_to_be16(cmd);114 p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);115 116 return &p->p.req;117}118 119int120qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,121 struct ct_sns_rsp *ct_rsp, const char *routine)122{123 int rval;124 uint16_t comp_status;125 struct qla_hw_data *ha = vha->hw;126 bool lid_is_sns = false;127 128 rval = QLA_FUNCTION_FAILED;129 if (ms_pkt->entry_status != 0) {130 ql_dbg(ql_dbg_disc, vha, 0x2031,131 "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",132 routine, ms_pkt->entry_status, vha->d_id.b.domain,133 vha->d_id.b.area, vha->d_id.b.al_pa);134 } else {135 if (IS_FWI2_CAPABLE(ha))136 comp_status = le16_to_cpu(137 ((struct ct_entry_24xx *)ms_pkt)->comp_status);138 else139 comp_status = le16_to_cpu(ms_pkt->status);140 switch (comp_status) {141 case CS_COMPLETE:142 case CS_DATA_UNDERRUN:143 case CS_DATA_OVERRUN: /* Overrun? */144 if (ct_rsp->header.response !=145 cpu_to_be16(CT_ACCEPT_RESPONSE)) {146 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,147 "%s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x\n",148 routine, vha->d_id.b.domain,149 vha->d_id.b.area, vha->d_id.b.al_pa,150 comp_status, ct_rsp->header.response);151 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,152 0x2078, ct_rsp,153 offsetof(typeof(*ct_rsp), rsp));154 rval = QLA_INVALID_COMMAND;155 } else156 rval = QLA_SUCCESS;157 break;158 case CS_PORT_LOGGED_OUT:159 if (IS_FWI2_CAPABLE(ha)) {160 if (le16_to_cpu(ms_pkt->loop_id.extended) ==161 NPH_SNS)162 lid_is_sns = true;163 } else {164 if (le16_to_cpu(ms_pkt->loop_id.extended) ==165 SIMPLE_NAME_SERVER)166 lid_is_sns = true;167 }168 if (lid_is_sns) {169 ql_dbg(ql_dbg_async, vha, 0x502b,170 "%s failed, Name server has logged out",171 routine);172 rval = QLA_NOT_LOGGED_IN;173 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);174 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);175 }176 break;177 case CS_TIMEOUT:178 rval = QLA_FUNCTION_TIMEOUT;179 fallthrough;180 default:181 ql_dbg(ql_dbg_disc, vha, 0x2033,182 "%s failed, completion status (%x) on port_id: "183 "%02x%02x%02x.\n", routine, comp_status,184 vha->d_id.b.domain, vha->d_id.b.area,185 vha->d_id.b.al_pa);186 break;187 }188 }189 return rval;190}191 192/**193 * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.194 * @vha: HA context195 * @fcport: fcport entry to updated196 *197 * Returns 0 on success.198 */199int200qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)201{202 int rval;203 204 ms_iocb_entry_t *ms_pkt;205 struct ct_sns_req *ct_req;206 struct ct_sns_rsp *ct_rsp;207 struct qla_hw_data *ha = vha->hw;208 struct ct_arg arg;209 210 if (IS_QLA2100(ha) || IS_QLA2200(ha))211 return qla2x00_sns_ga_nxt(vha, fcport);212 213 arg.iocb = ha->ms_iocb;214 arg.req_dma = ha->ct_sns_dma;215 arg.rsp_dma = ha->ct_sns_dma;216 arg.req_size = GA_NXT_REQ_SIZE;217 arg.rsp_size = GA_NXT_RSP_SIZE;218 arg.nport_handle = NPH_SNS;219 220 /* Issue GA_NXT */221 /* Prepare common MS IOCB */222 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);223 224 /* Prepare CT request */225 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,226 GA_NXT_RSP_SIZE);227 ct_rsp = &ha->ct_sns->p.rsp;228 229 /* Prepare CT arguments -- port_id */230 ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);231 232 /* Execute MS IOCB */233 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,234 sizeof(ms_iocb_entry_t));235 if (rval != QLA_SUCCESS) {236 /*EMPTY*/237 ql_dbg(ql_dbg_disc, vha, 0x2062,238 "GA_NXT issue IOCB failed (%d).\n", rval);239 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=240 QLA_SUCCESS) {241 rval = QLA_FUNCTION_FAILED;242 } else {243 /* Populate fc_port_t entry. */244 fcport->d_id = be_to_port_id(ct_rsp->rsp.ga_nxt.port_id);245 246 memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,247 WWN_SIZE);248 memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,249 WWN_SIZE);250 251 fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?252 FS_FC4TYPE_FCP : FC4_TYPE_OTHER;253 254 if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&255 ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)256 fcport->d_id.b.domain = 0xf0;257 258 ql_dbg(ql_dbg_disc, vha, 0x2063,259 "GA_NXT entry - nn %8phN pn %8phN "260 "port_id=%02x%02x%02x.\n",261 fcport->node_name, fcport->port_name,262 fcport->d_id.b.domain, fcport->d_id.b.area,263 fcport->d_id.b.al_pa);264 }265 266 return (rval);267}268 269static inline int270qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)271{272 return vha->hw->max_fibre_devices * 4 + 16;273}274 275/**276 * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.277 * @vha: HA context278 * @list: switch info entries to populate279 *280 * NOTE: Non-Nx_Ports are not requested.281 *282 * Returns 0 on success.283 */284int285qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)286{287 int rval;288 uint16_t i;289 290 ms_iocb_entry_t *ms_pkt;291 struct ct_sns_req *ct_req;292 struct ct_sns_rsp *ct_rsp;293 294 struct ct_sns_gid_pt_data *gid_data;295 struct qla_hw_data *ha = vha->hw;296 uint16_t gid_pt_rsp_size;297 struct ct_arg arg;298 299 if (IS_QLA2100(ha) || IS_QLA2200(ha))300 return qla2x00_sns_gid_pt(vha, list);301 302 gid_data = NULL;303 gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);304 305 arg.iocb = ha->ms_iocb;306 arg.req_dma = ha->ct_sns_dma;307 arg.rsp_dma = ha->ct_sns_dma;308 arg.req_size = GID_PT_REQ_SIZE;309 arg.rsp_size = gid_pt_rsp_size;310 arg.nport_handle = NPH_SNS;311 312 /* Issue GID_PT */313 /* Prepare common MS IOCB */314 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);315 316 /* Prepare CT request */317 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);318 ct_rsp = &ha->ct_sns->p.rsp;319 320 /* Prepare CT arguments -- port_type */321 ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;322 323 /* Execute MS IOCB */324 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,325 sizeof(ms_iocb_entry_t));326 if (rval != QLA_SUCCESS) {327 /*EMPTY*/328 ql_dbg(ql_dbg_disc, vha, 0x2055,329 "GID_PT issue IOCB failed (%d).\n", rval);330 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=331 QLA_SUCCESS) {332 rval = QLA_FUNCTION_FAILED;333 } else {334 /* Set port IDs in switch info list. */335 for (i = 0; i < ha->max_fibre_devices; i++) {336 gid_data = &ct_rsp->rsp.gid_pt.entries[i];337 list[i].d_id = be_to_port_id(gid_data->port_id);338 memset(list[i].fabric_port_name, 0, WWN_SIZE);339 list[i].fp_speed = PORT_SPEED_UNKNOWN;340 341 /* Last one exit. */342 if (gid_data->control_byte & BIT_7) {343 list[i].d_id.b.rsvd_1 = gid_data->control_byte;344 break;345 }346 }347 348 /*349 * If we've used all available slots, then the switch is350 * reporting back more devices than we can handle with this351 * single call. Return a failed status, and let GA_NXT handle352 * the overload.353 */354 if (i == ha->max_fibre_devices)355 rval = QLA_FUNCTION_FAILED;356 }357 358 return (rval);359}360 361/**362 * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.363 * @vha: HA context364 * @list: switch info entries to populate365 *366 * Returns 0 on success.367 */368int369qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)370{371 int rval = QLA_SUCCESS;372 uint16_t i;373 374 ms_iocb_entry_t *ms_pkt;375 struct ct_sns_req *ct_req;376 struct ct_sns_rsp *ct_rsp;377 struct qla_hw_data *ha = vha->hw;378 struct ct_arg arg;379 380 if (IS_QLA2100(ha) || IS_QLA2200(ha))381 return qla2x00_sns_gpn_id(vha, list);382 383 arg.iocb = ha->ms_iocb;384 arg.req_dma = ha->ct_sns_dma;385 arg.rsp_dma = ha->ct_sns_dma;386 arg.req_size = GPN_ID_REQ_SIZE;387 arg.rsp_size = GPN_ID_RSP_SIZE;388 arg.nport_handle = NPH_SNS;389 390 for (i = 0; i < ha->max_fibre_devices; i++) {391 /* Issue GPN_ID */392 /* Prepare common MS IOCB */393 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);394 395 /* Prepare CT request */396 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,397 GPN_ID_RSP_SIZE);398 ct_rsp = &ha->ct_sns->p.rsp;399 400 /* Prepare CT arguments -- port_id */401 ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);402 403 /* Execute MS IOCB */404 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,405 sizeof(ms_iocb_entry_t));406 if (rval != QLA_SUCCESS) {407 /*EMPTY*/408 ql_dbg(ql_dbg_disc, vha, 0x2056,409 "GPN_ID issue IOCB failed (%d).\n", rval);410 break;411 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,412 "GPN_ID") != QLA_SUCCESS) {413 rval = QLA_FUNCTION_FAILED;414 break;415 } else {416 /* Save portname */417 memcpy(list[i].port_name,418 ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);419 }420 421 /* Last device exit. */422 if (list[i].d_id.b.rsvd_1 != 0)423 break;424 }425 426 return (rval);427}428 429/**430 * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.431 * @vha: HA context432 * @list: switch info entries to populate433 *434 * Returns 0 on success.435 */436int437qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)438{439 int rval = QLA_SUCCESS;440 uint16_t i;441 struct qla_hw_data *ha = vha->hw;442 ms_iocb_entry_t *ms_pkt;443 struct ct_sns_req *ct_req;444 struct ct_sns_rsp *ct_rsp;445 struct ct_arg arg;446 447 if (IS_QLA2100(ha) || IS_QLA2200(ha))448 return qla2x00_sns_gnn_id(vha, list);449 450 arg.iocb = ha->ms_iocb;451 arg.req_dma = ha->ct_sns_dma;452 arg.rsp_dma = ha->ct_sns_dma;453 arg.req_size = GNN_ID_REQ_SIZE;454 arg.rsp_size = GNN_ID_RSP_SIZE;455 arg.nport_handle = NPH_SNS;456 457 for (i = 0; i < ha->max_fibre_devices; i++) {458 /* Issue GNN_ID */459 /* Prepare common MS IOCB */460 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);461 462 /* Prepare CT request */463 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,464 GNN_ID_RSP_SIZE);465 ct_rsp = &ha->ct_sns->p.rsp;466 467 /* Prepare CT arguments -- port_id */468 ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);469 470 /* Execute MS IOCB */471 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,472 sizeof(ms_iocb_entry_t));473 if (rval != QLA_SUCCESS) {474 /*EMPTY*/475 ql_dbg(ql_dbg_disc, vha, 0x2057,476 "GNN_ID issue IOCB failed (%d).\n", rval);477 break;478 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,479 "GNN_ID") != QLA_SUCCESS) {480 rval = QLA_FUNCTION_FAILED;481 break;482 } else {483 /* Save nodename */484 memcpy(list[i].node_name,485 ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);486 487 ql_dbg(ql_dbg_disc, vha, 0x2058,488 "GID_PT entry - nn %8phN pn %8phN "489 "portid=%02x%02x%02x.\n",490 list[i].node_name, list[i].port_name,491 list[i].d_id.b.domain, list[i].d_id.b.area,492 list[i].d_id.b.al_pa);493 }494 495 /* Last device exit. */496 if (list[i].d_id.b.rsvd_1 != 0)497 break;498 }499 500 return (rval);501}502 503static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)504{505 struct scsi_qla_host *vha = sp->vha;506 struct ct_sns_pkt *ct_sns;507 struct qla_work_evt *e;508 509 sp->rc = rc;510 if (rc == QLA_SUCCESS) {511 ql_dbg(ql_dbg_disc, vha, 0x204f,512 "Async done-%s exiting normally.\n",513 sp->name);514 } else if (rc == QLA_FUNCTION_TIMEOUT) {515 ql_dbg(ql_dbg_disc, vha, 0x204f,516 "Async done-%s timeout\n", sp->name);517 } else {518 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;519 memset(ct_sns, 0, sizeof(*ct_sns));520 sp->retry_count++;521 if (sp->retry_count > 3)522 goto err;523 524 ql_dbg(ql_dbg_disc, vha, 0x204f,525 "Async done-%s fail rc %x. Retry count %d\n",526 sp->name, rc, sp->retry_count);527 528 e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);529 if (!e)530 goto err2;531 532 e->u.iosb.sp = sp;533 qla2x00_post_work(vha, e);534 return;535 }536 537err:538 e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);539err2:540 if (!e) {541 /* please ignore kernel warning. otherwise, we have mem leak. */542 if (sp->u.iocb_cmd.u.ctarg.req) {543 dma_free_coherent(&vha->hw->pdev->dev,544 sp->u.iocb_cmd.u.ctarg.req_allocated_size,545 sp->u.iocb_cmd.u.ctarg.req,546 sp->u.iocb_cmd.u.ctarg.req_dma);547 sp->u.iocb_cmd.u.ctarg.req = NULL;548 }549 550 if (sp->u.iocb_cmd.u.ctarg.rsp) {551 dma_free_coherent(&vha->hw->pdev->dev,552 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,553 sp->u.iocb_cmd.u.ctarg.rsp,554 sp->u.iocb_cmd.u.ctarg.rsp_dma);555 sp->u.iocb_cmd.u.ctarg.rsp = NULL;556 }557 558 /* ref: INIT */559 kref_put(&sp->cmd_kref, qla2x00_sp_release);560 return;561 }562 563 e->u.iosb.sp = sp;564 qla2x00_post_work(vha, e);565}566 567/**568 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.569 * @vha: HA context570 *571 * Returns 0 on success.572 */573int574qla2x00_rft_id(scsi_qla_host_t *vha)575{576 struct qla_hw_data *ha = vha->hw;577 578 if (IS_QLA2100(ha) || IS_QLA2200(ha))579 return qla2x00_sns_rft_id(vha);580 581 return qla_async_rftid(vha, &vha->d_id);582}583 584static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)585{586 int rval = QLA_MEMORY_ALLOC_FAILED;587 struct ct_sns_req *ct_req;588 srb_t *sp;589 struct ct_sns_pkt *ct_sns;590 591 if (!vha->flags.online)592 goto done;593 594 /* ref: INIT */595 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);596 if (!sp)597 goto done;598 599 sp->type = SRB_CT_PTHRU_CMD;600 sp->name = "rft_id";601 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,602 qla2x00_async_sns_sp_done);603 604 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,605 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,606 GFP_KERNEL);607 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);608 if (!sp->u.iocb_cmd.u.ctarg.req) {609 ql_log(ql_log_warn, vha, 0xd041,610 "%s: Failed to allocate ct_sns request.\n",611 __func__);612 goto done_free_sp;613 }614 615 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,616 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,617 GFP_KERNEL);618 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);619 if (!sp->u.iocb_cmd.u.ctarg.rsp) {620 ql_log(ql_log_warn, vha, 0xd042,621 "%s: Failed to allocate ct_sns request.\n",622 __func__);623 goto done_free_sp;624 }625 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;626 memset(ct_sns, 0, sizeof(*ct_sns));627 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;628 629 /* Prepare CT request */630 ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);631 632 /* Prepare CT arguments -- port_id, FC-4 types */633 ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id);634 ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */635 636 if (vha->flags.nvme_enabled && qla_ini_mode_enabled(vha))637 ct_req->req.rft_id.fc4_types[6] = 1; /* NVMe type 28h */638 639 sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;640 sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;641 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;642 643 ql_dbg(ql_dbg_disc, vha, 0xffff,644 "Async-%s - hdl=%x portid %06x.\n",645 sp->name, sp->handle, d_id->b24);646 647 rval = qla2x00_start_sp(sp);648 if (rval != QLA_SUCCESS) {649 ql_dbg(ql_dbg_disc, vha, 0x2043,650 "RFT_ID issue IOCB failed (%d).\n", rval);651 goto done_free_sp;652 }653 return rval;654done_free_sp:655 /* ref: INIT */656 kref_put(&sp->cmd_kref, qla2x00_sp_release);657done:658 return rval;659}660 661/**662 * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.663 * @vha: HA context664 * @type: not used665 *666 * Returns 0 on success.667 */668int669qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)670{671 struct qla_hw_data *ha = vha->hw;672 673 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {674 ql_dbg(ql_dbg_disc, vha, 0x2046,675 "RFF_ID call not supported on ISP2100/ISP2200.\n");676 return (QLA_SUCCESS);677 }678 679 return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha), type);680}681 682static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,683 u8 fc4feature, u8 fc4type)684{685 int rval = QLA_MEMORY_ALLOC_FAILED;686 struct ct_sns_req *ct_req;687 srb_t *sp;688 struct ct_sns_pkt *ct_sns;689 690 /* ref: INIT */691 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);692 if (!sp)693 goto done;694 695 sp->type = SRB_CT_PTHRU_CMD;696 sp->name = "rff_id";697 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,698 qla2x00_async_sns_sp_done);699 700 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,701 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,702 GFP_KERNEL);703 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);704 if (!sp->u.iocb_cmd.u.ctarg.req) {705 ql_log(ql_log_warn, vha, 0xd041,706 "%s: Failed to allocate ct_sns request.\n",707 __func__);708 goto done_free_sp;709 }710 711 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,712 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,713 GFP_KERNEL);714 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);715 if (!sp->u.iocb_cmd.u.ctarg.rsp) {716 ql_log(ql_log_warn, vha, 0xd042,717 "%s: Failed to allocate ct_sns request.\n",718 __func__);719 goto done_free_sp;720 }721 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;722 memset(ct_sns, 0, sizeof(*ct_sns));723 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;724 725 /* Prepare CT request */726 ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);727 728 /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */729 ct_req->req.rff_id.port_id = port_id_to_be_id(*d_id);730 ct_req->req.rff_id.fc4_feature = fc4feature;731 ct_req->req.rff_id.fc4_type = fc4type; /* SCSI-FCP or FC-NVMe */732 733 sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;734 sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;735 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;736 737 ql_dbg(ql_dbg_disc, vha, 0xffff,738 "Async-%s - hdl=%x portid %06x feature %x type %x.\n",739 sp->name, sp->handle, d_id->b24, fc4feature, fc4type);740 741 rval = qla2x00_start_sp(sp);742 if (rval != QLA_SUCCESS) {743 ql_dbg(ql_dbg_disc, vha, 0x2047,744 "RFF_ID issue IOCB failed (%d).\n", rval);745 goto done_free_sp;746 }747 748 return rval;749 750done_free_sp:751 /* ref: INIT */752 kref_put(&sp->cmd_kref, qla2x00_sp_release);753done:754 return rval;755}756 757/**758 * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.759 * @vha: HA context760 *761 * Returns 0 on success.762 */763int764qla2x00_rnn_id(scsi_qla_host_t *vha)765{766 struct qla_hw_data *ha = vha->hw;767 768 if (IS_QLA2100(ha) || IS_QLA2200(ha))769 return qla2x00_sns_rnn_id(vha);770 771 return qla_async_rnnid(vha, &vha->d_id, vha->node_name);772}773 774static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,775 u8 *node_name)776{777 int rval = QLA_MEMORY_ALLOC_FAILED;778 struct ct_sns_req *ct_req;779 srb_t *sp;780 struct ct_sns_pkt *ct_sns;781 782 /* ref: INIT */783 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);784 if (!sp)785 goto done;786 787 sp->type = SRB_CT_PTHRU_CMD;788 sp->name = "rnid";789 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,790 qla2x00_async_sns_sp_done);791 792 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,793 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,794 GFP_KERNEL);795 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);796 if (!sp->u.iocb_cmd.u.ctarg.req) {797 ql_log(ql_log_warn, vha, 0xd041,798 "%s: Failed to allocate ct_sns request.\n",799 __func__);800 goto done_free_sp;801 }802 803 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,804 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,805 GFP_KERNEL);806 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);807 if (!sp->u.iocb_cmd.u.ctarg.rsp) {808 ql_log(ql_log_warn, vha, 0xd042,809 "%s: Failed to allocate ct_sns request.\n",810 __func__);811 goto done_free_sp;812 }813 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;814 memset(ct_sns, 0, sizeof(*ct_sns));815 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;816 817 /* Prepare CT request */818 ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);819 820 /* Prepare CT arguments -- port_id, node_name */821 ct_req->req.rnn_id.port_id = port_id_to_be_id(vha->d_id);822 memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);823 824 sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;825 sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;826 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;827 828 ql_dbg(ql_dbg_disc, vha, 0xffff,829 "Async-%s - hdl=%x portid %06x\n",830 sp->name, sp->handle, d_id->b24);831 832 rval = qla2x00_start_sp(sp);833 if (rval != QLA_SUCCESS) {834 ql_dbg(ql_dbg_disc, vha, 0x204d,835 "RNN_ID issue IOCB failed (%d).\n", rval);836 goto done_free_sp;837 }838 839 return rval;840 841done_free_sp:842 /* ref: INIT */843 kref_put(&sp->cmd_kref, qla2x00_sp_release);844done:845 return rval;846}847 848size_t849qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)850{851 struct qla_hw_data *ha = vha->hw;852 853 if (IS_QLAFX00(ha))854 return scnprintf(snn, size, "%s FW:v%s DVR:v%s",855 ha->model_number, ha->mr.fw_version, qla2x00_version_str);856 857 return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s",858 ha->model_number, ha->fw_major_version, ha->fw_minor_version,859 ha->fw_subminor_version, qla2x00_version_str);860}861 862/**863 * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.864 * @vha: HA context865 *866 * Returns 0 on success.867 */868int869qla2x00_rsnn_nn(scsi_qla_host_t *vha)870{871 struct qla_hw_data *ha = vha->hw;872 873 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {874 ql_dbg(ql_dbg_disc, vha, 0x2050,875 "RSNN_ID call unsupported on ISP2100/ISP2200.\n");876 return (QLA_SUCCESS);877 }878 879 return qla_async_rsnn_nn(vha);880}881 882static int qla_async_rsnn_nn(scsi_qla_host_t *vha)883{884 int rval = QLA_MEMORY_ALLOC_FAILED;885 struct ct_sns_req *ct_req;886 srb_t *sp;887 struct ct_sns_pkt *ct_sns;888 889 /* ref: INIT */890 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);891 if (!sp)892 goto done;893 894 sp->type = SRB_CT_PTHRU_CMD;895 sp->name = "rsnn_nn";896 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,897 qla2x00_async_sns_sp_done);898 899 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,900 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,901 GFP_KERNEL);902 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);903 if (!sp->u.iocb_cmd.u.ctarg.req) {904 ql_log(ql_log_warn, vha, 0xd041,905 "%s: Failed to allocate ct_sns request.\n",906 __func__);907 goto done_free_sp;908 }909 910 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,911 sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,912 GFP_KERNEL);913 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);914 if (!sp->u.iocb_cmd.u.ctarg.rsp) {915 ql_log(ql_log_warn, vha, 0xd042,916 "%s: Failed to allocate ct_sns request.\n",917 __func__);918 goto done_free_sp;919 }920 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;921 memset(ct_sns, 0, sizeof(*ct_sns));922 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;923 924 /* Prepare CT request */925 ct_req = qla2x00_prep_ct_req(ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE);926 927 /* Prepare CT arguments -- node_name, symbolic node_name, size */928 memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);929 930 /* Prepare the Symbolic Node Name */931 qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,932 sizeof(ct_req->req.rsnn_nn.sym_node_name));933 ct_req->req.rsnn_nn.name_len =934 (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);935 936 937 sp->u.iocb_cmd.u.ctarg.req_size = 24 + 1 + ct_req->req.rsnn_nn.name_len;938 sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;939 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;940 941 ql_dbg(ql_dbg_disc, vha, 0xffff,942 "Async-%s - hdl=%x.\n",943 sp->name, sp->handle);944 945 rval = qla2x00_start_sp(sp);946 if (rval != QLA_SUCCESS) {947 ql_dbg(ql_dbg_disc, vha, 0x2043,948 "RFT_ID issue IOCB failed (%d).\n", rval);949 goto done_free_sp;950 }951 952 return rval;953 954done_free_sp:955 /* ref: INIT */956 kref_put(&sp->cmd_kref, qla2x00_sp_release);957done:958 return rval;959}960 961/**962 * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.963 * @vha: HA context964 * @cmd: GS command965 * @scmd_len: Subcommand length966 * @data_size: response size in bytes967 *968 * Returns a pointer to the @ha's sns_cmd.969 */970static inline struct sns_cmd_pkt *971qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,972 uint16_t data_size)973{974 uint16_t wc;975 struct sns_cmd_pkt *sns_cmd;976 struct qla_hw_data *ha = vha->hw;977 978 sns_cmd = ha->sns_cmd;979 memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));980 wc = data_size / 2; /* Size in 16bit words. */981 sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);982 put_unaligned_le64(ha->sns_cmd_dma, &sns_cmd->p.cmd.buffer_address);983 sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);984 sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);985 wc = (data_size - 16) / 4; /* Size in 32bit words. */986 sns_cmd->p.cmd.size = cpu_to_le16(wc);987 988 vha->qla_stats.control_requests++;989 990 return (sns_cmd);991}992 993/**994 * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.995 * @vha: HA context996 * @fcport: fcport entry to updated997 *998 * This command uses the old Exectute SNS Command mailbox routine.999 *1000 * Returns 0 on success.1001 */1002static int1003qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)1004{1005 int rval = QLA_SUCCESS;1006 struct qla_hw_data *ha = vha->hw;1007 struct sns_cmd_pkt *sns_cmd;1008 1009 /* Issue GA_NXT. */1010 /* Prepare SNS command request. */1011 sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,1012 GA_NXT_SNS_DATA_SIZE);1013 1014 /* Prepare SNS command arguments -- port_id. */1015 sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;1016 sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;1017 sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;1018 1019 /* Execute SNS command. */1020 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,1021 sizeof(struct sns_cmd_pkt));1022 if (rval != QLA_SUCCESS) {1023 /*EMPTY*/1024 ql_dbg(ql_dbg_disc, vha, 0x205f,1025 "GA_NXT Send SNS failed (%d).\n", rval);1026 } else if (sns_cmd->p.gan_data[8] != 0x80 ||1027 sns_cmd->p.gan_data[9] != 0x02) {1028 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,1029 "GA_NXT failed, rejected request ga_nxt_rsp:\n");1030 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,1031 sns_cmd->p.gan_data, 16);1032 rval = QLA_FUNCTION_FAILED;1033 } else {1034 /* Populate fc_port_t entry. */1035 fcport->d_id.b.domain = sns_cmd->p.gan_data[17];1036 fcport->d_id.b.area = sns_cmd->p.gan_data[18];1037 fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];1038 1039 memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);1040 memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);1041 1042 if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&1043 sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)1044 fcport->d_id.b.domain = 0xf0;1045 1046 ql_dbg(ql_dbg_disc, vha, 0x2061,1047 "GA_NXT entry - nn %8phN pn %8phN "1048 "port_id=%02x%02x%02x.\n",1049 fcport->node_name, fcport->port_name,1050 fcport->d_id.b.domain, fcport->d_id.b.area,1051 fcport->d_id.b.al_pa);1052 }1053 1054 return (rval);1055}1056 1057/**1058 * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.1059 * @vha: HA context1060 * @list: switch info entries to populate1061 *1062 * This command uses the old Exectute SNS Command mailbox routine.1063 *1064 * NOTE: Non-Nx_Ports are not requested.1065 *1066 * Returns 0 on success.1067 */1068static int1069qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)1070{1071 int rval;1072 struct qla_hw_data *ha = vha->hw;1073 uint16_t i;1074 uint8_t *entry;1075 struct sns_cmd_pkt *sns_cmd;1076 uint16_t gid_pt_sns_data_size;1077 1078 gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);1079 1080 /* Issue GID_PT. */1081 /* Prepare SNS command request. */1082 sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,1083 gid_pt_sns_data_size);1084 1085 /* Prepare SNS command arguments -- port_type. */1086 sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;1087 1088 /* Execute SNS command. */1089 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,1090 sizeof(struct sns_cmd_pkt));1091 if (rval != QLA_SUCCESS) {1092 /*EMPTY*/1093 ql_dbg(ql_dbg_disc, vha, 0x206d,1094 "GID_PT Send SNS failed (%d).\n", rval);1095 } else if (sns_cmd->p.gid_data[8] != 0x80 ||1096 sns_cmd->p.gid_data[9] != 0x02) {1097 ql_dbg(ql_dbg_disc, vha, 0x202f,1098 "GID_PT failed, rejected request, gid_rsp:\n");1099 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,1100 sns_cmd->p.gid_data, 16);1101 rval = QLA_FUNCTION_FAILED;1102 } else {1103 /* Set port IDs in switch info list. */1104 for (i = 0; i < ha->max_fibre_devices; i++) {1105 entry = &sns_cmd->p.gid_data[(i * 4) + 16];1106 list[i].d_id.b.domain = entry[1];1107 list[i].d_id.b.area = entry[2];1108 list[i].d_id.b.al_pa = entry[3];1109 1110 /* Last one exit. */1111 if (entry[0] & BIT_7) {1112 list[i].d_id.b.rsvd_1 = entry[0];1113 break;1114 }1115 }1116 1117 /*1118 * If we've used all available slots, then the switch is1119 * reporting back more devices that we can handle with this1120 * single call. Return a failed status, and let GA_NXT handle1121 * the overload.1122 */1123 if (i == ha->max_fibre_devices)1124 rval = QLA_FUNCTION_FAILED;1125 }1126 1127 return (rval);1128}1129 1130/**1131 * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.1132 * @vha: HA context1133 * @list: switch info entries to populate1134 *1135 * This command uses the old Exectute SNS Command mailbox routine.1136 *1137 * Returns 0 on success.1138 */1139static int1140qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)1141{1142 int rval = QLA_SUCCESS;1143 struct qla_hw_data *ha = vha->hw;1144 uint16_t i;1145 struct sns_cmd_pkt *sns_cmd;1146 1147 for (i = 0; i < ha->max_fibre_devices; i++) {1148 /* Issue GPN_ID */1149 /* Prepare SNS command request. */1150 sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,1151 GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);1152 1153 /* Prepare SNS command arguments -- port_id. */1154 sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;1155 sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;1156 sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;1157 1158 /* Execute SNS command. */1159 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,1160 GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));1161 if (rval != QLA_SUCCESS) {1162 /*EMPTY*/1163 ql_dbg(ql_dbg_disc, vha, 0x2032,1164 "GPN_ID Send SNS failed (%d).\n", rval);1165 } else if (sns_cmd->p.gpn_data[8] != 0x80 ||1166 sns_cmd->p.gpn_data[9] != 0x02) {1167 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,1168 "GPN_ID failed, rejected request, gpn_rsp:\n");1169 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,1170 sns_cmd->p.gpn_data, 16);1171 rval = QLA_FUNCTION_FAILED;1172 } else {1173 /* Save portname */1174 memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],1175 WWN_SIZE);1176 }1177 1178 /* Last device exit. */1179 if (list[i].d_id.b.rsvd_1 != 0)1180 break;1181 }1182 1183 return (rval);1184}1185 1186/**1187 * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.1188 * @vha: HA context1189 * @list: switch info entries to populate1190 *1191 * This command uses the old Exectute SNS Command mailbox routine.1192 *1193 * Returns 0 on success.1194 */1195static int1196qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)1197{1198 int rval = QLA_SUCCESS;1199 struct qla_hw_data *ha = vha->hw;1200 uint16_t i;1201 struct sns_cmd_pkt *sns_cmd;1202 1203 for (i = 0; i < ha->max_fibre_devices; i++) {1204 /* Issue GNN_ID */1205 /* Prepare SNS command request. */1206 sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,1207 GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);1208 1209 /* Prepare SNS command arguments -- port_id. */1210 sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;1211 sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;1212 sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;1213 1214 /* Execute SNS command. */1215 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,1216 GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));1217 if (rval != QLA_SUCCESS) {1218 /*EMPTY*/1219 ql_dbg(ql_dbg_disc, vha, 0x203f,1220 "GNN_ID Send SNS failed (%d).\n", rval);1221 } else if (sns_cmd->p.gnn_data[8] != 0x80 ||1222 sns_cmd->p.gnn_data[9] != 0x02) {1223 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,1224 "GNN_ID failed, rejected request, gnn_rsp:\n");1225 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,1226 sns_cmd->p.gnn_data, 16);1227 rval = QLA_FUNCTION_FAILED;1228 } else {1229 /* Save nodename */1230 memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],1231 WWN_SIZE);1232 1233 ql_dbg(ql_dbg_disc, vha, 0x206e,1234 "GID_PT entry - nn %8phN pn %8phN "1235 "port_id=%02x%02x%02x.\n",1236 list[i].node_name, list[i].port_name,1237 list[i].d_id.b.domain, list[i].d_id.b.area,1238 list[i].d_id.b.al_pa);1239 }1240 1241 /* Last device exit. */1242 if (list[i].d_id.b.rsvd_1 != 0)1243 break;1244 }1245 1246 return (rval);1247}1248 1249/**1250 * qla2x00_sns_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.1251 * @vha: HA context1252 *1253 * This command uses the old Exectute SNS Command mailbox routine.1254 *1255 * Returns 0 on success.1256 */1257static int1258qla2x00_sns_rft_id(scsi_qla_host_t *vha)1259{1260 int rval;1261 struct qla_hw_data *ha = vha->hw;1262 struct sns_cmd_pkt *sns_cmd;1263 1264 /* Issue RFT_ID. */1265 /* Prepare SNS command request. */1266 sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,1267 RFT_ID_SNS_DATA_SIZE);1268 1269 /* Prepare SNS command arguments -- port_id, FC-4 types */1270 sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;1271 sns_cmd->p.cmd.param[1] = vha->d_id.b.area;1272 sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;1273 1274 sns_cmd->p.cmd.param[5] = 0x01; /* FCP-3 */1275 1276 /* Execute SNS command. */1277 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,1278 sizeof(struct sns_cmd_pkt));1279 if (rval != QLA_SUCCESS) {1280 /*EMPTY*/1281 ql_dbg(ql_dbg_disc, vha, 0x2060,1282 "RFT_ID Send SNS failed (%d).\n", rval);1283 } else if (sns_cmd->p.rft_data[8] != 0x80 ||1284 sns_cmd->p.rft_data[9] != 0x02) {1285 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,1286 "RFT_ID failed, rejected request rft_rsp:\n");1287 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,1288 sns_cmd->p.rft_data, 16);1289 rval = QLA_FUNCTION_FAILED;1290 } else {1291 ql_dbg(ql_dbg_disc, vha, 0x2073,1292 "RFT_ID exiting normally.\n");1293 }1294 1295 return (rval);1296}1297 1298/**1299 * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.1300 * @vha: HA context1301 *1302 * This command uses the old Exectute SNS Command mailbox routine.1303 *1304 * Returns 0 on success.1305 */1306static int1307qla2x00_sns_rnn_id(scsi_qla_host_t *vha)1308{1309 int rval;1310 struct qla_hw_data *ha = vha->hw;1311 struct sns_cmd_pkt *sns_cmd;1312 1313 /* Issue RNN_ID. */1314 /* Prepare SNS command request. */1315 sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,1316 RNN_ID_SNS_DATA_SIZE);1317 1318 /* Prepare SNS command arguments -- port_id, nodename. */1319 sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;1320 sns_cmd->p.cmd.param[1] = vha->d_id.b.area;1321 sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;1322 1323 sns_cmd->p.cmd.param[4] = vha->node_name[7];1324 sns_cmd->p.cmd.param[5] = vha->node_name[6];1325 sns_cmd->p.cmd.param[6] = vha->node_name[5];1326 sns_cmd->p.cmd.param[7] = vha->node_name[4];1327 sns_cmd->p.cmd.param[8] = vha->node_name[3];1328 sns_cmd->p.cmd.param[9] = vha->node_name[2];1329 sns_cmd->p.cmd.param[10] = vha->node_name[1];1330 sns_cmd->p.cmd.param[11] = vha->node_name[0];1331 1332 /* Execute SNS command. */1333 rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,1334 sizeof(struct sns_cmd_pkt));1335 if (rval != QLA_SUCCESS) {1336 /*EMPTY*/1337 ql_dbg(ql_dbg_disc, vha, 0x204a,1338 "RNN_ID Send SNS failed (%d).\n", rval);1339 } else if (sns_cmd->p.rnn_data[8] != 0x80 ||1340 sns_cmd->p.rnn_data[9] != 0x02) {1341 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,1342 "RNN_ID failed, rejected request, rnn_rsp:\n");1343 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,1344 sns_cmd->p.rnn_data, 16);1345 rval = QLA_FUNCTION_FAILED;1346 } else {1347 ql_dbg(ql_dbg_disc, vha, 0x204c,1348 "RNN_ID exiting normally.\n");1349 }1350 1351 return (rval);1352}1353 1354/**1355 * qla2x00_mgmt_svr_login() - Login to fabric Management Service.1356 * @vha: HA context1357 *1358 * Returns 0 on success.1359 */1360int1361qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)1362{1363 int ret, rval;1364 uint16_t mb[MAILBOX_REGISTER_COUNT];1365 struct qla_hw_data *ha = vha->hw;1366 1367 ret = QLA_SUCCESS;1368 if (vha->flags.management_server_logged_in)1369 return ret;1370 1371 rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,1372 0xfa, mb, BIT_1);1373 if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {1374 if (rval == QLA_MEMORY_ALLOC_FAILED)1375 ql_dbg(ql_dbg_disc, vha, 0x2085,1376 "Failed management_server login: loopid=%x "1377 "rval=%d\n", vha->mgmt_svr_loop_id, rval);1378 else1379 ql_dbg(ql_dbg_disc, vha, 0x2024,1380 "Failed management_server login: loopid=%x "1381 "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",1382 vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],1383 mb[7]);1384 ret = QLA_FUNCTION_FAILED;1385 } else1386 vha->flags.management_server_logged_in = 1;1387 1388 return ret;1389}1390 1391/**1392 * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.1393 * @vha: HA context1394 * @req_size: request size in bytes1395 * @rsp_size: response size in bytes1396 *1397 * Returns a pointer to the @ha's ms_iocb.1398 */1399void *1400qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,1401 uint32_t rsp_size)1402{1403 ms_iocb_entry_t *ms_pkt;1404 struct qla_hw_data *ha = vha->hw;1405 1406 ms_pkt = ha->ms_iocb;1407 memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));1408 1409 ms_pkt->entry_type = MS_IOCB_TYPE;1410 ms_pkt->entry_count = 1;1411 SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);1412 ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);1413 ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);1414 ms_pkt->cmd_dsd_count = cpu_to_le16(1);1415 ms_pkt->total_dsd_count = cpu_to_le16(2);1416 ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);1417 ms_pkt->req_bytecount = cpu_to_le32(req_size);1418 1419 put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->req_dsd.address);1420 ms_pkt->req_dsd.length = ms_pkt->req_bytecount;1421 1422 put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->rsp_dsd.address);1423 ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;1424 1425 return ms_pkt;1426}1427 1428/**1429 * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.1430 * @vha: HA context1431 * @req_size: request size in bytes1432 * @rsp_size: response size in bytes1433 *1434 * Returns a pointer to the @ha's ms_iocb.1435 */1436void *1437qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,1438 uint32_t rsp_size)1439{1440 struct ct_entry_24xx *ct_pkt;1441 struct qla_hw_data *ha = vha->hw;1442 1443 ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;1444 memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));1445 1446 ct_pkt->entry_type = CT_IOCB_TYPE;1447 ct_pkt->entry_count = 1;1448 ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);1449 ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);1450 ct_pkt->cmd_dsd_count = cpu_to_le16(1);1451 ct_pkt->rsp_dsd_count = cpu_to_le16(1);1452 ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);1453 ct_pkt->cmd_byte_count = cpu_to_le32(req_size);1454 1455 put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[0].address);1456 ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;1457 1458 put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[1].address);1459 ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;1460 ct_pkt->vp_index = vha->vp_idx;1461 1462 return ct_pkt;1463}1464 1465static void1466qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)1467{1468 struct qla_hw_data *ha = vha->hw;1469 ms_iocb_entry_t *ms_pkt = ha->ms_iocb;1470 struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;1471 1472 if (IS_FWI2_CAPABLE(ha)) {1473 ct_pkt->cmd_byte_count = cpu_to_le32(req_size);1474 ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;1475 } else {1476 ms_pkt->req_bytecount = cpu_to_le32(req_size);1477 ms_pkt->req_dsd.length = ms_pkt->req_bytecount;1478 }1479}1480 1481/**1482 * qla2x00_prep_ct_fdmi_req() - Prepare common CT request fields for SNS query.1483 * @p: CT request buffer1484 * @cmd: GS command1485 * @rsp_size: response size in bytes1486 *1487 * Returns a pointer to the intitialized @ct_req.1488 */1489static inline struct ct_sns_req *1490qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,1491 uint16_t rsp_size)1492{1493 memset(p, 0, sizeof(struct ct_sns_pkt));1494 1495 p->p.req.header.revision = 0x01;1496 p->p.req.header.gs_type = 0xFA;1497 p->p.req.header.gs_subtype = 0x10;1498 p->p.req.command = cpu_to_be16(cmd);1499 p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);1500 1501 return &p->p.req;1502}1503 1504uint1505qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha)1506{1507 uint speeds = 0;1508 1509 if (IS_CNA_CAPABLE(ha))1510 return FDMI_PORT_SPEED_10GB;1511 if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {1512 if (ha->max_supported_speed == 2) {1513 if (ha->min_supported_speed <= 6)1514 speeds |= FDMI_PORT_SPEED_64GB;1515 }1516 if (ha->max_supported_speed == 2 ||1517 ha->max_supported_speed == 1) {1518 if (ha->min_supported_speed <= 5)1519 speeds |= FDMI_PORT_SPEED_32GB;1520 }1521 if (ha->max_supported_speed == 2 ||1522 ha->max_supported_speed == 1 ||1523 ha->max_supported_speed == 0) {1524 if (ha->min_supported_speed <= 4)1525 speeds |= FDMI_PORT_SPEED_16GB;1526 }1527 if (ha->max_supported_speed == 1 ||1528 ha->max_supported_speed == 0) {1529 if (ha->min_supported_speed <= 3)1530 speeds |= FDMI_PORT_SPEED_8GB;1531 }1532 if (ha->max_supported_speed == 0) {1533 if (ha->min_supported_speed <= 2)1534 speeds |= FDMI_PORT_SPEED_4GB;1535 }1536 return speeds;1537 }1538 if (IS_QLA2031(ha)) {1539 if ((ha->pdev->subsystem_vendor == 0x103C) &&1540 ((ha->pdev->subsystem_device == 0x8002) ||1541 (ha->pdev->subsystem_device == 0x8086))) {1542 speeds = FDMI_PORT_SPEED_16GB;1543 } else {1544 speeds = FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB|1545 FDMI_PORT_SPEED_4GB;1546 }1547 return speeds;1548 }1549 if (IS_QLA25XX(ha) || IS_QLAFX00(ha))1550 return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB|1551 FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;1552 if (IS_QLA24XX_TYPE(ha))1553 return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB|1554 FDMI_PORT_SPEED_1GB;1555 if (IS_QLA23XX(ha))1556 return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;1557 return FDMI_PORT_SPEED_1GB;1558}1559 1560uint1561qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha)1562{1563 switch (ha->link_data_rate) {1564 case PORT_SPEED_1GB:1565 return FDMI_PORT_SPEED_1GB;1566 case PORT_SPEED_2GB:1567 return FDMI_PORT_SPEED_2GB;1568 case PORT_SPEED_4GB:1569 return FDMI_PORT_SPEED_4GB;1570 case PORT_SPEED_8GB:1571 return FDMI_PORT_SPEED_8GB;1572 case PORT_SPEED_10GB:1573 return FDMI_PORT_SPEED_10GB;1574 case PORT_SPEED_16GB:1575 return FDMI_PORT_SPEED_16GB;1576 case PORT_SPEED_32GB:1577 return FDMI_PORT_SPEED_32GB;1578 case PORT_SPEED_64GB:1579 return FDMI_PORT_SPEED_64GB;1580 default:1581 return FDMI_PORT_SPEED_UNKNOWN;1582 }1583}1584 1585/**1586 * qla2x00_hba_attributes() - perform HBA attributes registration1587 * @vha: HA context1588 * @entries: number of entries to use1589 * @callopt: Option to issue extended or standard FDMI1590 * command parameter1591 *1592 * Returns 0 on success.1593 */1594static unsigned long1595qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,1596 unsigned int callopt)1597{1598 struct qla_hw_data *ha = vha->hw;1599 struct new_utsname *p_sysid = utsname();1600 struct ct_fdmi_hba_attr *eiter;1601 uint16_t alen;1602 unsigned long size = 0;1603 1604 /* Nodename. */1605 eiter = entries + size;1606 eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);1607 memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));1608 alen = sizeof(eiter->a.node_name);1609 alen += FDMI_ATTR_TYPELEN(eiter);1610 eiter->len = cpu_to_be16(alen);1611 size += alen;1612 ql_dbg(ql_dbg_disc, vha, 0x20a0,1613 "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));1614 /* Manufacturer. */1615 eiter = entries + size;1616 eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);1617 alen = scnprintf(1618 eiter->a.manufacturer, sizeof(eiter->a.manufacturer),1619 "%s", QLA2XXX_MANUFACTURER);1620 alen += FDMI_ATTR_ALIGNMENT(alen);1621 alen += FDMI_ATTR_TYPELEN(eiter);1622 eiter->len = cpu_to_be16(alen);1623 size += alen;1624 ql_dbg(ql_dbg_disc, vha, 0x20a1,1625 "MANUFACTURER = %s.\n", eiter->a.manufacturer);1626 /* Serial number. */1627 eiter = entries + size;1628 eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);1629 alen = 0;1630 if (IS_FWI2_CAPABLE(ha)) {1631 alen = qla2xxx_get_vpd_field(vha, "SN",1632 eiter->a.serial_num, sizeof(eiter->a.serial_num));1633 }1634 if (!alen) {1635 uint32_t sn = ((ha->serial0 & 0x1f) << 16) |1636 (ha->serial2 << 8) | ha->serial1;1637 alen = scnprintf(1638 eiter->a.serial_num, sizeof(eiter->a.serial_num),1639 "%c%05d", 'A' + sn / 100000, sn % 100000);1640 }1641 alen += FDMI_ATTR_ALIGNMENT(alen);1642 alen += FDMI_ATTR_TYPELEN(eiter);1643 eiter->len = cpu_to_be16(alen);1644 size += alen;1645 ql_dbg(ql_dbg_disc, vha, 0x20a2,1646 "SERIAL NUMBER = %s.\n", eiter->a.serial_num);1647 /* Model name. */1648 eiter = entries + size;1649 eiter->type = cpu_to_be16(FDMI_HBA_MODEL);1650 alen = scnprintf(1651 eiter->a.model, sizeof(eiter->a.model),1652 "%s", ha->model_number);1653 alen += FDMI_ATTR_ALIGNMENT(alen);1654 alen += FDMI_ATTR_TYPELEN(eiter);1655 eiter->len = cpu_to_be16(alen);1656 size += alen;1657 ql_dbg(ql_dbg_disc, vha, 0x20a3,1658 "MODEL NAME = %s.\n", eiter->a.model);1659 /* Model description. */1660 eiter = entries + size;1661 eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);1662 alen = scnprintf(1663 eiter->a.model_desc, sizeof(eiter->a.model_desc),1664 "%s", ha->model_desc);1665 alen += FDMI_ATTR_ALIGNMENT(alen);1666 alen += FDMI_ATTR_TYPELEN(eiter);1667 eiter->len = cpu_to_be16(alen);1668 size += alen;1669 ql_dbg(ql_dbg_disc, vha, 0x20a4,1670 "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc);1671 /* Hardware version. */1672 eiter = entries + size;1673 eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);1674 alen = 0;1675 if (IS_FWI2_CAPABLE(ha)) {1676 if (!alen) {1677 alen = qla2xxx_get_vpd_field(vha, "MN",1678 eiter->a.hw_version, sizeof(eiter->a.hw_version));1679 }1680 if (!alen) {1681 alen = qla2xxx_get_vpd_field(vha, "EC",1682 eiter->a.hw_version, sizeof(eiter->a.hw_version));1683 }1684 }1685 if (!alen) {1686 alen = scnprintf(1687 eiter->a.hw_version, sizeof(eiter->a.hw_version),1688 "HW:%s", ha->adapter_id);1689 }1690 alen += FDMI_ATTR_ALIGNMENT(alen);1691 alen += FDMI_ATTR_TYPELEN(eiter);1692 eiter->len = cpu_to_be16(alen);1693 size += alen;1694 ql_dbg(ql_dbg_disc, vha, 0x20a5,1695 "HARDWARE VERSION = %s.\n", eiter->a.hw_version);1696 /* Driver version. */1697 eiter = entries + size;1698 eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);1699 alen = scnprintf(1700 eiter->a.driver_version, sizeof(eiter->a.driver_version),1701 "%s", qla2x00_version_str);1702 alen += FDMI_ATTR_ALIGNMENT(alen);1703 alen += FDMI_ATTR_TYPELEN(eiter);1704 eiter->len = cpu_to_be16(alen);1705 size += alen;1706 ql_dbg(ql_dbg_disc, vha, 0x20a6,1707 "DRIVER VERSION = %s.\n", eiter->a.driver_version);1708 /* Option ROM version. */1709 eiter = entries + size;1710 eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);1711 alen = scnprintf(1712 eiter->a.orom_version, sizeof(eiter->a.orom_version),1713 "%d.%02d", ha->efi_revision[1], ha->efi_revision[0]);1714 alen += FDMI_ATTR_ALIGNMENT(alen);1715 alen += FDMI_ATTR_TYPELEN(eiter);1716 eiter->len = cpu_to_be16(alen);1717 size += alen;1718 1719 ql_dbg(ql_dbg_disc, vha, 0x20a7,1720 "OPTROM VERSION = %d.%02d.\n",1721 eiter->a.orom_version[1], eiter->a.orom_version[0]);1722 /* Firmware version */1723 eiter = entries + size;1724 eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);1725 ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,1726 sizeof(eiter->a.fw_version));1727 alen += FDMI_ATTR_ALIGNMENT(alen);1728 alen += FDMI_ATTR_TYPELEN(eiter);1729 eiter->len = cpu_to_be16(alen);1730 size += alen;1731 ql_dbg(ql_dbg_disc, vha, 0x20a8,1732 "FIRMWARE VERSION = %s.\n", eiter->a.fw_version);1733 /* OS Name and Version */1734 eiter = entries + size;1735 eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);1736 alen = 0;1737 if (p_sysid) {1738 alen = scnprintf(1739 eiter->a.os_version, sizeof(eiter->a.os_version),1740 "%s %s %s",1741 p_sysid->sysname, p_sysid->release, p_sysid->machine);1742 }1743 if (!alen) {1744 alen = scnprintf(1745 eiter->a.os_version, sizeof(eiter->a.os_version),1746 "%s %s",1747 "Linux", fc_host_system_hostname(vha->host));1748 }1749 alen += FDMI_ATTR_ALIGNMENT(alen);1750 alen += FDMI_ATTR_TYPELEN(eiter);1751 eiter->len = cpu_to_be16(alen);1752 size += alen;1753 ql_dbg(ql_dbg_disc, vha, 0x20a9,1754 "OS VERSION = %s.\n", eiter->a.os_version);1755 if (callopt == CALLOPT_FDMI1)1756 goto done;1757 /* MAX CT Payload Length */1758 eiter = entries + size;1759 eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);1760 eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size >> 2);1761 1762 alen = sizeof(eiter->a.max_ct_len);1763 alen += FDMI_ATTR_TYPELEN(eiter);1764 eiter->len = cpu_to_be16(alen);1765 size += alen;1766 ql_dbg(ql_dbg_disc, vha, 0x20aa,1767 "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len));1768 /* Node Symbolic Name */1769 eiter = entries + size;1770 eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);1771 alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name,1772 sizeof(eiter->a.sym_name));1773 alen += FDMI_ATTR_ALIGNMENT(alen);1774 alen += FDMI_ATTR_TYPELEN(eiter);1775 eiter->len = cpu_to_be16(alen);1776 size += alen;1777 ql_dbg(ql_dbg_disc, vha, 0x20ab,1778 "SYMBOLIC NAME = %s.\n", eiter->a.sym_name);1779 /* Vendor Specific information */1780 eiter = entries + size;1781 eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO);1782 eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC);1783 alen = sizeof(eiter->a.vendor_specific_info);1784 alen += FDMI_ATTR_TYPELEN(eiter);1785 eiter->len = cpu_to_be16(alen);1786 size += alen;1787 ql_dbg(ql_dbg_disc, vha, 0x20ac,1788 "VENDOR SPECIFIC INFO = 0x%x.\n",1789 be32_to_cpu(eiter->a.vendor_specific_info));1790 /* Num Ports */1791 eiter = entries + size;1792 eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);1793 eiter->a.num_ports = cpu_to_be32(1);1794 alen = sizeof(eiter->a.num_ports);1795 alen += FDMI_ATTR_TYPELEN(eiter);1796 eiter->len = cpu_to_be16(alen);1797 size += alen;1798 ql_dbg(ql_dbg_disc, vha, 0x20ad,1799 "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));1800 /* Fabric Name */1801 eiter = entries + size;1802 eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);1803 memcpy(eiter->a.fabric_name, vha->fabric_node_name,1804 sizeof(eiter->a.fabric_name));1805 alen = sizeof(eiter->a.fabric_name);1806 alen += FDMI_ATTR_TYPELEN(eiter);1807 eiter->len = cpu_to_be16(alen);1808 size += alen;1809 ql_dbg(ql_dbg_disc, vha, 0x20ae,1810 "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));1811 /* BIOS Version */1812 eiter = entries + size;1813 eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);1814 alen = scnprintf(1815 eiter->a.bios_name, sizeof(eiter->a.bios_name),1816 "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);1817 alen += FDMI_ATTR_ALIGNMENT(alen);1818 alen += FDMI_ATTR_TYPELEN(eiter);1819 eiter->len = cpu_to_be16(alen);1820 size += alen;1821 ql_dbg(ql_dbg_disc, vha, 0x20af,1822 "BIOS NAME = %s\n", eiter->a.bios_name);1823 /* Vendor Identifier */1824 eiter = entries + size;1825 eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER);1826 alen = scnprintf(1827 eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),1828 "%s", "QLGC");1829 alen += FDMI_ATTR_ALIGNMENT(alen);1830 alen += FDMI_ATTR_TYPELEN(eiter);1831 eiter->len = cpu_to_be16(alen);1832 size += alen;1833 ql_dbg(ql_dbg_disc, vha, 0x20b0,1834 "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier);1835done:1836 return size;1837}1838 1839/**1840 * qla2x00_port_attributes() - perform Port attributes registration1841 * @vha: HA context1842 * @entries: number of entries to use1843 * @callopt: Option to issue extended or standard FDMI1844 * command parameter1845 *1846 * Returns 0 on success.1847 */1848static unsigned long1849qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,1850 unsigned int callopt)1851{1852 struct qla_hw_data *ha = vha->hw;1853 struct new_utsname *p_sysid = utsname();1854 char *hostname = p_sysid ?1855 p_sysid->nodename : fc_host_system_hostname(vha->host);1856 struct ct_fdmi_port_attr *eiter;1857 uint16_t alen;1858 unsigned long size = 0;1859 1860 /* FC4 types. */1861 eiter = entries + size;1862 eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);1863 eiter->a.fc4_types[0] = 0x00;1864 eiter->a.fc4_types[1] = 0x00;1865 eiter->a.fc4_types[2] = 0x01;1866 eiter->a.fc4_types[3] = 0x00;1867 alen = sizeof(eiter->a.fc4_types);1868 alen += FDMI_ATTR_TYPELEN(eiter);1869 eiter->len = cpu_to_be16(alen);1870 size += alen;1871 ql_dbg(ql_dbg_disc, vha, 0x20c0,1872 "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types);1873 if (vha->flags.nvme_enabled) {1874 eiter->a.fc4_types[6] = 1; /* NVMe type 28h */1875 ql_dbg(ql_dbg_disc, vha, 0x211f,1876 "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",1877 eiter->a.fc4_types[6]);1878 }1879 /* Supported speed. */1880 eiter = entries + size;1881 eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);1882 eiter->a.sup_speed = cpu_to_be32(1883 qla25xx_fdmi_port_speed_capability(ha));1884 alen = sizeof(eiter->a.sup_speed);1885 alen += FDMI_ATTR_TYPELEN(eiter);1886 eiter->len = cpu_to_be16(alen);1887 size += alen;1888 ql_dbg(ql_dbg_disc, vha, 0x20c1,1889 "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed));1890 /* Current speed. */1891 eiter = entries + size;1892 eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);1893 eiter->a.cur_speed = cpu_to_be32(1894 qla25xx_fdmi_port_speed_currently(ha));1895 alen = sizeof(eiter->a.cur_speed);1896 alen += FDMI_ATTR_TYPELEN(eiter);1897 eiter->len = cpu_to_be16(alen);1898 size += alen;1899 ql_dbg(ql_dbg_disc, vha, 0x20c2,1900 "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed));1901 /* Max frame size. */1902 eiter = entries + size;1903 eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);1904 eiter->a.max_frame_size = cpu_to_be32(ha->frame_payload_size);1905 alen = sizeof(eiter->a.max_frame_size);1906 alen += FDMI_ATTR_TYPELEN(eiter);1907 eiter->len = cpu_to_be16(alen);1908 size += alen;1909 ql_dbg(ql_dbg_disc, vha, 0x20c3,1910 "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size));1911 /* OS device name. */1912 eiter = entries + size;1913 eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);1914 alen = scnprintf(1915 eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),1916 "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);1917 alen += FDMI_ATTR_ALIGNMENT(alen);1918 alen += FDMI_ATTR_TYPELEN(eiter);1919 eiter->len = cpu_to_be16(alen);1920 size += alen;1921 ql_dbg(ql_dbg_disc, vha, 0x20c4,1922 "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name);1923 /* Hostname. */1924 eiter = entries + size;1925 eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);1926 if (!*hostname || !strncmp(hostname, "(none)", 6))1927 hostname = "Linux-default";1928 alen = scnprintf(1929 eiter->a.host_name, sizeof(eiter->a.host_name),1930 "%s", hostname);1931 alen += FDMI_ATTR_ALIGNMENT(alen);1932 alen += FDMI_ATTR_TYPELEN(eiter);1933 eiter->len = cpu_to_be16(alen);1934 size += alen;1935 ql_dbg(ql_dbg_disc, vha, 0x20c5,1936 "HOSTNAME = %s.\n", eiter->a.host_name);1937 1938 if (callopt == CALLOPT_FDMI1)1939 goto done;1940 1941 /* Node Name */1942 eiter = entries + size;1943 eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);1944 memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));1945 alen = sizeof(eiter->a.node_name);1946 alen += FDMI_ATTR_TYPELEN(eiter);1947 eiter->len = cpu_to_be16(alen);1948 size += alen;1949 ql_dbg(ql_dbg_disc, vha, 0x20c6,1950 "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));1951 1952 /* Port Name */1953 eiter = entries + size;1954 eiter->type = cpu_to_be16(FDMI_PORT_NAME);1955 memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name));1956 alen = sizeof(eiter->a.port_name);1957 alen += FDMI_ATTR_TYPELEN(eiter);1958 eiter->len = cpu_to_be16(alen);1959 size += alen;1960 ql_dbg(ql_dbg_disc, vha, 0x20c7,1961 "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name));1962 1963 /* Port Symbolic Name */1964 eiter = entries + size;1965 eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);1966 alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,1967 sizeof(eiter->a.port_sym_name));1968 alen += FDMI_ATTR_ALIGNMENT(alen);1969 alen += FDMI_ATTR_TYPELEN(eiter);1970 eiter->len = cpu_to_be16(alen);1971 size += alen;1972 ql_dbg(ql_dbg_disc, vha, 0x20c8,1973 "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name);1974 1975 /* Port Type */1976 eiter = entries + size;1977 eiter->type = cpu_to_be16(FDMI_PORT_TYPE);1978 eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);1979 alen = sizeof(eiter->a.port_type);1980 alen += FDMI_ATTR_TYPELEN(eiter);1981 eiter->len = cpu_to_be16(alen);1982 size += alen;1983 ql_dbg(ql_dbg_disc, vha, 0x20c9,1984 "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type));1985 1986 /* Supported Class of Service */1987 eiter = entries + size;1988 eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);1989 eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);1990 alen = sizeof(eiter->a.port_supported_cos);1991 alen += FDMI_ATTR_TYPELEN(eiter);1992 eiter->len = cpu_to_be16(alen);1993 size += alen;1994 ql_dbg(ql_dbg_disc, vha, 0x20ca,1995 "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos));1996 1997 /* Port Fabric Name */1998 eiter = entries + size;1999 eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);2000 memcpy(eiter->a.fabric_name, vha->fabric_node_name,2001 sizeof(eiter->a.fabric_name));2002 alen = sizeof(eiter->a.fabric_name);2003 alen += FDMI_ATTR_TYPELEN(eiter);2004 eiter->len = cpu_to_be16(alen);2005 size += alen;2006 ql_dbg(ql_dbg_disc, vha, 0x20cb,2007 "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));2008 2009 /* FC4_type */2010 eiter = entries + size;2011 eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);2012 eiter->a.port_fc4_type[0] = 0x00;2013 eiter->a.port_fc4_type[1] = 0x00;2014 eiter->a.port_fc4_type[2] = 0x01;2015 eiter->a.port_fc4_type[3] = 0x00;2016 alen = sizeof(eiter->a.port_fc4_type);2017 alen += FDMI_ATTR_TYPELEN(eiter);2018 eiter->len = cpu_to_be16(alen);2019 size += alen;2020 ql_dbg(ql_dbg_disc, vha, 0x20cc,2021 "PORT ACTIVE FC4 TYPE = %016llx.\n",2022 *(uint64_t *)eiter->a.port_fc4_type);2023 2024 /* Port State */2025 eiter = entries + size;2026 eiter->type = cpu_to_be16(FDMI_PORT_STATE);2027 eiter->a.port_state = cpu_to_be32(2);2028 alen = sizeof(eiter->a.port_state);2029 alen += FDMI_ATTR_TYPELEN(eiter);2030 eiter->len = cpu_to_be16(alen);2031 size += alen;2032 ql_dbg(ql_dbg_disc, vha, 0x20cd,2033 "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state));2034 2035 /* Number of Ports */2036 eiter = entries + size;2037 eiter->type = cpu_to_be16(FDMI_PORT_COUNT);2038 eiter->a.num_ports = cpu_to_be32(1);2039 alen = sizeof(eiter->a.num_ports);2040 alen += FDMI_ATTR_TYPELEN(eiter);2041 eiter->len = cpu_to_be16(alen);2042 size += alen;2043 ql_dbg(ql_dbg_disc, vha, 0x20ce,2044 "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));2045 2046 /* Port Identifier */2047 eiter = entries + size;2048 eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER);2049 eiter->a.port_id = cpu_to_be32(vha->d_id.b24);2050 alen = sizeof(eiter->a.port_id);2051 alen += FDMI_ATTR_TYPELEN(eiter);2052 eiter->len = cpu_to_be16(alen);2053 size += alen;2054 ql_dbg(ql_dbg_disc, vha, 0x20cf,2055 "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id));2056 2057 if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan)2058 goto done;2059 2060 /* Smart SAN Service Category (Populate Smart SAN Initiator)*/2061 eiter = entries + size;2062 eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE);2063 alen = scnprintf(2064 eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service),2065 "%s", "Smart SAN Initiator");2066 alen += FDMI_ATTR_ALIGNMENT(alen);2067 alen += FDMI_ATTR_TYPELEN(eiter);2068 eiter->len = cpu_to_be16(alen);2069 size += alen;2070 ql_dbg(ql_dbg_disc, vha, 0x20d0,2071 "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service);2072 2073 /* Smart SAN GUID (NWWN+PWWN) */2074 eiter = entries + size;2075 eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID);2076 memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE);2077 memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE);2078 alen = sizeof(eiter->a.smartsan_guid);2079 alen += FDMI_ATTR_TYPELEN(eiter);2080 eiter->len = cpu_to_be16(alen);2081 size += alen;2082 ql_dbg(ql_dbg_disc, vha, 0x20d1,2083 "Smart SAN GUID = %016llx-%016llx\n",2084 wwn_to_u64(eiter->a.smartsan_guid),2085 wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE));2086 2087 /* Smart SAN Version (populate "Smart SAN Version 1.0") */2088 eiter = entries + size;2089 eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION);2090 alen = scnprintf(2091 eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version),2092 "%s", "Smart SAN Version 2.0");2093 alen += FDMI_ATTR_ALIGNMENT(alen);2094 alen += FDMI_ATTR_TYPELEN(eiter);2095 eiter->len = cpu_to_be16(alen);2096 size += alen;2097 ql_dbg(ql_dbg_disc, vha, 0x20d2,2098 "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version);2099 2100 /* Smart SAN Product Name (Specify Adapter Model No) */2101 eiter = entries + size;2102 eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME);2103 alen = scnprintf(eiter->a.smartsan_prod_name,2104 sizeof(eiter->a.smartsan_prod_name),2105 "ISP%04x", ha->pdev->device);2106 alen += FDMI_ATTR_ALIGNMENT(alen);2107 alen += FDMI_ATTR_TYPELEN(eiter);2108 eiter->len = cpu_to_be16(alen);2109 size += alen;2110 ql_dbg(ql_dbg_disc, vha, 0x20d3,2111 "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name);2112 2113 /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */2114 eiter = entries + size;2115 eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO);2116 eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1);2117 alen = sizeof(eiter->a.smartsan_port_info);2118 alen += FDMI_ATTR_TYPELEN(eiter);2119 eiter->len = cpu_to_be16(alen);2120 size += alen;2121 ql_dbg(ql_dbg_disc, vha, 0x20d4,2122 "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info);2123 2124 /* Smart SAN Security Support */2125 eiter = entries + size;2126 eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT);2127 eiter->a.smartsan_security_support = cpu_to_be32(1);2128 alen = sizeof(eiter->a.smartsan_security_support);2129 alen += FDMI_ATTR_TYPELEN(eiter);2130 eiter->len = cpu_to_be16(alen);2131 size += alen;2132 ql_dbg(ql_dbg_disc, vha, 0x20d6,2133 "SMARTSAN SECURITY SUPPORT = %d\n",2134 be32_to_cpu(eiter->a.smartsan_security_support));2135 2136done:2137 return size;2138}2139 2140/**2141 * qla2x00_fdmi_rhba() - perform RHBA FDMI registration2142 * @vha: HA context2143 * @callopt: Option to issue FDMI registration2144 *2145 * Returns 0 on success.2146 */2147static int2148qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt)2149{2150 struct qla_hw_data *ha = vha->hw;2151 unsigned long size = 0;2152 unsigned int rval, count;2153 ms_iocb_entry_t *ms_pkt;2154 struct ct_sns_req *ct_req;2155 struct ct_sns_rsp *ct_rsp;2156 void *entries;2157 2158 count = callopt != CALLOPT_FDMI1 ?2159 FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT;2160 2161 size = RHBA_RSP_SIZE;2162 2163 ql_dbg(ql_dbg_disc, vha, 0x20e0,2164 "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size);2165 2166 /* Request size adjusted after CT preparation */2167 ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);2168 2169 /* Prepare CT request */2170 ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size);2171 ct_rsp = &ha->ct_sns->p.rsp;2172 2173 /* Prepare FDMI command entries */2174 memcpy(ct_req->req.rhba.hba_identifier, vha->port_name,2175 sizeof(ct_req->req.rhba.hba_identifier));2176 size += sizeof(ct_req->req.rhba.hba_identifier);2177 2178 ct_req->req.rhba.entry_count = cpu_to_be32(1);2179 size += sizeof(ct_req->req.rhba.entry_count);2180 2181 memcpy(ct_req->req.rhba.port_name, vha->port_name,2182 sizeof(ct_req->req.rhba.port_name));2183 size += sizeof(ct_req->req.rhba.port_name);2184 2185 /* Attribute count */2186 ct_req->req.rhba.attrs.count = cpu_to_be32(count);2187 size += sizeof(ct_req->req.rhba.attrs.count);2188 2189 /* Attribute block */2190 entries = &ct_req->req.rhba.attrs.entry;2191 2192 size += qla2x00_hba_attributes(vha, entries, callopt);2193 2194 /* Update MS request size. */2195 qla2x00_update_ms_fdmi_iocb(vha, size + 16);2196 2197 ql_dbg(ql_dbg_disc, vha, 0x20e1,2198 "RHBA %016llx %016llx.\n",2199 wwn_to_u64(ct_req->req.rhba.hba_identifier),2200 wwn_to_u64(ct_req->req.rhba.port_name));2201 2202 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2,2203 entries, size);2204 2205 /* Execute MS IOCB */2206 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2207 sizeof(*ha->ms_iocb));2208 if (rval) {2209 ql_dbg(ql_dbg_disc, vha, 0x20e3,2210 "RHBA iocb failed (%d).\n", rval);2211 return rval;2212 }2213 2214 rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA");2215 if (rval) {2216 if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&2217 ct_rsp->header.explanation_code ==2218 CT_EXPL_ALREADY_REGISTERED) {2219 ql_dbg(ql_dbg_disc, vha, 0x20e4,2220 "RHBA already registered.\n");2221 return QLA_ALREADY_REGISTERED;2222 }2223 2224 ql_dbg(ql_dbg_disc, vha, 0x20e5,2225 "RHBA failed, CT Reason %#x, CT Explanation %#x\n",2226 ct_rsp->header.reason_code,2227 ct_rsp->header.explanation_code);2228 return rval;2229 }2230 2231 ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n");2232 return rval;2233}2234 2235 2236static int2237qla2x00_fdmi_dhba(scsi_qla_host_t *vha)2238{2239 int rval;2240 struct qla_hw_data *ha = vha->hw;2241 ms_iocb_entry_t *ms_pkt;2242 struct ct_sns_req *ct_req;2243 struct ct_sns_rsp *ct_rsp;2244 /* Issue RPA */2245 /* Prepare common MS IOCB */2246 ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,2247 DHBA_RSP_SIZE);2248 /* Prepare CT request */2249 ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);2250 ct_rsp = &ha->ct_sns->p.rsp;2251 /* Prepare FDMI command arguments -- portname. */2252 memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);2253 ql_dbg(ql_dbg_disc, vha, 0x2036,2254 "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);2255 /* Execute MS IOCB */2256 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2257 sizeof(ms_iocb_entry_t));2258 if (rval != QLA_SUCCESS) {2259 /*EMPTY*/2260 ql_dbg(ql_dbg_disc, vha, 0x2037,2261 "DHBA issue IOCB failed (%d).\n", rval);2262 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=2263 QLA_SUCCESS) {2264 rval = QLA_FUNCTION_FAILED;2265 } else {2266 ql_dbg(ql_dbg_disc, vha, 0x2038,2267 "DHBA exiting normally.\n");2268 }2269 return rval;2270}2271 2272/**2273 * qla2x00_fdmi_rprt() - perform RPRT registration2274 * @vha: HA context2275 * @callopt: Option to issue extended or standard FDMI2276 * command parameter2277 *2278 * Returns 0 on success.2279 */2280static int2281qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt)2282{2283 struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);2284 struct qla_hw_data *ha = vha->hw;2285 ulong size = 0;2286 uint rval, count;2287 ms_iocb_entry_t *ms_pkt;2288 struct ct_sns_req *ct_req;2289 struct ct_sns_rsp *ct_rsp;2290 void *entries;2291 count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?2292 FDMI2_SMARTSAN_PORT_ATTR_COUNT :2293 callopt != CALLOPT_FDMI1 ?2294 FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;2295 2296 size = RPRT_RSP_SIZE;2297 ql_dbg(ql_dbg_disc, vha, 0x20e8,2298 "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size);2299 /* Request size adjusted after CT preparation */2300 ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);2301 /* Prepare CT request */2302 ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size);2303 ct_rsp = &ha->ct_sns->p.rsp;2304 /* Prepare FDMI command entries */2305 memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name,2306 sizeof(ct_req->req.rprt.hba_identifier));2307 size += sizeof(ct_req->req.rprt.hba_identifier);2308 memcpy(ct_req->req.rprt.port_name, vha->port_name,2309 sizeof(ct_req->req.rprt.port_name));2310 size += sizeof(ct_req->req.rprt.port_name);2311 /* Attribute count */2312 ct_req->req.rprt.attrs.count = cpu_to_be32(count);2313 size += sizeof(ct_req->req.rprt.attrs.count);2314 /* Attribute block */2315 entries = ct_req->req.rprt.attrs.entry;2316 size += qla2x00_port_attributes(vha, entries, callopt);2317 /* Update MS request size. */2318 qla2x00_update_ms_fdmi_iocb(vha, size + 16);2319 ql_dbg(ql_dbg_disc, vha, 0x20e9,2320 "RPRT %016llx %016llx.\n",2321 wwn_to_u64(ct_req->req.rprt.port_name),2322 wwn_to_u64(ct_req->req.rprt.port_name));2323 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea,2324 entries, size);2325 /* Execute MS IOCB */2326 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2327 sizeof(*ha->ms_iocb));2328 if (rval) {2329 ql_dbg(ql_dbg_disc, vha, 0x20eb,2330 "RPRT iocb failed (%d).\n", rval);2331 return rval;2332 }2333 rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT");2334 if (rval) {2335 if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&2336 ct_rsp->header.explanation_code ==2337 CT_EXPL_ALREADY_REGISTERED) {2338 ql_dbg(ql_dbg_disc, vha, 0x20ec,2339 "RPRT already registered.\n");2340 return QLA_ALREADY_REGISTERED;2341 }2342 2343 ql_dbg(ql_dbg_disc, vha, 0x20ed,2344 "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n",2345 ct_rsp->header.reason_code,2346 ct_rsp->header.explanation_code);2347 return rval;2348 }2349 ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n");2350 return rval;2351}2352 2353/**2354 * qla2x00_fdmi_rpa() - perform RPA registration2355 * @vha: HA context2356 * @callopt: Option to issue FDMI registration2357 *2358 * Returns 0 on success.2359 */2360static int2361qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt)2362{2363 struct qla_hw_data *ha = vha->hw;2364 ulong size = 0;2365 uint rval, count;2366 ms_iocb_entry_t *ms_pkt;2367 struct ct_sns_req *ct_req;2368 struct ct_sns_rsp *ct_rsp;2369 void *entries;2370 2371 count =2372 callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?2373 FDMI2_SMARTSAN_PORT_ATTR_COUNT :2374 callopt != CALLOPT_FDMI1 ?2375 FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;2376 2377 size =2378 callopt != CALLOPT_FDMI1 ?2379 SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE;2380 2381 ql_dbg(ql_dbg_disc, vha, 0x20f0,2382 "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size);2383 2384 /* Request size adjusted after CT preparation */2385 ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);2386 2387 /* Prepare CT request */2388 ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size);2389 ct_rsp = &ha->ct_sns->p.rsp;2390 2391 /* Prepare FDMI command entries. */2392 memcpy(ct_req->req.rpa.port_name, vha->port_name,2393 sizeof(ct_req->req.rpa.port_name));2394 size += sizeof(ct_req->req.rpa.port_name);2395 2396 /* Attribute count */2397 ct_req->req.rpa.attrs.count = cpu_to_be32(count);2398 size += sizeof(ct_req->req.rpa.attrs.count);2399 2400 /* Attribute block */2401 entries = ct_req->req.rpa.attrs.entry;2402 2403 size += qla2x00_port_attributes(vha, entries, callopt);2404 2405 /* Update MS request size. */2406 qla2x00_update_ms_fdmi_iocb(vha, size + 16);2407 2408 ql_dbg(ql_dbg_disc, vha, 0x20f1,2409 "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name));2410 2411 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2,2412 entries, size);2413 2414 /* Execute MS IOCB */2415 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2416 sizeof(*ha->ms_iocb));2417 if (rval) {2418 ql_dbg(ql_dbg_disc, vha, 0x20f3,2419 "RPA iocb failed (%d).\n", rval);2420 return rval;2421 }2422 2423 rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA");2424 if (rval) {2425 if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&2426 ct_rsp->header.explanation_code ==2427 CT_EXPL_ALREADY_REGISTERED) {2428 ql_dbg(ql_dbg_disc, vha, 0x20f4,2429 "RPA already registered.\n");2430 return QLA_ALREADY_REGISTERED;2431 }2432 2433 ql_dbg(ql_dbg_disc, vha, 0x20f5,2434 "RPA failed, CT Reason code: %#x, CT Explanation %#x\n",2435 ct_rsp->header.reason_code,2436 ct_rsp->header.explanation_code);2437 return rval;2438 }2439 2440 ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n");2441 return rval;2442}2443 2444/**2445 * qla2x00_fdmi_register() -2446 * @vha: HA context2447 *2448 * Returns 0 on success.2449 */2450int2451qla2x00_fdmi_register(scsi_qla_host_t *vha)2452{2453 int rval = QLA_SUCCESS;2454 struct qla_hw_data *ha = vha->hw;2455 2456 if (IS_QLA2100(ha) || IS_QLA2200(ha) ||2457 IS_QLAFX00(ha))2458 return rval;2459 2460 rval = qla2x00_mgmt_svr_login(vha);2461 if (rval)2462 return rval;2463 2464 /* For npiv/vport send rprt only */2465 if (vha->vp_idx) {2466 if (ql2xsmartsan)2467 rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN);2468 if (rval || !ql2xsmartsan)2469 rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2);2470 if (rval)2471 rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1);2472 2473 return rval;2474 }2475 2476 /* Try fdmi2 first, if fails then try fdmi1 */2477 rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);2478 if (rval) {2479 if (rval != QLA_ALREADY_REGISTERED)2480 goto try_fdmi;2481 2482 rval = qla2x00_fdmi_dhba(vha);2483 if (rval)2484 goto try_fdmi;2485 2486 rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);2487 if (rval)2488 goto try_fdmi;2489 }2490 2491 if (ql2xsmartsan)2492 rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN);2493 if (rval || !ql2xsmartsan)2494 rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2);2495 if (rval)2496 goto try_fdmi;2497 2498 return rval;2499 2500try_fdmi:2501 rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);2502 if (rval) {2503 if (rval != QLA_ALREADY_REGISTERED)2504 return rval;2505 2506 rval = qla2x00_fdmi_dhba(vha);2507 if (rval)2508 return rval;2509 2510 rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);2511 if (rval)2512 return rval;2513 }2514 2515 rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1);2516 2517 return rval;2518}2519 2520/**2521 * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.2522 * @vha: HA context2523 * @list: switch info entries to populate2524 *2525 * Returns 0 on success.2526 */2527int2528qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)2529{2530 int rval = QLA_SUCCESS;2531 uint16_t i;2532 struct qla_hw_data *ha = vha->hw;2533 ms_iocb_entry_t *ms_pkt;2534 struct ct_sns_req *ct_req;2535 struct ct_sns_rsp *ct_rsp;2536 struct ct_arg arg;2537 2538 if (!IS_IIDMA_CAPABLE(ha))2539 return QLA_FUNCTION_FAILED;2540 2541 arg.iocb = ha->ms_iocb;2542 arg.req_dma = ha->ct_sns_dma;2543 arg.rsp_dma = ha->ct_sns_dma;2544 arg.req_size = GFPN_ID_REQ_SIZE;2545 arg.rsp_size = GFPN_ID_RSP_SIZE;2546 arg.nport_handle = NPH_SNS;2547 2548 for (i = 0; i < ha->max_fibre_devices; i++) {2549 /* Issue GFPN_ID */2550 /* Prepare common MS IOCB */2551 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);2552 2553 /* Prepare CT request */2554 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,2555 GFPN_ID_RSP_SIZE);2556 ct_rsp = &ha->ct_sns->p.rsp;2557 2558 /* Prepare CT arguments -- port_id */2559 ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);2560 2561 /* Execute MS IOCB */2562 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2563 sizeof(ms_iocb_entry_t));2564 if (rval != QLA_SUCCESS) {2565 /*EMPTY*/2566 ql_dbg(ql_dbg_disc, vha, 0x2023,2567 "GFPN_ID issue IOCB failed (%d).\n", rval);2568 break;2569 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,2570 "GFPN_ID") != QLA_SUCCESS) {2571 rval = QLA_FUNCTION_FAILED;2572 break;2573 } else {2574 /* Save fabric portname */2575 memcpy(list[i].fabric_port_name,2576 ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);2577 }2578 2579 /* Last device exit. */2580 if (list[i].d_id.b.rsvd_1 != 0)2581 break;2582 }2583 2584 return (rval);2585}2586 2587 2588static inline struct ct_sns_req *2589qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,2590 uint16_t rsp_size)2591{2592 memset(p, 0, sizeof(struct ct_sns_pkt));2593 2594 p->p.req.header.revision = 0x01;2595 p->p.req.header.gs_type = 0xFA;2596 p->p.req.header.gs_subtype = 0x01;2597 p->p.req.command = cpu_to_be16(cmd);2598 p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);2599 2600 return &p->p.req;2601}2602 2603static uint16_t2604qla2x00_port_speed_capability(uint16_t speed)2605{2606 switch (speed) {2607 case BIT_15:2608 return PORT_SPEED_1GB;2609 case BIT_14:2610 return PORT_SPEED_2GB;2611 case BIT_13:2612 return PORT_SPEED_4GB;2613 case BIT_12:2614 return PORT_SPEED_10GB;2615 case BIT_11:2616 return PORT_SPEED_8GB;2617 case BIT_10:2618 return PORT_SPEED_16GB;2619 case BIT_8:2620 return PORT_SPEED_32GB;2621 case BIT_7:2622 return PORT_SPEED_64GB;2623 default:2624 return PORT_SPEED_UNKNOWN;2625 }2626}2627 2628/**2629 * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.2630 * @vha: HA context2631 * @list: switch info entries to populate2632 *2633 * Returns 0 on success.2634 */2635int2636qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)2637{2638 int rval;2639 uint16_t i;2640 struct qla_hw_data *ha = vha->hw;2641 ms_iocb_entry_t *ms_pkt;2642 struct ct_sns_req *ct_req;2643 struct ct_sns_rsp *ct_rsp;2644 struct ct_arg arg;2645 2646 if (!IS_IIDMA_CAPABLE(ha))2647 return QLA_FUNCTION_FAILED;2648 if (!ha->flags.gpsc_supported)2649 return QLA_FUNCTION_FAILED;2650 2651 rval = qla2x00_mgmt_svr_login(vha);2652 if (rval)2653 return rval;2654 2655 arg.iocb = ha->ms_iocb;2656 arg.req_dma = ha->ct_sns_dma;2657 arg.rsp_dma = ha->ct_sns_dma;2658 arg.req_size = GPSC_REQ_SIZE;2659 arg.rsp_size = GPSC_RSP_SIZE;2660 arg.nport_handle = vha->mgmt_svr_loop_id;2661 2662 for (i = 0; i < ha->max_fibre_devices; i++) {2663 /* Issue GFPN_ID */2664 /* Prepare common MS IOCB */2665 ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);2666 2667 /* Prepare CT request */2668 ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,2669 GPSC_RSP_SIZE);2670 ct_rsp = &ha->ct_sns->p.rsp;2671 2672 /* Prepare CT arguments -- port_name */2673 memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,2674 WWN_SIZE);2675 2676 /* Execute MS IOCB */2677 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2678 sizeof(ms_iocb_entry_t));2679 if (rval != QLA_SUCCESS) {2680 /*EMPTY*/2681 ql_dbg(ql_dbg_disc, vha, 0x2059,2682 "GPSC issue IOCB failed (%d).\n", rval);2683 } else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,2684 "GPSC")) != QLA_SUCCESS) {2685 /* FM command unsupported? */2686 if (rval == QLA_INVALID_COMMAND &&2687 (ct_rsp->header.reason_code ==2688 CT_REASON_INVALID_COMMAND_CODE ||2689 ct_rsp->header.reason_code ==2690 CT_REASON_COMMAND_UNSUPPORTED)) {2691 ql_dbg(ql_dbg_disc, vha, 0x205a,2692 "GPSC command unsupported, disabling "2693 "query.\n");2694 ha->flags.gpsc_supported = 0;2695 rval = QLA_FUNCTION_FAILED;2696 break;2697 }2698 rval = QLA_FUNCTION_FAILED;2699 } else {2700 list->fp_speed = qla2x00_port_speed_capability(2701 be16_to_cpu(ct_rsp->rsp.gpsc.speed));2702 ql_dbg(ql_dbg_disc, vha, 0x205b,2703 "GPSC ext entry - fpn "2704 "%8phN speeds=%04x speed=%04x.\n",2705 list[i].fabric_port_name,2706 be16_to_cpu(ct_rsp->rsp.gpsc.speeds),2707 be16_to_cpu(ct_rsp->rsp.gpsc.speed));2708 }2709 2710 /* Last device exit. */2711 if (list[i].d_id.b.rsvd_1 != 0)2712 break;2713 }2714 2715 return (rval);2716}2717 2718/**2719 * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.2720 *2721 * @vha: HA context2722 * @list: switch info entries to populate2723 *2724 */2725void2726qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)2727{2728 int rval;2729 uint16_t i;2730 2731 ms_iocb_entry_t *ms_pkt;2732 struct ct_sns_req *ct_req;2733 struct ct_sns_rsp *ct_rsp;2734 struct qla_hw_data *ha = vha->hw;2735 uint8_t fcp_scsi_features = 0, nvme_features = 0;2736 struct ct_arg arg;2737 2738 for (i = 0; i < ha->max_fibre_devices; i++) {2739 /* Set default FC4 Type as UNKNOWN so the default is to2740 * Process this port */2741 list[i].fc4_type = 0;2742 2743 /* Do not attempt GFF_ID if we are not FWI_2 capable */2744 if (!IS_FWI2_CAPABLE(ha))2745 continue;2746 2747 arg.iocb = ha->ms_iocb;2748 arg.req_dma = ha->ct_sns_dma;2749 arg.rsp_dma = ha->ct_sns_dma;2750 arg.req_size = GFF_ID_REQ_SIZE;2751 arg.rsp_size = GFF_ID_RSP_SIZE;2752 arg.nport_handle = NPH_SNS;2753 2754 /* Prepare common MS IOCB */2755 ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);2756 2757 /* Prepare CT request */2758 ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,2759 GFF_ID_RSP_SIZE);2760 ct_rsp = &ha->ct_sns->p.rsp;2761 2762 /* Prepare CT arguments -- port_id */2763 ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);2764 2765 /* Execute MS IOCB */2766 rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,2767 sizeof(ms_iocb_entry_t));2768 2769 if (rval != QLA_SUCCESS) {2770 ql_dbg(ql_dbg_disc, vha, 0x205c,2771 "GFF_ID issue IOCB failed (%d).\n", rval);2772 } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,2773 "GFF_ID") != QLA_SUCCESS) {2774 ql_dbg(ql_dbg_disc, vha, 0x205d,2775 "GFF_ID IOCB status had a failure status code.\n");2776 } else {2777 fcp_scsi_features =2778 ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];2779 fcp_scsi_features &= 0x0f;2780 2781 if (fcp_scsi_features) {2782 list[i].fc4_type = FS_FC4TYPE_FCP;2783 list[i].fc4_features = fcp_scsi_features;2784 }2785 2786 nvme_features =2787 ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];2788 nvme_features &= 0xf;2789 2790 if (nvme_features) {2791 list[i].fc4_type |= FS_FC4TYPE_NVME;2792 list[i].fc4_features = nvme_features;2793 }2794 }2795 2796 /* Last device exit. */2797 if (list[i].d_id.b.rsvd_1 != 0)2798 break;2799 }2800}2801 2802int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)2803{2804 struct qla_work_evt *e;2805 2806 e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);2807 if (!e)2808 return QLA_FUNCTION_FAILED;2809 2810 e->u.fcport.fcport = fcport;2811 return qla2x00_post_work(vha, e);2812}2813 2814void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)2815{2816 struct fc_port *fcport = ea->fcport;2817 2818 ql_dbg(ql_dbg_disc, vha, 0x20d8,2819 "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",2820 __func__, fcport->port_name, fcport->disc_state,2821 fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,2822 ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);2823 2824 if (fcport->disc_state == DSC_DELETE_PEND)2825 return;2826 2827 /* We will figure-out what happen after AUTH completes */2828 if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)2829 return;2830 2831 if (ea->sp->gen2 != fcport->login_gen) {2832 /* target side must have changed it. */2833 ql_dbg(ql_dbg_disc, vha, 0x20d3,2834 "%s %8phC generation changed\n",2835 __func__, fcport->port_name);2836 return;2837 } else if (ea->sp->gen1 != fcport->rscn_gen) {2838 return;2839 }2840 2841 qla_post_iidma_work(vha, fcport);2842}2843 2844static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)2845{2846 struct scsi_qla_host *vha = sp->vha;2847 struct qla_hw_data *ha = vha->hw;2848 fc_port_t *fcport = sp->fcport;2849 struct ct_sns_rsp *ct_rsp;2850 struct event_arg ea;2851 2852 ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;2853 2854 ql_dbg(ql_dbg_disc, vha, 0x2053,2855 "Async done-%s res %x, WWPN %8phC \n",2856 sp->name, res, fcport->port_name);2857 2858 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);2859 2860 if (res == QLA_FUNCTION_TIMEOUT)2861 goto done;2862 2863 if (res == (DID_ERROR << 16)) {2864 /* entry status error */2865 goto done;2866 } else if (res) {2867 if ((ct_rsp->header.reason_code ==2868 CT_REASON_INVALID_COMMAND_CODE) ||2869 (ct_rsp->header.reason_code ==2870 CT_REASON_COMMAND_UNSUPPORTED)) {2871 ql_dbg(ql_dbg_disc, vha, 0x2019,2872 "GPSC command unsupported, disabling query.\n");2873 ha->flags.gpsc_supported = 0;2874 goto done;2875 }2876 } else {2877 fcport->fp_speed = qla2x00_port_speed_capability(2878 be16_to_cpu(ct_rsp->rsp.gpsc.speed));2879 2880 ql_dbg(ql_dbg_disc, vha, 0x2054,2881 "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",2882 sp->name, fcport->fabric_port_name,2883 be16_to_cpu(ct_rsp->rsp.gpsc.speeds),2884 be16_to_cpu(ct_rsp->rsp.gpsc.speed));2885 }2886 memset(&ea, 0, sizeof(ea));2887 ea.rc = res;2888 ea.fcport = fcport;2889 ea.sp = sp;2890 qla24xx_handle_gpsc_event(vha, &ea);2891 2892done:2893 /* ref: INIT */2894 kref_put(&sp->cmd_kref, qla2x00_sp_release);2895}2896 2897int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)2898{2899 int rval = QLA_FUNCTION_FAILED;2900 struct ct_sns_req *ct_req;2901 srb_t *sp;2902 2903 if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))2904 return rval;2905 2906 /* ref: INIT */2907 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);2908 if (!sp)2909 goto done;2910 2911 sp->type = SRB_CT_PTHRU_CMD;2912 sp->name = "gpsc";2913 sp->gen1 = fcport->rscn_gen;2914 sp->gen2 = fcport->login_gen;2915 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,2916 qla24xx_async_gpsc_sp_done);2917 2918 /* CT_IU preamble */2919 ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,2920 GPSC_RSP_SIZE);2921 2922 /* GPSC req */2923 memcpy(ct_req->req.gpsc.port_name, fcport->fabric_port_name,2924 WWN_SIZE);2925 2926 sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;2927 sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;2928 sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;2929 sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;2930 sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;2931 sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;2932 sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;2933 2934 ql_dbg(ql_dbg_disc, vha, 0x205e,2935 "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",2936 sp->name, fcport->port_name, sp->handle,2937 fcport->loop_id, fcport->d_id.b.domain,2938 fcport->d_id.b.area, fcport->d_id.b.al_pa);2939 2940 rval = qla2x00_start_sp(sp);2941 if (rval != QLA_SUCCESS)2942 goto done_free_sp;2943 return rval;2944 2945done_free_sp:2946 /* ref: INIT */2947 kref_put(&sp->cmd_kref, qla2x00_sp_release);2948done:2949 return rval;2950}2951 2952void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)2953{2954 struct srb_iocb *c = &sp->u.iocb_cmd;2955 2956 switch (sp->type) {2957 case SRB_ELS_DCMD:2958 qla2x00_els_dcmd2_free(vha, &c->u.els_plogi);2959 break;2960 case SRB_CT_PTHRU_CMD:2961 default:2962 if (sp->u.iocb_cmd.u.ctarg.req) {2963 dma_free_coherent(&vha->hw->pdev->dev,2964 sp->u.iocb_cmd.u.ctarg.req_allocated_size,2965 sp->u.iocb_cmd.u.ctarg.req,2966 sp->u.iocb_cmd.u.ctarg.req_dma);2967 sp->u.iocb_cmd.u.ctarg.req = NULL;2968 }2969 2970 if (sp->u.iocb_cmd.u.ctarg.rsp) {2971 dma_free_coherent(&vha->hw->pdev->dev,2972 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,2973 sp->u.iocb_cmd.u.ctarg.rsp,2974 sp->u.iocb_cmd.u.ctarg.rsp_dma);2975 sp->u.iocb_cmd.u.ctarg.rsp = NULL;2976 }2977 break;2978 }2979 2980 /* ref: INIT */2981 kref_put(&sp->cmd_kref, qla2x00_sp_release);2982}2983 2984void qla24xx_async_gffid_sp_done(srb_t *sp, int res)2985{2986 struct scsi_qla_host *vha = sp->vha;2987 fc_port_t *fcport = sp->fcport;2988 struct ct_sns_rsp *ct_rsp;2989 uint8_t fc4_scsi_feat;2990 uint8_t fc4_nvme_feat;2991 2992 ql_dbg(ql_dbg_disc, vha, 0x2133,2993 "Async done-%s res %x ID %x. %8phC\n",2994 sp->name, res, fcport->d_id.b24, fcport->port_name);2995 2996 ct_rsp = sp->u.iocb_cmd.u.ctarg.rsp;2997 fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];2998 fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];2999 sp->rc = res;3000 3001 /*3002 * FC-GS-7, 5.2.3.12 FC-4 Features - format3003 * The format of the FC-4 Features object, as defined by the FC-4,3004 * Shall be an array of 4-bit values, one for each type code value3005 */3006 if (!res) {3007 if (fc4_scsi_feat & 0xf) {3008 /* w1 b00:03 */3009 fcport->fc4_type = FS_FC4TYPE_FCP;3010 fcport->fc4_features = fc4_scsi_feat & 0xf;3011 }3012 3013 if (fc4_nvme_feat & 0xf) {3014 /* w5 [00:03]/28h */3015 fcport->fc4_type |= FS_FC4TYPE_NVME;3016 fcport->fc4_features = fc4_nvme_feat & 0xf;3017 }3018 }3019 3020 if (sp->flags & SRB_WAKEUP_ON_COMP) {3021 complete(sp->comp);3022 } else {3023 if (sp->u.iocb_cmd.u.ctarg.req) {3024 dma_free_coherent(&vha->hw->pdev->dev,3025 sp->u.iocb_cmd.u.ctarg.req_allocated_size,3026 sp->u.iocb_cmd.u.ctarg.req,3027 sp->u.iocb_cmd.u.ctarg.req_dma);3028 sp->u.iocb_cmd.u.ctarg.req = NULL;3029 }3030 3031 if (sp->u.iocb_cmd.u.ctarg.rsp) {3032 dma_free_coherent(&vha->hw->pdev->dev,3033 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,3034 sp->u.iocb_cmd.u.ctarg.rsp,3035 sp->u.iocb_cmd.u.ctarg.rsp_dma);3036 sp->u.iocb_cmd.u.ctarg.rsp = NULL;3037 }3038 3039 /* ref: INIT */3040 kref_put(&sp->cmd_kref, qla2x00_sp_release);3041 /* we should not be here */3042 dump_stack();3043 }3044}3045 3046/* Get FC4 Feature with Nport ID. */3047int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool wait)3048{3049 int rval = QLA_FUNCTION_FAILED;3050 struct ct_sns_req *ct_req;3051 srb_t *sp;3052 DECLARE_COMPLETION_ONSTACK(comp);3053 3054 /* this routine does not have handling for no wait */3055 if (!vha->flags.online || !wait)3056 return rval;3057 3058 /* ref: INIT */3059 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);3060 if (!sp)3061 return rval;3062 3063 sp->type = SRB_CT_PTHRU_CMD;3064 sp->name = "gffid";3065 sp->gen1 = fcport->rscn_gen;3066 sp->gen2 = fcport->login_gen;3067 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,3068 qla24xx_async_gffid_sp_done);3069 sp->comp = ∁3070 sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout;3071 3072 if (wait)3073 sp->flags = SRB_WAKEUP_ON_COMP;3074 3075 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);3076 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,3077 sp->u.iocb_cmd.u.ctarg.req_allocated_size,3078 &sp->u.iocb_cmd.u.ctarg.req_dma,3079 GFP_KERNEL);3080 if (!sp->u.iocb_cmd.u.ctarg.req) {3081 ql_log(ql_log_warn, vha, 0xd041,3082 "%s: Failed to allocate ct_sns request.\n",3083 __func__);3084 goto done_free_sp;3085 }3086 3087 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);3088 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,3089 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,3090 &sp->u.iocb_cmd.u.ctarg.rsp_dma,3091 GFP_KERNEL);3092 if (!sp->u.iocb_cmd.u.ctarg.rsp) {3093 ql_log(ql_log_warn, vha, 0xd041,3094 "%s: Failed to allocate ct_sns response.\n",3095 __func__);3096 goto done_free_sp;3097 }3098 3099 /* CT_IU preamble */3100 ct_req = qla2x00_prep_ct_req(sp->u.iocb_cmd.u.ctarg.req, GFF_ID_CMD, GFF_ID_RSP_SIZE);3101 3102 ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;3103 ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;3104 ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;3105 3106 sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;3107 sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;3108 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;3109 3110 rval = qla2x00_start_sp(sp);3111 3112 if (rval != QLA_SUCCESS) {3113 rval = QLA_FUNCTION_FAILED;3114 goto done_free_sp;3115 } else {3116 ql_dbg(ql_dbg_disc, vha, 0x3074,3117 "Async-%s hdl=%x portid %06x\n",3118 sp->name, sp->handle, fcport->d_id.b24);3119 }3120 3121 wait_for_completion(sp->comp);3122 rval = sp->rc;3123 3124done_free_sp:3125 if (sp->u.iocb_cmd.u.ctarg.req) {3126 dma_free_coherent(&vha->hw->pdev->dev,3127 sp->u.iocb_cmd.u.ctarg.req_allocated_size,3128 sp->u.iocb_cmd.u.ctarg.req,3129 sp->u.iocb_cmd.u.ctarg.req_dma);3130 sp->u.iocb_cmd.u.ctarg.req = NULL;3131 }3132 3133 if (sp->u.iocb_cmd.u.ctarg.rsp) {3134 dma_free_coherent(&vha->hw->pdev->dev,3135 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,3136 sp->u.iocb_cmd.u.ctarg.rsp,3137 sp->u.iocb_cmd.u.ctarg.rsp_dma);3138 sp->u.iocb_cmd.u.ctarg.rsp = NULL;3139 }3140 3141 /* ref: INIT */3142 kref_put(&sp->cmd_kref, qla2x00_sp_release);3143 return rval;3144}3145 3146/* GPN_FT + GNN_FT*/3147static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)3148{3149 struct qla_hw_data *ha = vha->hw;3150 scsi_qla_host_t *vp;3151 unsigned long flags;3152 u64 twwn;3153 int rc = 0;3154 3155 if (!ha->num_vhosts)3156 return 0;3157 3158 spin_lock_irqsave(&ha->vport_slock, flags);3159 list_for_each_entry(vp, &ha->vp_list, list) {3160 twwn = wwn_to_u64(vp->port_name);3161 if (wwn == twwn) {3162 rc = 1;3163 break;3164 }3165 }3166 spin_unlock_irqrestore(&ha->vport_slock, flags);3167 3168 return rc;3169}3170 3171static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, fc_port_t *fcport)3172{3173 u32 rscn_gen;3174 3175 rscn_gen = atomic_read(&vha->rscn_gen);3176 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2017,3177 "%s %d %8phC rscn_gen %x start %x end %x current %x\n",3178 __func__, __LINE__, fcport->port_name, fcport->rscn_gen,3179 vha->scan.rscn_gen_start, vha->scan.rscn_gen_end, rscn_gen);3180 3181 if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_start,3182 vha->scan.rscn_gen_end))3183 /* rscn came in before fabric scan */3184 return true;3185 3186 if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_end, rscn_gen))3187 /* rscn came in after fabric scan */3188 return false;3189 3190 /* rare: fcport's scan_needed + rscn_gen must be stale */3191 return true;3192}3193 3194void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp)3195{3196 fc_port_t *fcport;3197 u32 i, rc;3198 bool found;3199 struct fab_scan_rp *rp, *trp;3200 unsigned long flags;3201 u8 recheck = 0;3202 u16 dup = 0, dup_cnt = 0;3203 3204 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,3205 "%s enter\n", __func__);3206 3207 if (sp->gen1 != vha->hw->base_qpair->chip_reset) {3208 ql_dbg(ql_dbg_disc, vha, 0xffff,3209 "%s scan stop due to chip reset %x/%x\n",3210 sp->name, sp->gen1, vha->hw->base_qpair->chip_reset);3211 goto out;3212 }3213 3214 rc = sp->rc;3215 if (rc) {3216 vha->scan.scan_retry++;3217 if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {3218 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3219 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3220 goto out;3221 } else {3222 ql_dbg(ql_dbg_disc, vha, 0xffff,3223 "%s: Fabric scan failed for %d retries.\n",3224 __func__, vha->scan.scan_retry);3225 /*3226 * Unable to scan any rports. logout loop below3227 * will unregister all sessions.3228 */3229 list_for_each_entry(fcport, &vha->vp_fcports, list) {3230 if ((fcport->flags & FCF_FABRIC_DEVICE) != 0) {3231 fcport->scan_state = QLA_FCPORT_SCAN;3232 if (fcport->loop_id == FC_NO_LOOP_ID)3233 fcport->logout_on_delete = 0;3234 else3235 fcport->logout_on_delete = 1;3236 }3237 }3238 goto login_logout;3239 }3240 }3241 vha->scan.scan_retry = 0;3242 3243 list_for_each_entry(fcport, &vha->vp_fcports, list)3244 fcport->scan_state = QLA_FCPORT_SCAN;3245 3246 for (i = 0; i < vha->hw->max_fibre_devices; i++) {3247 u64 wwn;3248 int k;3249 3250 rp = &vha->scan.l[i];3251 found = false;3252 3253 wwn = wwn_to_u64(rp->port_name);3254 if (wwn == 0)3255 continue;3256 3257 /* Remove duplicate NPORT ID entries from switch data base */3258 for (k = i + 1; k < vha->hw->max_fibre_devices; k++) {3259 trp = &vha->scan.l[k];3260 if (rp->id.b24 == trp->id.b24) {3261 dup = 1;3262 dup_cnt++;3263 ql_dbg(ql_dbg_disc + ql_dbg_verbose,3264 vha, 0xffff,3265 "Detected duplicate NPORT ID from switch data base: ID %06x WWN %8phN WWN %8phN\n",3266 rp->id.b24, rp->port_name, trp->port_name);3267 memset(trp, 0, sizeof(*trp));3268 }3269 }3270 3271 if (!memcmp(rp->port_name, vha->port_name, WWN_SIZE))3272 continue;3273 3274 /* Bypass reserved domain fields. */3275 if ((rp->id.b.domain & 0xf0) == 0xf0)3276 continue;3277 3278 /* Bypass virtual ports of the same host. */3279 if (qla2x00_is_a_vp(vha, wwn))3280 continue;3281 3282 list_for_each_entry(fcport, &vha->vp_fcports, list) {3283 if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))3284 continue;3285 fcport->scan_state = QLA_FCPORT_FOUND;3286 fcport->last_rscn_gen = fcport->rscn_gen;3287 fcport->fc4_type = rp->fc4type;3288 found = true;3289 3290 if (fcport->scan_needed) {3291 if (NVME_PRIORITY(vha->hw, fcport))3292 fcport->do_prli_nvme = 1;3293 else3294 fcport->do_prli_nvme = 0;3295 }3296 3297 /*3298 * If device was not a fabric device before.3299 */3300 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {3301 qla2x00_clear_loop_id(fcport);3302 fcport->flags |= FCF_FABRIC_DEVICE;3303 } else if (fcport->d_id.b24 != rp->id.b24 ||3304 (fcport->scan_needed &&3305 fcport->port_type != FCT_INITIATOR &&3306 fcport->port_type != FCT_NVME_INITIATOR)) {3307 fcport->scan_needed = 0;3308 qlt_schedule_sess_for_deletion(fcport);3309 }3310 fcport->d_id.b24 = rp->id.b24;3311 break;3312 }3313 3314 if (!found) {3315 ql_dbg(ql_dbg_disc, vha, 0xffff,3316 "%s %d %8phC post new sess\n",3317 __func__, __LINE__, rp->port_name);3318 qla24xx_post_newsess_work(vha, &rp->id, rp->port_name,3319 rp->node_name, NULL, rp->fc4type);3320 }3321 }3322 3323 if (dup) {3324 ql_log(ql_log_warn, vha, 0xffff,3325 "Detected %d duplicate NPORT ID(s) from switch data base\n",3326 dup_cnt);3327 }3328 3329login_logout:3330 /*3331 * Logout all previous fabric dev marked lost, except FCP2 devices.3332 */3333 list_for_each_entry(fcport, &vha->vp_fcports, list) {3334 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {3335 fcport->scan_needed = 0;3336 continue;3337 }3338 3339 if (fcport->scan_state != QLA_FCPORT_FOUND) {3340 bool do_delete = false;3341 3342 if (fcport->scan_needed &&3343 fcport->disc_state == DSC_LOGIN_PEND) {3344 /* Cable got disconnected after we sent3345 * a login. Do delete to prevent timeout.3346 */3347 fcport->logout_on_delete = 1;3348 do_delete = true;3349 }3350 3351 if (qla_ok_to_clear_rscn(vha, fcport))3352 fcport->scan_needed = 0;3353 3354 if (((qla_dual_mode_enabled(vha) ||3355 qla_ini_mode_enabled(vha)) &&3356 atomic_read(&fcport->state) == FCS_ONLINE) ||3357 do_delete) {3358 if (fcport->loop_id != FC_NO_LOOP_ID) {3359 if (fcport->flags & FCF_FCP2_DEVICE)3360 continue;3361 3362 ql_log(ql_log_warn, vha, 0x20f0,3363 "%s %d %8phC post del sess\n",3364 __func__, __LINE__,3365 fcport->port_name);3366 3367 fcport->tgt_link_down_time = 0;3368 qlt_schedule_sess_for_deletion(fcport);3369 continue;3370 }3371 }3372 } else {3373 if (fcport->scan_needed ||3374 fcport->disc_state != DSC_LOGIN_COMPLETE) {3375 if (fcport->login_retry == 0) {3376 fcport->login_retry =3377 vha->hw->login_retry_count;3378 ql_dbg(ql_dbg_disc, vha, 0x20a3,3379 "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",3380 fcport->port_name, fcport->loop_id,3381 fcport->login_retry);3382 }3383 3384 if (qla_ok_to_clear_rscn(vha, fcport))3385 fcport->scan_needed = 0;3386 qla24xx_fcport_handle_login(vha, fcport);3387 }3388 }3389 }3390 3391 recheck = 1;3392out:3393 qla24xx_sp_unmap(vha, sp);3394 spin_lock_irqsave(&vha->work_lock, flags);3395 vha->scan.scan_flags &= ~SF_SCANNING;3396 spin_unlock_irqrestore(&vha->work_lock, flags);3397 3398 if (recheck) {3399 list_for_each_entry(fcport, &vha->vp_fcports, list) {3400 if (fcport->scan_needed) {3401 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3402 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3403 break;3404 }3405 }3406 }3407}3408 3409static int qla2x00_post_next_scan_work(struct scsi_qla_host *vha,3410 srb_t *sp, int cmd)3411{3412 struct qla_work_evt *e;3413 3414 e = qla2x00_alloc_work(vha, cmd);3415 if (!e)3416 return QLA_FUNCTION_FAILED;3417 3418 e->u.iosb.sp = sp;3419 3420 return qla2x00_post_work(vha, e);3421}3422 3423static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,3424 struct srb *sp)3425{3426 struct qla_hw_data *ha = vha->hw;3427 int num_fibre_dev = ha->max_fibre_devices;3428 struct ct_sns_gpnft_rsp *ct_rsp =3429 (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;3430 struct ct_sns_gpn_ft_data *d;3431 struct fab_scan_rp *rp;3432 int i, j, k;3433 port_id_t id;3434 u8 found;3435 u64 wwn;3436 3437 j = 0;3438 for (i = 0; i < num_fibre_dev; i++) {3439 d = &ct_rsp->entries[i];3440 3441 id.b.rsvd_1 = 0;3442 id.b.domain = d->port_id[0];3443 id.b.area = d->port_id[1];3444 id.b.al_pa = d->port_id[2];3445 wwn = wwn_to_u64(d->port_name);3446 3447 if (id.b24 == 0 || wwn == 0)3448 continue;3449 3450 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2025,3451 "%s %06x %8ph \n",3452 __func__, id.b24, d->port_name);3453 3454 switch (vha->scan.step) {3455 case FAB_SCAN_GPNFT_FCP:3456 rp = &vha->scan.l[j];3457 rp->id = id;3458 memcpy(rp->port_name, d->port_name, 8);3459 j++;3460 rp->fc4type = FS_FC4TYPE_FCP;3461 break;3462 case FAB_SCAN_GNNFT_FCP:3463 for (k = 0; k < num_fibre_dev; k++) {3464 rp = &vha->scan.l[k];3465 if (id.b24 == rp->id.b24) {3466 memcpy(rp->node_name,3467 d->port_name, 8);3468 break;3469 }3470 }3471 break;3472 case FAB_SCAN_GPNFT_NVME:3473 found = 0;3474 3475 for (k = 0; k < num_fibre_dev; k++) {3476 rp = &vha->scan.l[k];3477 if (!memcmp(rp->port_name, d->port_name, 8)) {3478 /*3479 * Supports FC-NVMe & FCP3480 */3481 rp->fc4type |= FS_FC4TYPE_NVME;3482 found = 1;3483 break;3484 }3485 }3486 3487 /* We found new FC-NVMe only port */3488 if (!found) {3489 for (k = 0; k < num_fibre_dev; k++) {3490 rp = &vha->scan.l[k];3491 if (wwn_to_u64(rp->port_name)) {3492 continue;3493 } else {3494 rp->id = id;3495 memcpy(rp->port_name, d->port_name, 8);3496 rp->fc4type = FS_FC4TYPE_NVME;3497 break;3498 }3499 }3500 }3501 break;3502 case FAB_SCAN_GNNFT_NVME:3503 for (k = 0; k < num_fibre_dev; k++) {3504 rp = &vha->scan.l[k];3505 if (id.b24 == rp->id.b24) {3506 memcpy(rp->node_name, d->port_name, 8);3507 break;3508 }3509 }3510 break;3511 default:3512 break;3513 }3514 }3515}3516 3517static void qla_async_scan_sp_done(srb_t *sp, int res)3518{3519 struct scsi_qla_host *vha = sp->vha;3520 unsigned long flags;3521 int rc;3522 3523 /* gen2 field is holding the fc4type */3524 ql_dbg(ql_dbg_disc, vha, 0x2026,3525 "Async done-%s res %x step %x\n",3526 sp->name, res, vha->scan.step);3527 3528 sp->rc = res;3529 if (res) {3530 unsigned long flags;3531 const char *name = sp->name;3532 3533 if (res == QLA_OS_TIMER_EXPIRED) {3534 /* switch is ignoring all commands.3535 * This might be a zone disable behavior.3536 * This means we hit 64s timeout.3537 * 22s GPNFT + 44s Abort = 64s3538 */3539 ql_dbg(ql_dbg_disc, vha, 0xffff,3540 "%s: Switch Zone check please .\n",3541 name);3542 qla2x00_mark_all_devices_lost(vha);3543 }3544 3545 /*3546 * We are in an Interrupt context, queue up this3547 * sp for GNNFT_DONE work. This will allow all3548 * the resource to get freed up.3549 */3550 rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);3551 if (rc) {3552 /* Cleanup here to prevent memory leak */3553 qla24xx_sp_unmap(vha, sp);3554 3555 spin_lock_irqsave(&vha->work_lock, flags);3556 vha->scan.scan_flags &= ~SF_SCANNING;3557 vha->scan.scan_retry++;3558 spin_unlock_irqrestore(&vha->work_lock, flags);3559 3560 if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {3561 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3562 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3563 qla2xxx_wake_dpc(vha);3564 } else {3565 ql_dbg(ql_dbg_disc, vha, 0xffff,3566 "Async done-%s rescan failed on all retries.\n",3567 name);3568 }3569 }3570 return;3571 }3572 3573 qla2x00_find_free_fcp_nvme_slot(vha, sp);3574 3575 spin_lock_irqsave(&vha->work_lock, flags);3576 vha->scan.scan_flags &= ~SF_SCANNING;3577 spin_unlock_irqrestore(&vha->work_lock, flags);3578 3579 switch (vha->scan.step) {3580 case FAB_SCAN_GPNFT_FCP:3581 case FAB_SCAN_GPNFT_NVME:3582 rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);3583 break;3584 case FAB_SCAN_GNNFT_FCP:3585 if (vha->flags.nvme_enabled)3586 rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);3587 else3588 rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);3589 3590 break;3591 case FAB_SCAN_GNNFT_NVME:3592 rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);3593 break;3594 default:3595 /* should not be here */3596 WARN_ON(1);3597 rc = QLA_FUNCTION_FAILED;3598 break;3599 }3600 3601 if (rc) {3602 qla24xx_sp_unmap(vha, sp);3603 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3604 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3605 return;3606 }3607}3608 3609/* Get WWPN list for certain fc4_type */3610int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)3611{3612 int rval = QLA_FUNCTION_FAILED;3613 struct ct_sns_req *ct_req;3614 struct ct_sns_pkt *ct_sns;3615 u32 rspsz = 0;3616 unsigned long flags;3617 3618 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x200c,3619 "%s enter\n", __func__);3620 3621 if (!vha->flags.online)3622 return rval;3623 3624 spin_lock_irqsave(&vha->work_lock, flags);3625 if (vha->scan.scan_flags & SF_SCANNING) {3626 spin_unlock_irqrestore(&vha->work_lock, flags);3627 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,3628 "%s: scan active\n", __func__);3629 return rval;3630 }3631 vha->scan.scan_flags |= SF_SCANNING;3632 if (!sp)3633 vha->scan.step = FAB_SCAN_START;3634 3635 spin_unlock_irqrestore(&vha->work_lock, flags);3636 3637 switch (vha->scan.step) {3638 case FAB_SCAN_START:3639 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2018,3640 "%s: Performing FCP Scan\n", __func__);3641 3642 /* ref: INIT */3643 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);3644 if (!sp) {3645 spin_lock_irqsave(&vha->work_lock, flags);3646 vha->scan.scan_flags &= ~SF_SCANNING;3647 spin_unlock_irqrestore(&vha->work_lock, flags);3648 return rval;3649 }3650 3651 sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,3652 sizeof(struct ct_sns_pkt),3653 &sp->u.iocb_cmd.u.ctarg.req_dma,3654 GFP_KERNEL);3655 sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);3656 if (!sp->u.iocb_cmd.u.ctarg.req) {3657 ql_log(ql_log_warn, vha, 0x201a,3658 "Failed to allocate ct_sns request.\n");3659 spin_lock_irqsave(&vha->work_lock, flags);3660 vha->scan.scan_flags &= ~SF_SCANNING;3661 spin_unlock_irqrestore(&vha->work_lock, flags);3662 qla2x00_rel_sp(sp);3663 return rval;3664 }3665 3666 rspsz = sizeof(struct ct_sns_gpnft_rsp) +3667 vha->hw->max_fibre_devices *3668 sizeof(struct ct_sns_gpn_ft_data);3669 3670 sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,3671 rspsz,3672 &sp->u.iocb_cmd.u.ctarg.rsp_dma,3673 GFP_KERNEL);3674 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;3675 if (!sp->u.iocb_cmd.u.ctarg.rsp) {3676 ql_log(ql_log_warn, vha, 0x201b,3677 "Failed to allocate ct_sns request.\n");3678 spin_lock_irqsave(&vha->work_lock, flags);3679 vha->scan.scan_flags &= ~SF_SCANNING;3680 spin_unlock_irqrestore(&vha->work_lock, flags);3681 dma_free_coherent(&vha->hw->pdev->dev,3682 sp->u.iocb_cmd.u.ctarg.req_allocated_size,3683 sp->u.iocb_cmd.u.ctarg.req,3684 sp->u.iocb_cmd.u.ctarg.req_dma);3685 sp->u.iocb_cmd.u.ctarg.req = NULL;3686 /* ref: INIT */3687 qla2x00_rel_sp(sp);3688 return rval;3689 }3690 sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;3691 3692 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,3693 "%s scan list size %d\n", __func__, vha->scan.size);3694 3695 memset(vha->scan.l, 0, vha->scan.size);3696 3697 vha->scan.step = FAB_SCAN_GPNFT_FCP;3698 break;3699 case FAB_SCAN_GPNFT_FCP:3700 vha->scan.step = FAB_SCAN_GNNFT_FCP;3701 break;3702 case FAB_SCAN_GNNFT_FCP:3703 vha->scan.step = FAB_SCAN_GPNFT_NVME;3704 break;3705 case FAB_SCAN_GPNFT_NVME:3706 vha->scan.step = FAB_SCAN_GNNFT_NVME;3707 break;3708 case FAB_SCAN_GNNFT_NVME:3709 default:3710 /* should not be here */3711 WARN_ON(1);3712 goto done_free_sp;3713 }3714 3715 if (!sp) {3716 ql_dbg(ql_dbg_disc, vha, 0x201c,3717 "scan did not provide SP\n");3718 return rval;3719 }3720 if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {3721 ql_log(ql_log_warn, vha, 0x201d,3722 "%s: req %p rsp %p are not setup\n",3723 __func__, sp->u.iocb_cmd.u.ctarg.req,3724 sp->u.iocb_cmd.u.ctarg.rsp);3725 spin_lock_irqsave(&vha->work_lock, flags);3726 vha->scan.scan_flags &= ~SF_SCANNING;3727 spin_unlock_irqrestore(&vha->work_lock, flags);3728 WARN_ON(1);3729 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3730 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3731 goto done_free_sp;3732 }3733 3734 rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;3735 memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);3736 memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);3737 3738 3739 sp->type = SRB_CT_PTHRU_CMD;3740 sp->gen1 = vha->hw->base_qpair->chip_reset;3741 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,3742 qla_async_scan_sp_done);3743 3744 ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;3745 3746 /* CT_IU preamble */3747 switch (vha->scan.step) {3748 case FAB_SCAN_GPNFT_FCP:3749 sp->name = "gpnft";3750 ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);3751 ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;3752 sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;3753 break;3754 case FAB_SCAN_GNNFT_FCP:3755 sp->name = "gnnft";3756 ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);3757 ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;3758 sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;3759 break;3760 case FAB_SCAN_GPNFT_NVME:3761 sp->name = "gpnft";3762 ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);3763 ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;3764 sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;3765 break;3766 case FAB_SCAN_GNNFT_NVME:3767 sp->name = "gnnft";3768 ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);3769 ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;3770 sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;3771 break;3772 default:3773 /* should not be here */3774 WARN_ON(1);3775 goto done_free_sp;3776 }3777 3778 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;3779 3780 ql_dbg(ql_dbg_disc, vha, 0x2003,3781 "%s: step %d, rsp size %d, req size %d hdl %x %s FC4TYPE %x \n",3782 __func__, vha->scan.step, sp->u.iocb_cmd.u.ctarg.rsp_size,3783 sp->u.iocb_cmd.u.ctarg.req_size, sp->handle, sp->name,3784 ct_req->req.gpn_ft.port_type);3785 3786 rval = qla2x00_start_sp(sp);3787 if (rval != QLA_SUCCESS) {3788 goto done_free_sp;3789 }3790 3791 return rval;3792 3793done_free_sp:3794 if (sp->u.iocb_cmd.u.ctarg.req) {3795 dma_free_coherent(&vha->hw->pdev->dev,3796 sp->u.iocb_cmd.u.ctarg.req_allocated_size,3797 sp->u.iocb_cmd.u.ctarg.req,3798 sp->u.iocb_cmd.u.ctarg.req_dma);3799 sp->u.iocb_cmd.u.ctarg.req = NULL;3800 }3801 if (sp->u.iocb_cmd.u.ctarg.rsp) {3802 dma_free_coherent(&vha->hw->pdev->dev,3803 sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,3804 sp->u.iocb_cmd.u.ctarg.rsp,3805 sp->u.iocb_cmd.u.ctarg.rsp_dma);3806 sp->u.iocb_cmd.u.ctarg.rsp = NULL;3807 }3808 3809 /* ref: INIT */3810 kref_put(&sp->cmd_kref, qla2x00_sp_release);3811 3812 spin_lock_irqsave(&vha->work_lock, flags);3813 vha->scan.scan_flags &= ~SF_SCANNING;3814 if (vha->scan.scan_flags == 0) {3815 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2007,3816 "%s: Scan scheduled.\n", __func__);3817 vha->scan.scan_flags |= SF_QUEUED;3818 schedule_delayed_work(&vha->scan.scan_work, 5);3819 }3820 spin_unlock_irqrestore(&vha->work_lock, flags);3821 3822 3823 return rval;3824}3825 3826void qla_fab_scan_start(struct scsi_qla_host *vha)3827{3828 int rval;3829 3830 rval = qla_fab_async_scan(vha, NULL);3831 if (rval)3832 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3833}3834 3835void qla_scan_work_fn(struct work_struct *work)3836{3837 struct fab_scan *s = container_of(to_delayed_work(work),3838 struct fab_scan, scan_work);3839 struct scsi_qla_host *vha = container_of(s, struct scsi_qla_host,3840 scan);3841 unsigned long flags;3842 3843 ql_dbg(ql_dbg_disc, vha, 0xffff,3844 "%s: schedule loop resync\n", __func__);3845 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);3846 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);3847 qla2xxx_wake_dpc(vha);3848 spin_lock_irqsave(&vha->work_lock, flags);3849 vha->scan.scan_flags &= ~SF_QUEUED;3850 spin_unlock_irqrestore(&vha->work_lock, flags);3851}3852 3853/* GPFN_ID */3854void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)3855{3856 fc_port_t *fcport = ea->fcport;3857 3858 ql_dbg(ql_dbg_disc, vha, 0xffff,3859 "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d\n",3860 __func__, fcport->port_name, fcport->disc_state,3861 fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,3862 fcport->rscn_gen, ea->sp->gen1, vha->fcport_count);3863 3864 if (fcport->disc_state == DSC_DELETE_PEND)3865 return;3866 3867 if (ea->sp->gen2 != fcport->login_gen) {3868 /* target side must have changed it. */3869 ql_dbg(ql_dbg_disc, vha, 0x20d3,3870 "%s %8phC generation changed\n",3871 __func__, fcport->port_name);3872 return;3873 } else if (ea->sp->gen1 != fcport->rscn_gen) {3874 return;3875 }3876 3877 qla24xx_post_gpsc_work(vha, fcport);3878}3879 3880static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)3881{3882 struct scsi_qla_host *vha = sp->vha;3883 fc_port_t *fcport = sp->fcport;3884 u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;3885 struct event_arg ea;3886 u64 wwn;3887 3888 wwn = wwn_to_u64(fpn);3889 if (wwn)3890 memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);3891 3892 memset(&ea, 0, sizeof(ea));3893 ea.fcport = fcport;3894 ea.sp = sp;3895 ea.rc = res;3896 3897 ql_dbg(ql_dbg_disc, vha, 0x204f,3898 "Async done-%s res %x, WWPN %8phC %8phC\n",3899 sp->name, res, fcport->port_name, fcport->fabric_port_name);3900 3901 qla24xx_handle_gfpnid_event(vha, &ea);3902 3903 /* ref: INIT */3904 kref_put(&sp->cmd_kref, qla2x00_sp_release);3905}3906 3907int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)3908{3909 int rval = QLA_FUNCTION_FAILED;3910 struct ct_sns_req *ct_req;3911 srb_t *sp;3912 3913 if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))3914 return rval;3915 3916 /* ref: INIT */3917 sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);3918 if (!sp)3919 goto done;3920 3921 sp->type = SRB_CT_PTHRU_CMD;3922 sp->name = "gfpnid";3923 sp->gen1 = fcport->rscn_gen;3924 sp->gen2 = fcport->login_gen;3925 qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,3926 qla2x00_async_gfpnid_sp_done);3927 3928 /* CT_IU preamble */3929 ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,3930 GFPN_ID_RSP_SIZE);3931 3932 /* GFPN_ID req */3933 ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);3934 3935 3936 /* req & rsp use the same buffer */3937 sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;3938 sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;3939 sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;3940 sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;3941 sp->u.iocb_cmd.u.ctarg.req_size = GFPN_ID_REQ_SIZE;3942 sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;3943 sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;3944 3945 ql_dbg(ql_dbg_disc, vha, 0xffff,3946 "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",3947 sp->name, fcport->port_name,3948 sp->handle, fcport->loop_id, fcport->d_id.b24);3949 3950 rval = qla2x00_start_sp(sp);3951 if (rval != QLA_SUCCESS)3952 goto done_free_sp;3953 3954 return rval;3955 3956done_free_sp:3957 /* ref: INIT */3958 kref_put(&sp->cmd_kref, qla2x00_sp_release);3959done:3960 return rval;3961}3962 3963int qla24xx_post_gfpnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)3964{3965 struct qla_work_evt *e;3966 int ls;3967 3968 ls = atomic_read(&vha->loop_state);3969 if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||3970 test_bit(UNLOADING, &vha->dpc_flags))3971 return 0;3972 3973 e = qla2x00_alloc_work(vha, QLA_EVT_GFPNID);3974 if (!e)3975 return QLA_FUNCTION_FAILED;3976 3977 e->u.fcport.fcport = fcport;3978 return qla2x00_post_work(vha, e);3979}3980