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