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