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