1 /* 2 * QLOGIC LINUX SOFTWARE 3 * 4 * QLogic ISP2x00 device driver for Linux 2.6.x 5 * Copyright (C) 2003-2004 QLogic Corporation 6 * (www.qlogic.com) 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2, or (at your option) any 11 * later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 */ 19 #include "qla_def.h" 20 21 static inline ms_iocb_entry_t * 22 qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t); 23 24 static inline struct ct_sns_req * 25 qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t); 26 27 static inline struct sns_cmd_pkt * 28 qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); 29 30 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *); 31 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *); 32 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *); 33 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *); 34 static int qla2x00_sns_rft_id(scsi_qla_host_t *); 35 static int qla2x00_sns_rnn_id(scsi_qla_host_t *); 36 37 /** 38 * qla2x00_prep_ms_iocb() - Prepare common MS IOCB fields for SNS CT query. 39 * @ha: HA context 40 * @req_size: request size in bytes 41 * @rsp_size: response size in bytes 42 * 43 * Returns a pointer to the @ha's ms_iocb. 44 */ 45 static inline ms_iocb_entry_t * 46 qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) 47 { 48 ms_iocb_entry_t *ms_pkt; 49 50 ms_pkt = ha->ms_iocb; 51 memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); 52 53 ms_pkt->entry_type = MS_IOCB_TYPE; 54 ms_pkt->entry_count = 1; 55 SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER); 56 ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); 57 ms_pkt->timeout = __constant_cpu_to_le16(25); 58 ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); 59 ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); 60 ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); 61 ms_pkt->req_bytecount = cpu_to_le32(req_size); 62 63 ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); 64 ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); 65 ms_pkt->dseg_req_length = ms_pkt->req_bytecount; 66 67 ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); 68 ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); 69 ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; 70 71 return (ms_pkt); 72 } 73 74 /** 75 * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. 76 * @ct_req: CT request buffer 77 * @cmd: GS command 78 * @rsp_size: response size in bytes 79 * 80 * Returns a pointer to the intitialized @ct_req. 81 */ 82 static inline struct ct_sns_req * 83 qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size) 84 { 85 memset(ct_req, 0, sizeof(struct ct_sns_pkt)); 86 87 ct_req->header.revision = 0x01; 88 ct_req->header.gs_type = 0xFC; 89 ct_req->header.gs_subtype = 0x02; 90 ct_req->command = cpu_to_be16(cmd); 91 ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); 92 93 return (ct_req); 94 } 95 96 97 /** 98 * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command. 99 * @ha: HA context 100 * @fcport: fcport entry to updated 101 * 102 * Returns 0 on success. 103 */ 104 int 105 qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport) 106 { 107 int rval; 108 109 ms_iocb_entry_t *ms_pkt; 110 struct ct_sns_req *ct_req; 111 struct ct_sns_rsp *ct_rsp; 112 113 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 114 return (qla2x00_sns_ga_nxt(ha, fcport)); 115 } 116 117 /* Issue GA_NXT */ 118 /* Prepare common MS IOCB */ 119 ms_pkt = qla2x00_prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE); 120 121 /* Prepare CT request */ 122 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, 123 GA_NXT_RSP_SIZE); 124 ct_rsp = &ha->ct_sns->p.rsp; 125 126 /* Prepare CT arguments -- port_id */ 127 ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain; 128 ct_req->req.port_id.port_id[1] = fcport->d_id.b.area; 129 ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa; 130 131 /* Execute MS IOCB */ 132 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 133 sizeof(ms_iocb_entry_t)); 134 if (rval != QLA_SUCCESS) { 135 /*EMPTY*/ 136 DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n", 137 ha->host_no, rval)); 138 } else if (ct_rsp->header.response != 139 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 140 DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, " 141 "ga_nxt_rsp:\n", ha->host_no)); 142 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 143 sizeof(struct ct_rsp_hdr))); 144 rval = QLA_FUNCTION_FAILED; 145 } else { 146 /* Populate fc_port_t entry. */ 147 fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0]; 148 fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1]; 149 fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2]; 150 151 memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name, 152 WWN_SIZE); 153 memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name, 154 WWN_SIZE); 155 156 if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE && 157 ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE) 158 fcport->d_id.b.domain = 0xf0; 159 160 DEBUG2_3(printk("scsi(%ld): GA_NXT entry - " 161 "nn %02x%02x%02x%02x%02x%02x%02x%02x " 162 "pn %02x%02x%02x%02x%02x%02x%02x%02x " 163 "portid=%02x%02x%02x.\n", 164 ha->host_no, 165 fcport->node_name[0], fcport->node_name[1], 166 fcport->node_name[2], fcport->node_name[3], 167 fcport->node_name[4], fcport->node_name[5], 168 fcport->node_name[6], fcport->node_name[7], 169 fcport->port_name[0], fcport->port_name[1], 170 fcport->port_name[2], fcport->port_name[3], 171 fcport->port_name[4], fcport->port_name[5], 172 fcport->port_name[6], fcport->port_name[7], 173 fcport->d_id.b.domain, fcport->d_id.b.area, 174 fcport->d_id.b.al_pa)); 175 } 176 177 return (rval); 178 } 179 180 /** 181 * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command. 182 * @ha: HA context 183 * @list: switch info entries to populate 184 * 185 * NOTE: Non-Nx_Ports are not requested. 186 * 187 * Returns 0 on success. 188 */ 189 int 190 qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) 191 { 192 int rval; 193 uint16_t i; 194 195 ms_iocb_entry_t *ms_pkt; 196 struct ct_sns_req *ct_req; 197 struct ct_sns_rsp *ct_rsp; 198 199 struct ct_sns_gid_pt_data *gid_data; 200 201 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 202 return (qla2x00_sns_gid_pt(ha, list)); 203 } 204 205 gid_data = NULL; 206 207 /* Issue GID_PT */ 208 /* Prepare common MS IOCB */ 209 ms_pkt = qla2x00_prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE); 210 211 /* Prepare CT request */ 212 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, 213 GID_PT_RSP_SIZE); 214 ct_rsp = &ha->ct_sns->p.rsp; 215 216 /* Prepare CT arguments -- port_type */ 217 ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE; 218 219 /* Execute MS IOCB */ 220 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 221 sizeof(ms_iocb_entry_t)); 222 if (rval != QLA_SUCCESS) { 223 /*EMPTY*/ 224 DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n", 225 ha->host_no, rval)); 226 } else if (ct_rsp->header.response != 227 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 228 DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, " 229 "gid_pt_rsp:\n", ha->host_no)); 230 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 231 sizeof(struct ct_rsp_hdr))); 232 rval = QLA_FUNCTION_FAILED; 233 } else { 234 /* Set port IDs in switch info list. */ 235 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 236 gid_data = &ct_rsp->rsp.gid_pt.entries[i]; 237 list[i].d_id.b.domain = gid_data->port_id[0]; 238 list[i].d_id.b.area = gid_data->port_id[1]; 239 list[i].d_id.b.al_pa = gid_data->port_id[2]; 240 241 /* Last one exit. */ 242 if (gid_data->control_byte & BIT_7) { 243 list[i].d_id.b.rsvd_1 = gid_data->control_byte; 244 break; 245 } 246 } 247 248 /* 249 * If we've used all available slots, then the switch is 250 * reporting back more devices than we can handle with this 251 * single call. Return a failed status, and let GA_NXT handle 252 * the overload. 253 */ 254 if (i == MAX_FIBRE_DEVICES) 255 rval = QLA_FUNCTION_FAILED; 256 } 257 258 return (rval); 259 } 260 261 /** 262 * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query. 263 * @ha: HA context 264 * @list: switch info entries to populate 265 * 266 * Returns 0 on success. 267 */ 268 int 269 qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list) 270 { 271 int rval; 272 uint16_t i; 273 274 ms_iocb_entry_t *ms_pkt; 275 struct ct_sns_req *ct_req; 276 struct ct_sns_rsp *ct_rsp; 277 278 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 279 return (qla2x00_sns_gpn_id(ha, list)); 280 } 281 282 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 283 /* Issue GPN_ID */ 284 /* Prepare common MS IOCB */ 285 ms_pkt = qla2x00_prep_ms_iocb(ha, GPN_ID_REQ_SIZE, 286 GPN_ID_RSP_SIZE); 287 288 /* Prepare CT request */ 289 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD, 290 GPN_ID_RSP_SIZE); 291 ct_rsp = &ha->ct_sns->p.rsp; 292 293 /* Prepare CT arguments -- port_id */ 294 ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; 295 ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; 296 ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; 297 298 /* Execute MS IOCB */ 299 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 300 sizeof(ms_iocb_entry_t)); 301 if (rval != QLA_SUCCESS) { 302 /*EMPTY*/ 303 DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed " 304 "(%d).\n", ha->host_no, rval)); 305 } else if (ct_rsp->header.response != 306 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 307 DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected " 308 "request, gpn_id_rsp:\n", ha->host_no)); 309 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 310 sizeof(struct ct_rsp_hdr))); 311 rval = QLA_FUNCTION_FAILED; 312 } else { 313 /* Save portname */ 314 memcpy(list[i].port_name, 315 ct_rsp->rsp.gpn_id.port_name, WWN_SIZE); 316 } 317 318 /* Last device exit. */ 319 if (list[i].d_id.b.rsvd_1 != 0) 320 break; 321 } 322 323 return (rval); 324 } 325 326 /** 327 * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query. 328 * @ha: HA context 329 * @list: switch info entries to populate 330 * 331 * Returns 0 on success. 332 */ 333 int 334 qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list) 335 { 336 int rval; 337 uint16_t i; 338 339 ms_iocb_entry_t *ms_pkt; 340 struct ct_sns_req *ct_req; 341 struct ct_sns_rsp *ct_rsp; 342 343 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 344 return (qla2x00_sns_gnn_id(ha, list)); 345 } 346 347 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 348 /* Issue GNN_ID */ 349 /* Prepare common MS IOCB */ 350 ms_pkt = qla2x00_prep_ms_iocb(ha, GNN_ID_REQ_SIZE, 351 GNN_ID_RSP_SIZE); 352 353 /* Prepare CT request */ 354 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD, 355 GNN_ID_RSP_SIZE); 356 ct_rsp = &ha->ct_sns->p.rsp; 357 358 /* Prepare CT arguments -- port_id */ 359 ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; 360 ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; 361 ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; 362 363 /* Execute MS IOCB */ 364 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 365 sizeof(ms_iocb_entry_t)); 366 if (rval != QLA_SUCCESS) { 367 /*EMPTY*/ 368 DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed " 369 "(%d).\n", ha->host_no, rval)); 370 } else if (ct_rsp->header.response != 371 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 372 DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected " 373 "request, gnn_id_rsp:\n", ha->host_no)); 374 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 375 sizeof(struct ct_rsp_hdr))); 376 rval = QLA_FUNCTION_FAILED; 377 } else { 378 /* Save nodename */ 379 memcpy(list[i].node_name, 380 ct_rsp->rsp.gnn_id.node_name, WWN_SIZE); 381 382 DEBUG2_3(printk("scsi(%ld): GID_PT entry - " 383 "nn %02x%02x%02x%02x%02x%02x%02x%02x " 384 "pn %02x%02x%02x%02x%02x%02x%02x%02x " 385 "portid=%02x%02x%02x.\n", 386 ha->host_no, 387 list[i].node_name[0], list[i].node_name[1], 388 list[i].node_name[2], list[i].node_name[3], 389 list[i].node_name[4], list[i].node_name[5], 390 list[i].node_name[6], list[i].node_name[7], 391 list[i].port_name[0], list[i].port_name[1], 392 list[i].port_name[2], list[i].port_name[3], 393 list[i].port_name[4], list[i].port_name[5], 394 list[i].port_name[6], list[i].port_name[7], 395 list[i].d_id.b.domain, list[i].d_id.b.area, 396 list[i].d_id.b.al_pa)); 397 } 398 399 /* Last device exit. */ 400 if (list[i].d_id.b.rsvd_1 != 0) 401 break; 402 } 403 404 return (rval); 405 } 406 407 /** 408 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA. 409 * @ha: HA context 410 * 411 * Returns 0 on success. 412 */ 413 int 414 qla2x00_rft_id(scsi_qla_host_t *ha) 415 { 416 int rval; 417 418 ms_iocb_entry_t *ms_pkt; 419 struct ct_sns_req *ct_req; 420 struct ct_sns_rsp *ct_rsp; 421 422 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 423 return (qla2x00_sns_rft_id(ha)); 424 } 425 426 /* Issue RFT_ID */ 427 /* Prepare common MS IOCB */ 428 ms_pkt = qla2x00_prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE); 429 430 /* Prepare CT request */ 431 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, 432 RFT_ID_RSP_SIZE); 433 ct_rsp = &ha->ct_sns->p.rsp; 434 435 /* Prepare CT arguments -- port_id, FC-4 types */ 436 ct_req->req.rft_id.port_id[0] = ha->d_id.b.domain; 437 ct_req->req.rft_id.port_id[1] = ha->d_id.b.area; 438 ct_req->req.rft_id.port_id[2] = ha->d_id.b.al_pa; 439 440 ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */ 441 442 /* Execute MS IOCB */ 443 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 444 sizeof(ms_iocb_entry_t)); 445 if (rval != QLA_SUCCESS) { 446 /*EMPTY*/ 447 DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n", 448 ha->host_no, rval)); 449 } else if (ct_rsp->header.response != 450 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 451 DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected " 452 "request, rft_id_rsp:\n", ha->host_no)); 453 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 454 sizeof(struct ct_rsp_hdr))); 455 rval = QLA_FUNCTION_FAILED; 456 } else { 457 DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n", 458 ha->host_no)); 459 } 460 461 return (rval); 462 } 463 464 /** 465 * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA. 466 * @ha: HA context 467 * 468 * Returns 0 on success. 469 */ 470 int 471 qla2x00_rff_id(scsi_qla_host_t *ha) 472 { 473 int rval; 474 475 ms_iocb_entry_t *ms_pkt; 476 struct ct_sns_req *ct_req; 477 struct ct_sns_rsp *ct_rsp; 478 479 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 480 DEBUG2(printk("scsi(%ld): RFF_ID call unsupported on " 481 "ISP2100/ISP2200.\n", ha->host_no)); 482 return (QLA_SUCCESS); 483 } 484 485 /* Issue RFF_ID */ 486 /* Prepare common MS IOCB */ 487 ms_pkt = qla2x00_prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE); 488 489 /* Prepare CT request */ 490 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, 491 RFF_ID_RSP_SIZE); 492 ct_rsp = &ha->ct_sns->p.rsp; 493 494 /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */ 495 ct_req->req.rff_id.port_id[0] = ha->d_id.b.domain; 496 ct_req->req.rff_id.port_id[1] = ha->d_id.b.area; 497 ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa; 498 499 ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ 500 501 /* Execute MS IOCB */ 502 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 503 sizeof(ms_iocb_entry_t)); 504 if (rval != QLA_SUCCESS) { 505 /*EMPTY*/ 506 DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n", 507 ha->host_no, rval)); 508 } else if (ct_rsp->header.response != 509 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 510 DEBUG2_3(printk("scsi(%ld): RFF_ID failed, rejected " 511 "request, rff_id_rsp:\n", ha->host_no)); 512 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 513 sizeof(struct ct_rsp_hdr))); 514 rval = QLA_FUNCTION_FAILED; 515 } else { 516 DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n", 517 ha->host_no)); 518 } 519 520 return (rval); 521 } 522 523 /** 524 * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA. 525 * @ha: HA context 526 * 527 * Returns 0 on success. 528 */ 529 int 530 qla2x00_rnn_id(scsi_qla_host_t *ha) 531 { 532 int rval; 533 534 ms_iocb_entry_t *ms_pkt; 535 struct ct_sns_req *ct_req; 536 struct ct_sns_rsp *ct_rsp; 537 538 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 539 return (qla2x00_sns_rnn_id(ha)); 540 } 541 542 /* Issue RNN_ID */ 543 /* Prepare common MS IOCB */ 544 ms_pkt = qla2x00_prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE); 545 546 /* Prepare CT request */ 547 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, 548 RNN_ID_RSP_SIZE); 549 ct_rsp = &ha->ct_sns->p.rsp; 550 551 /* Prepare CT arguments -- port_id, node_name */ 552 ct_req->req.rnn_id.port_id[0] = ha->d_id.b.domain; 553 ct_req->req.rnn_id.port_id[1] = ha->d_id.b.area; 554 ct_req->req.rnn_id.port_id[2] = ha->d_id.b.al_pa; 555 556 memcpy(ct_req->req.rnn_id.node_name, ha->init_cb->node_name, WWN_SIZE); 557 558 /* Execute MS IOCB */ 559 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 560 sizeof(ms_iocb_entry_t)); 561 if (rval != QLA_SUCCESS) { 562 /*EMPTY*/ 563 DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n", 564 ha->host_no, rval)); 565 } else if (ct_rsp->header.response != 566 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 567 DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected " 568 "request, rnn_id_rsp:\n", ha->host_no)); 569 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 570 sizeof(struct ct_rsp_hdr))); 571 rval = QLA_FUNCTION_FAILED; 572 } else { 573 DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n", 574 ha->host_no)); 575 } 576 577 return (rval); 578 } 579 580 /** 581 * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA. 582 * @ha: HA context 583 * 584 * Returns 0 on success. 585 */ 586 int 587 qla2x00_rsnn_nn(scsi_qla_host_t *ha) 588 { 589 int rval; 590 uint8_t *snn; 591 uint8_t version[20]; 592 593 ms_iocb_entry_t *ms_pkt; 594 struct ct_sns_req *ct_req; 595 struct ct_sns_rsp *ct_rsp; 596 597 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 598 DEBUG2(printk("scsi(%ld): RSNN_ID call unsupported on " 599 "ISP2100/ISP2200.\n", ha->host_no)); 600 return (QLA_SUCCESS); 601 } 602 603 /* Issue RSNN_NN */ 604 /* Prepare common MS IOCB */ 605 /* Request size adjusted after CT preparation */ 606 ms_pkt = qla2x00_prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); 607 608 /* Prepare CT request */ 609 ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, 610 RSNN_NN_RSP_SIZE); 611 ct_rsp = &ha->ct_sns->p.rsp; 612 613 /* Prepare CT arguments -- node_name, symbolic node_name, size */ 614 memcpy(ct_req->req.rsnn_nn.node_name, ha->init_cb->node_name, WWN_SIZE); 615 616 /* Prepare the Symbolic Node Name */ 617 /* Board type */ 618 snn = ct_req->req.rsnn_nn.sym_node_name; 619 strcpy(snn, ha->model_number); 620 /* Firmware version */ 621 strcat(snn, " FW:v"); 622 sprintf(version, "%d.%02d.%02d", ha->fw_major_version, 623 ha->fw_minor_version, ha->fw_subminor_version); 624 strcat(snn, version); 625 /* Driver version */ 626 strcat(snn, " DVR:v"); 627 strcat(snn, qla2x00_version_str); 628 629 /* Calculate SNN length */ 630 ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn); 631 632 /* Update MS IOCB request */ 633 ms_pkt->req_bytecount = 634 cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len); 635 ms_pkt->dseg_req_length = ms_pkt->req_bytecount; 636 637 /* Execute MS IOCB */ 638 rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, 639 sizeof(ms_iocb_entry_t)); 640 if (rval != QLA_SUCCESS) { 641 /*EMPTY*/ 642 DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n", 643 ha->host_no, rval)); 644 } else if (ct_rsp->header.response != 645 __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { 646 DEBUG2_3(printk("scsi(%ld): RSNN_NN failed, rejected " 647 "request, rsnn_id_rsp:\n", ha->host_no)); 648 DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, 649 sizeof(struct ct_rsp_hdr))); 650 rval = QLA_FUNCTION_FAILED; 651 } else { 652 DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n", 653 ha->host_no)); 654 } 655 656 return (rval); 657 } 658 659 660 /** 661 * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query. 662 * @ha: HA context 663 * @cmd: GS command 664 * @scmd_len: Subcommand length 665 * @data_size: response size in bytes 666 * 667 * Returns a pointer to the @ha's sns_cmd. 668 */ 669 static inline struct sns_cmd_pkt * 670 qla2x00_prep_sns_cmd(scsi_qla_host_t *ha, uint16_t cmd, uint16_t scmd_len, 671 uint16_t data_size) 672 { 673 uint16_t wc; 674 struct sns_cmd_pkt *sns_cmd; 675 676 sns_cmd = ha->sns_cmd; 677 memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt)); 678 wc = data_size / 2; /* Size in 16bit words. */ 679 sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc); 680 sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma)); 681 sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma)); 682 sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len); 683 sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd); 684 wc = (data_size - 16) / 4; /* Size in 32bit words. */ 685 sns_cmd->p.cmd.size = cpu_to_le16(wc); 686 687 return (sns_cmd); 688 } 689 690 /** 691 * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command. 692 * @ha: HA context 693 * @fcport: fcport entry to updated 694 * 695 * This command uses the old Exectute SNS Command mailbox routine. 696 * 697 * Returns 0 on success. 698 */ 699 static int 700 qla2x00_sns_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport) 701 { 702 int rval; 703 704 struct sns_cmd_pkt *sns_cmd; 705 706 /* Issue GA_NXT. */ 707 /* Prepare SNS command request. */ 708 sns_cmd = qla2x00_prep_sns_cmd(ha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN, 709 GA_NXT_SNS_DATA_SIZE); 710 711 /* Prepare SNS command arguments -- port_id. */ 712 sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa; 713 sns_cmd->p.cmd.param[1] = fcport->d_id.b.area; 714 sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain; 715 716 /* Execute SNS command. */ 717 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2, 718 sizeof(struct sns_cmd_pkt)); 719 if (rval != QLA_SUCCESS) { 720 /*EMPTY*/ 721 DEBUG2_3(printk("scsi(%ld): GA_NXT Send SNS failed (%d).\n", 722 ha->host_no, rval)); 723 } else if (sns_cmd->p.gan_data[8] != 0x80 || 724 sns_cmd->p.gan_data[9] != 0x02) { 725 DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, " 726 "ga_nxt_rsp:\n", ha->host_no)); 727 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gan_data, 16)); 728 rval = QLA_FUNCTION_FAILED; 729 } else { 730 /* Populate fc_port_t entry. */ 731 fcport->d_id.b.domain = sns_cmd->p.gan_data[17]; 732 fcport->d_id.b.area = sns_cmd->p.gan_data[18]; 733 fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19]; 734 735 memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE); 736 memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE); 737 738 if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE && 739 sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE) 740 fcport->d_id.b.domain = 0xf0; 741 742 DEBUG2_3(printk("scsi(%ld): GA_NXT entry - " 743 "nn %02x%02x%02x%02x%02x%02x%02x%02x " 744 "pn %02x%02x%02x%02x%02x%02x%02x%02x " 745 "portid=%02x%02x%02x.\n", 746 ha->host_no, 747 fcport->node_name[0], fcport->node_name[1], 748 fcport->node_name[2], fcport->node_name[3], 749 fcport->node_name[4], fcport->node_name[5], 750 fcport->node_name[6], fcport->node_name[7], 751 fcport->port_name[0], fcport->port_name[1], 752 fcport->port_name[2], fcport->port_name[3], 753 fcport->port_name[4], fcport->port_name[5], 754 fcport->port_name[6], fcport->port_name[7], 755 fcport->d_id.b.domain, fcport->d_id.b.area, 756 fcport->d_id.b.al_pa)); 757 } 758 759 return (rval); 760 } 761 762 /** 763 * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command. 764 * @ha: HA context 765 * @list: switch info entries to populate 766 * 767 * This command uses the old Exectute SNS Command mailbox routine. 768 * 769 * NOTE: Non-Nx_Ports are not requested. 770 * 771 * Returns 0 on success. 772 */ 773 static int 774 qla2x00_sns_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) 775 { 776 int rval; 777 778 uint16_t i; 779 uint8_t *entry; 780 struct sns_cmd_pkt *sns_cmd; 781 782 /* Issue GID_PT. */ 783 /* Prepare SNS command request. */ 784 sns_cmd = qla2x00_prep_sns_cmd(ha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN, 785 GID_PT_SNS_DATA_SIZE); 786 787 /* Prepare SNS command arguments -- port_type. */ 788 sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE; 789 790 /* Execute SNS command. */ 791 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2, 792 sizeof(struct sns_cmd_pkt)); 793 if (rval != QLA_SUCCESS) { 794 /*EMPTY*/ 795 DEBUG2_3(printk("scsi(%ld): GID_PT Send SNS failed (%d).\n", 796 ha->host_no, rval)); 797 } else if (sns_cmd->p.gid_data[8] != 0x80 || 798 sns_cmd->p.gid_data[9] != 0x02) { 799 DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, " 800 "gid_rsp:\n", ha->host_no)); 801 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gid_data, 16)); 802 rval = QLA_FUNCTION_FAILED; 803 } else { 804 /* Set port IDs in switch info list. */ 805 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 806 entry = &sns_cmd->p.gid_data[(i * 4) + 16]; 807 list[i].d_id.b.domain = entry[1]; 808 list[i].d_id.b.area = entry[2]; 809 list[i].d_id.b.al_pa = entry[3]; 810 811 /* Last one exit. */ 812 if (entry[0] & BIT_7) { 813 list[i].d_id.b.rsvd_1 = entry[0]; 814 break; 815 } 816 } 817 818 /* 819 * If we've used all available slots, then the switch is 820 * reporting back more devices that we can handle with this 821 * single call. Return a failed status, and let GA_NXT handle 822 * the overload. 823 */ 824 if (i == MAX_FIBRE_DEVICES) 825 rval = QLA_FUNCTION_FAILED; 826 } 827 828 return (rval); 829 } 830 831 /** 832 * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query. 833 * @ha: HA context 834 * @list: switch info entries to populate 835 * 836 * This command uses the old Exectute SNS Command mailbox routine. 837 * 838 * Returns 0 on success. 839 */ 840 static int 841 qla2x00_sns_gpn_id(scsi_qla_host_t *ha, sw_info_t *list) 842 { 843 int rval; 844 845 uint16_t i; 846 struct sns_cmd_pkt *sns_cmd; 847 848 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 849 /* Issue GPN_ID */ 850 /* Prepare SNS command request. */ 851 sns_cmd = qla2x00_prep_sns_cmd(ha, GPN_ID_CMD, 852 GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE); 853 854 /* Prepare SNS command arguments -- port_id. */ 855 sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa; 856 sns_cmd->p.cmd.param[1] = list[i].d_id.b.area; 857 sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain; 858 859 /* Execute SNS command. */ 860 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, 861 GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt)); 862 if (rval != QLA_SUCCESS) { 863 /*EMPTY*/ 864 DEBUG2_3(printk("scsi(%ld): GPN_ID Send SNS failed " 865 "(%d).\n", ha->host_no, rval)); 866 } else if (sns_cmd->p.gpn_data[8] != 0x80 || 867 sns_cmd->p.gpn_data[9] != 0x02) { 868 DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected " 869 "request, gpn_rsp:\n", ha->host_no)); 870 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gpn_data, 16)); 871 rval = QLA_FUNCTION_FAILED; 872 } else { 873 /* Save portname */ 874 memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16], 875 WWN_SIZE); 876 } 877 878 /* Last device exit. */ 879 if (list[i].d_id.b.rsvd_1 != 0) 880 break; 881 } 882 883 return (rval); 884 } 885 886 /** 887 * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query. 888 * @ha: HA context 889 * @list: switch info entries to populate 890 * 891 * This command uses the old Exectute SNS Command mailbox routine. 892 * 893 * Returns 0 on success. 894 */ 895 static int 896 qla2x00_sns_gnn_id(scsi_qla_host_t *ha, sw_info_t *list) 897 { 898 int rval; 899 900 uint16_t i; 901 struct sns_cmd_pkt *sns_cmd; 902 903 for (i = 0; i < MAX_FIBRE_DEVICES; i++) { 904 /* Issue GNN_ID */ 905 /* Prepare SNS command request. */ 906 sns_cmd = qla2x00_prep_sns_cmd(ha, GNN_ID_CMD, 907 GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE); 908 909 /* Prepare SNS command arguments -- port_id. */ 910 sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa; 911 sns_cmd->p.cmd.param[1] = list[i].d_id.b.area; 912 sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain; 913 914 /* Execute SNS command. */ 915 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, 916 GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt)); 917 if (rval != QLA_SUCCESS) { 918 /*EMPTY*/ 919 DEBUG2_3(printk("scsi(%ld): GNN_ID Send SNS failed " 920 "(%d).\n", ha->host_no, rval)); 921 } else if (sns_cmd->p.gnn_data[8] != 0x80 || 922 sns_cmd->p.gnn_data[9] != 0x02) { 923 DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected " 924 "request, gnn_rsp:\n", ha->host_no)); 925 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gnn_data, 16)); 926 rval = QLA_FUNCTION_FAILED; 927 } else { 928 /* Save nodename */ 929 memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16], 930 WWN_SIZE); 931 932 DEBUG2_3(printk("scsi(%ld): GID_PT entry - " 933 "nn %02x%02x%02x%02x%02x%02x%02x%02x " 934 "pn %02x%02x%02x%02x%02x%02x%02x%02x " 935 "portid=%02x%02x%02x.\n", 936 ha->host_no, 937 list[i].node_name[0], list[i].node_name[1], 938 list[i].node_name[2], list[i].node_name[3], 939 list[i].node_name[4], list[i].node_name[5], 940 list[i].node_name[6], list[i].node_name[7], 941 list[i].port_name[0], list[i].port_name[1], 942 list[i].port_name[2], list[i].port_name[3], 943 list[i].port_name[4], list[i].port_name[5], 944 list[i].port_name[6], list[i].port_name[7], 945 list[i].d_id.b.domain, list[i].d_id.b.area, 946 list[i].d_id.b.al_pa)); 947 } 948 949 /* Last device exit. */ 950 if (list[i].d_id.b.rsvd_1 != 0) 951 break; 952 } 953 954 return (rval); 955 } 956 957 /** 958 * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA. 959 * @ha: HA context 960 * 961 * This command uses the old Exectute SNS Command mailbox routine. 962 * 963 * Returns 0 on success. 964 */ 965 static int 966 qla2x00_sns_rft_id(scsi_qla_host_t *ha) 967 { 968 int rval; 969 970 struct sns_cmd_pkt *sns_cmd; 971 972 /* Issue RFT_ID. */ 973 /* Prepare SNS command request. */ 974 sns_cmd = qla2x00_prep_sns_cmd(ha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN, 975 RFT_ID_SNS_DATA_SIZE); 976 977 /* Prepare SNS command arguments -- port_id, FC-4 types */ 978 sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa; 979 sns_cmd->p.cmd.param[1] = ha->d_id.b.area; 980 sns_cmd->p.cmd.param[2] = ha->d_id.b.domain; 981 982 sns_cmd->p.cmd.param[5] = 0x01; /* FCP-3 */ 983 984 /* Execute SNS command. */ 985 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2, 986 sizeof(struct sns_cmd_pkt)); 987 if (rval != QLA_SUCCESS) { 988 /*EMPTY*/ 989 DEBUG2_3(printk("scsi(%ld): RFT_ID Send SNS failed (%d).\n", 990 ha->host_no, rval)); 991 } else if (sns_cmd->p.rft_data[8] != 0x80 || 992 sns_cmd->p.rft_data[9] != 0x02) { 993 DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected request, " 994 "rft_rsp:\n", ha->host_no)); 995 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rft_data, 16)); 996 rval = QLA_FUNCTION_FAILED; 997 } else { 998 DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n", 999 ha->host_no)); 1000 } 1001 1002 return (rval); 1003 } 1004 1005 /** 1006 * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA. 1007 * HBA. 1008 * @ha: HA context 1009 * 1010 * This command uses the old Exectute SNS Command mailbox routine. 1011 * 1012 * Returns 0 on success. 1013 */ 1014 static int 1015 qla2x00_sns_rnn_id(scsi_qla_host_t *ha) 1016 { 1017 int rval; 1018 1019 struct sns_cmd_pkt *sns_cmd; 1020 1021 /* Issue RNN_ID. */ 1022 /* Prepare SNS command request. */ 1023 sns_cmd = qla2x00_prep_sns_cmd(ha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN, 1024 RNN_ID_SNS_DATA_SIZE); 1025 1026 /* Prepare SNS command arguments -- port_id, nodename. */ 1027 sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa; 1028 sns_cmd->p.cmd.param[1] = ha->d_id.b.area; 1029 sns_cmd->p.cmd.param[2] = ha->d_id.b.domain; 1030 1031 sns_cmd->p.cmd.param[4] = ha->init_cb->node_name[7]; 1032 sns_cmd->p.cmd.param[5] = ha->init_cb->node_name[6]; 1033 sns_cmd->p.cmd.param[6] = ha->init_cb->node_name[5]; 1034 sns_cmd->p.cmd.param[7] = ha->init_cb->node_name[4]; 1035 sns_cmd->p.cmd.param[8] = ha->init_cb->node_name[3]; 1036 sns_cmd->p.cmd.param[9] = ha->init_cb->node_name[2]; 1037 sns_cmd->p.cmd.param[10] = ha->init_cb->node_name[1]; 1038 sns_cmd->p.cmd.param[11] = ha->init_cb->node_name[0]; 1039 1040 /* Execute SNS command. */ 1041 rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2, 1042 sizeof(struct sns_cmd_pkt)); 1043 if (rval != QLA_SUCCESS) { 1044 /*EMPTY*/ 1045 DEBUG2_3(printk("scsi(%ld): RNN_ID Send SNS failed (%d).\n", 1046 ha->host_no, rval)); 1047 } else if (sns_cmd->p.rnn_data[8] != 0x80 || 1048 sns_cmd->p.rnn_data[9] != 0x02) { 1049 DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected request, " 1050 "rnn_rsp:\n", ha->host_no)); 1051 DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rnn_data, 16)); 1052 rval = QLA_FUNCTION_FAILED; 1053 } else { 1054 DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n", 1055 ha->host_no)); 1056 } 1057 1058 return (rval); 1059 } 1060