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