ql4_bsg.c (24579B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * QLogic iSCSI HBA Driver 4 * Copyright (c) 2011-2013 QLogic Corporation 5 */ 6 7#include "ql4_def.h" 8#include "ql4_glbl.h" 9#include "ql4_bsg.h" 10 11static int 12qla4xxx_read_flash(struct bsg_job *bsg_job) 13{ 14 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 15 struct scsi_qla_host *ha = to_qla_host(host); 16 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 17 struct iscsi_bsg_request *bsg_req = bsg_job->request; 18 uint32_t offset = 0; 19 uint32_t length = 0; 20 dma_addr_t flash_dma; 21 uint8_t *flash = NULL; 22 int rval = -EINVAL; 23 24 bsg_reply->reply_payload_rcv_len = 0; 25 26 if (unlikely(pci_channel_offline(ha->pdev))) 27 goto leave; 28 29 if (ql4xxx_reset_active(ha)) { 30 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 31 rval = -EBUSY; 32 goto leave; 33 } 34 35 if (ha->flash_state != QLFLASH_WAITING) { 36 ql4_printk(KERN_ERR, ha, "%s: another flash operation " 37 "active\n", __func__); 38 rval = -EBUSY; 39 goto leave; 40 } 41 42 ha->flash_state = QLFLASH_READING; 43 offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 44 length = bsg_job->reply_payload.payload_len; 45 46 flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, 47 GFP_KERNEL); 48 if (!flash) { 49 ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 50 "data\n", __func__); 51 rval = -ENOMEM; 52 goto leave; 53 } 54 55 rval = qla4xxx_get_flash(ha, flash_dma, offset, length); 56 if (rval) { 57 ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__); 58 bsg_reply->result = DID_ERROR << 16; 59 rval = -EIO; 60 } else { 61 bsg_reply->reply_payload_rcv_len = 62 sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 63 bsg_job->reply_payload.sg_cnt, 64 flash, length); 65 bsg_reply->result = DID_OK << 16; 66 } 67 68 bsg_job_done(bsg_job, bsg_reply->result, 69 bsg_reply->reply_payload_rcv_len); 70 dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); 71leave: 72 ha->flash_state = QLFLASH_WAITING; 73 return rval; 74} 75 76static int 77qla4xxx_update_flash(struct bsg_job *bsg_job) 78{ 79 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 80 struct scsi_qla_host *ha = to_qla_host(host); 81 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 82 struct iscsi_bsg_request *bsg_req = bsg_job->request; 83 uint32_t length = 0; 84 uint32_t offset = 0; 85 uint32_t options = 0; 86 dma_addr_t flash_dma; 87 uint8_t *flash = NULL; 88 int rval = -EINVAL; 89 90 bsg_reply->reply_payload_rcv_len = 0; 91 92 if (unlikely(pci_channel_offline(ha->pdev))) 93 goto leave; 94 95 if (ql4xxx_reset_active(ha)) { 96 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 97 rval = -EBUSY; 98 goto leave; 99 } 100 101 if (ha->flash_state != QLFLASH_WAITING) { 102 ql4_printk(KERN_ERR, ha, "%s: another flash operation " 103 "active\n", __func__); 104 rval = -EBUSY; 105 goto leave; 106 } 107 108 ha->flash_state = QLFLASH_WRITING; 109 length = bsg_job->request_payload.payload_len; 110 offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 111 options = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 112 113 flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, 114 GFP_KERNEL); 115 if (!flash) { 116 ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 117 "data\n", __func__); 118 rval = -ENOMEM; 119 goto leave; 120 } 121 122 sg_copy_to_buffer(bsg_job->request_payload.sg_list, 123 bsg_job->request_payload.sg_cnt, flash, length); 124 125 rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options); 126 if (rval) { 127 ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__); 128 bsg_reply->result = DID_ERROR << 16; 129 rval = -EIO; 130 } else 131 bsg_reply->result = DID_OK << 16; 132 133 bsg_job_done(bsg_job, bsg_reply->result, 134 bsg_reply->reply_payload_rcv_len); 135 dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); 136leave: 137 ha->flash_state = QLFLASH_WAITING; 138 return rval; 139} 140 141static int 142qla4xxx_get_acb_state(struct bsg_job *bsg_job) 143{ 144 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 145 struct scsi_qla_host *ha = to_qla_host(host); 146 struct iscsi_bsg_request *bsg_req = bsg_job->request; 147 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 148 uint32_t status[MBOX_REG_COUNT]; 149 uint32_t acb_idx; 150 uint32_t ip_idx; 151 int rval = -EINVAL; 152 153 bsg_reply->reply_payload_rcv_len = 0; 154 155 if (unlikely(pci_channel_offline(ha->pdev))) 156 goto leave; 157 158 /* Only 4022 and above adapters are supported */ 159 if (is_qla4010(ha)) 160 goto leave; 161 162 if (ql4xxx_reset_active(ha)) { 163 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 164 rval = -EBUSY; 165 goto leave; 166 } 167 168 if (bsg_job->reply_payload.payload_len < sizeof(status)) { 169 ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n", 170 __func__, bsg_job->reply_payload.payload_len); 171 rval = -EINVAL; 172 goto leave; 173 } 174 175 acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 176 ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 177 178 rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status); 179 if (rval) { 180 ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n", 181 __func__); 182 bsg_reply->result = DID_ERROR << 16; 183 rval = -EIO; 184 } else { 185 bsg_reply->reply_payload_rcv_len = 186 sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 187 bsg_job->reply_payload.sg_cnt, 188 status, sizeof(status)); 189 bsg_reply->result = DID_OK << 16; 190 } 191 192 bsg_job_done(bsg_job, bsg_reply->result, 193 bsg_reply->reply_payload_rcv_len); 194leave: 195 return rval; 196} 197 198static int 199qla4xxx_read_nvram(struct bsg_job *bsg_job) 200{ 201 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 202 struct scsi_qla_host *ha = to_qla_host(host); 203 struct iscsi_bsg_request *bsg_req = bsg_job->request; 204 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 205 uint32_t offset = 0; 206 uint32_t len = 0; 207 uint32_t total_len = 0; 208 dma_addr_t nvram_dma; 209 uint8_t *nvram = NULL; 210 int rval = -EINVAL; 211 212 bsg_reply->reply_payload_rcv_len = 0; 213 214 if (unlikely(pci_channel_offline(ha->pdev))) 215 goto leave; 216 217 /* Only 40xx adapters are supported */ 218 if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) 219 goto leave; 220 221 if (ql4xxx_reset_active(ha)) { 222 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 223 rval = -EBUSY; 224 goto leave; 225 } 226 227 offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 228 len = bsg_job->reply_payload.payload_len; 229 total_len = offset + len; 230 231 /* total len should not be greater than max NVRAM size */ 232 if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || 233 ((is_qla4022(ha) || is_qla4032(ha)) && 234 total_len > QL40X2_NVRAM_SIZE)) { 235 ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" 236 " nvram size, offset=%d len=%d\n", 237 __func__, offset, len); 238 goto leave; 239 } 240 241 nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, 242 GFP_KERNEL); 243 if (!nvram) { 244 ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram " 245 "data\n", __func__); 246 rval = -ENOMEM; 247 goto leave; 248 } 249 250 rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len); 251 if (rval) { 252 ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__); 253 bsg_reply->result = DID_ERROR << 16; 254 rval = -EIO; 255 } else { 256 bsg_reply->reply_payload_rcv_len = 257 sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 258 bsg_job->reply_payload.sg_cnt, 259 nvram, len); 260 bsg_reply->result = DID_OK << 16; 261 } 262 263 bsg_job_done(bsg_job, bsg_reply->result, 264 bsg_reply->reply_payload_rcv_len); 265 dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); 266leave: 267 return rval; 268} 269 270static int 271qla4xxx_update_nvram(struct bsg_job *bsg_job) 272{ 273 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 274 struct scsi_qla_host *ha = to_qla_host(host); 275 struct iscsi_bsg_request *bsg_req = bsg_job->request; 276 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 277 uint32_t offset = 0; 278 uint32_t len = 0; 279 uint32_t total_len = 0; 280 dma_addr_t nvram_dma; 281 uint8_t *nvram = NULL; 282 int rval = -EINVAL; 283 284 bsg_reply->reply_payload_rcv_len = 0; 285 286 if (unlikely(pci_channel_offline(ha->pdev))) 287 goto leave; 288 289 if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) 290 goto leave; 291 292 if (ql4xxx_reset_active(ha)) { 293 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 294 rval = -EBUSY; 295 goto leave; 296 } 297 298 offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 299 len = bsg_job->request_payload.payload_len; 300 total_len = offset + len; 301 302 /* total len should not be greater than max NVRAM size */ 303 if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || 304 ((is_qla4022(ha) || is_qla4032(ha)) && 305 total_len > QL40X2_NVRAM_SIZE)) { 306 ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" 307 " nvram size, offset=%d len=%d\n", 308 __func__, offset, len); 309 goto leave; 310 } 311 312 nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, 313 GFP_KERNEL); 314 if (!nvram) { 315 ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 316 "data\n", __func__); 317 rval = -ENOMEM; 318 goto leave; 319 } 320 321 sg_copy_to_buffer(bsg_job->request_payload.sg_list, 322 bsg_job->request_payload.sg_cnt, nvram, len); 323 324 rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len); 325 if (rval) { 326 ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__); 327 bsg_reply->result = DID_ERROR << 16; 328 rval = -EIO; 329 } else 330 bsg_reply->result = DID_OK << 16; 331 332 bsg_job_done(bsg_job, bsg_reply->result, 333 bsg_reply->reply_payload_rcv_len); 334 dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); 335leave: 336 return rval; 337} 338 339static int 340qla4xxx_restore_defaults(struct bsg_job *bsg_job) 341{ 342 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 343 struct scsi_qla_host *ha = to_qla_host(host); 344 struct iscsi_bsg_request *bsg_req = bsg_job->request; 345 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 346 uint32_t region = 0; 347 uint32_t field0 = 0; 348 uint32_t field1 = 0; 349 int rval = -EINVAL; 350 351 bsg_reply->reply_payload_rcv_len = 0; 352 353 if (unlikely(pci_channel_offline(ha->pdev))) 354 goto leave; 355 356 if (is_qla4010(ha)) 357 goto leave; 358 359 if (ql4xxx_reset_active(ha)) { 360 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 361 rval = -EBUSY; 362 goto leave; 363 } 364 365 region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 366 field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 367 field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; 368 369 rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1); 370 if (rval) { 371 ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__); 372 bsg_reply->result = DID_ERROR << 16; 373 rval = -EIO; 374 } else 375 bsg_reply->result = DID_OK << 16; 376 377 bsg_job_done(bsg_job, bsg_reply->result, 378 bsg_reply->reply_payload_rcv_len); 379leave: 380 return rval; 381} 382 383static int 384qla4xxx_bsg_get_acb(struct bsg_job *bsg_job) 385{ 386 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 387 struct scsi_qla_host *ha = to_qla_host(host); 388 struct iscsi_bsg_request *bsg_req = bsg_job->request; 389 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 390 uint32_t acb_type = 0; 391 uint32_t len = 0; 392 dma_addr_t acb_dma; 393 uint8_t *acb = NULL; 394 int rval = -EINVAL; 395 396 bsg_reply->reply_payload_rcv_len = 0; 397 398 if (unlikely(pci_channel_offline(ha->pdev))) 399 goto leave; 400 401 /* Only 4022 and above adapters are supported */ 402 if (is_qla4010(ha)) 403 goto leave; 404 405 if (ql4xxx_reset_active(ha)) { 406 ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 407 rval = -EBUSY; 408 goto leave; 409 } 410 411 acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 412 len = bsg_job->reply_payload.payload_len; 413 if (len < sizeof(struct addr_ctrl_blk)) { 414 ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n", 415 __func__, len); 416 rval = -EINVAL; 417 goto leave; 418 } 419 420 acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL); 421 if (!acb) { 422 ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb " 423 "data\n", __func__); 424 rval = -ENOMEM; 425 goto leave; 426 } 427 428 rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len); 429 if (rval) { 430 ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__); 431 bsg_reply->result = DID_ERROR << 16; 432 rval = -EIO; 433 } else { 434 bsg_reply->reply_payload_rcv_len = 435 sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 436 bsg_job->reply_payload.sg_cnt, 437 acb, len); 438 bsg_reply->result = DID_OK << 16; 439 } 440 441 bsg_job_done(bsg_job, bsg_reply->result, 442 bsg_reply->reply_payload_rcv_len); 443 dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma); 444leave: 445 return rval; 446} 447 448static void ql4xxx_execute_diag_cmd(struct bsg_job *bsg_job) 449{ 450 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 451 struct scsi_qla_host *ha = to_qla_host(host); 452 struct iscsi_bsg_request *bsg_req = bsg_job->request; 453 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 454 uint8_t *rsp_ptr = NULL; 455 uint32_t mbox_cmd[MBOX_REG_COUNT]; 456 uint32_t mbox_sts[MBOX_REG_COUNT]; 457 int status = QLA_ERROR; 458 459 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); 460 461 if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 462 ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", 463 __func__); 464 bsg_reply->result = DID_ERROR << 16; 465 goto exit_diag_mem_test; 466 } 467 468 bsg_reply->reply_payload_rcv_len = 0; 469 memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], 470 sizeof(uint32_t) * MBOX_REG_COUNT); 471 472 DEBUG2(ql4_printk(KERN_INFO, ha, 473 "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", 474 __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], 475 mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], 476 mbox_cmd[7])); 477 478 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], 479 &mbox_sts[0]); 480 481 DEBUG2(ql4_printk(KERN_INFO, ha, 482 "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", 483 __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], 484 mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], 485 mbox_sts[7])); 486 487 if (status == QLA_SUCCESS) 488 bsg_reply->result = DID_OK << 16; 489 else 490 bsg_reply->result = DID_ERROR << 16; 491 492 /* Send mbox_sts to application */ 493 bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); 494 rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); 495 memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); 496 497exit_diag_mem_test: 498 DEBUG2(ql4_printk(KERN_INFO, ha, 499 "%s: bsg_reply->result = x%x, status = %s\n", 500 __func__, bsg_reply->result, STATUS(status))); 501 502 bsg_job_done(bsg_job, bsg_reply->result, 503 bsg_reply->reply_payload_rcv_len); 504} 505 506static int qla4_83xx_wait_for_loopback_config_comp(struct scsi_qla_host *ha, 507 int wait_for_link) 508{ 509 int status = QLA_SUCCESS; 510 511 if (!wait_for_completion_timeout(&ha->idc_comp, (IDC_COMP_TOV * HZ))) { 512 ql4_printk(KERN_INFO, ha, "%s: IDC Complete notification not received, Waiting for another %d timeout", 513 __func__, ha->idc_extend_tmo); 514 if (ha->idc_extend_tmo) { 515 if (!wait_for_completion_timeout(&ha->idc_comp, 516 (ha->idc_extend_tmo * HZ))) { 517 ha->notify_idc_comp = 0; 518 ha->notify_link_up_comp = 0; 519 ql4_printk(KERN_WARNING, ha, "%s: Aborting: IDC Complete notification not received", 520 __func__); 521 status = QLA_ERROR; 522 goto exit_wait; 523 } else { 524 DEBUG2(ql4_printk(KERN_INFO, ha, 525 "%s: IDC Complete notification received\n", 526 __func__)); 527 } 528 } 529 } else { 530 DEBUG2(ql4_printk(KERN_INFO, ha, 531 "%s: IDC Complete notification received\n", 532 __func__)); 533 } 534 ha->notify_idc_comp = 0; 535 536 if (wait_for_link) { 537 if (!wait_for_completion_timeout(&ha->link_up_comp, 538 (IDC_COMP_TOV * HZ))) { 539 ha->notify_link_up_comp = 0; 540 ql4_printk(KERN_WARNING, ha, "%s: Aborting: LINK UP notification not received", 541 __func__); 542 status = QLA_ERROR; 543 goto exit_wait; 544 } else { 545 DEBUG2(ql4_printk(KERN_INFO, ha, 546 "%s: LINK UP notification received\n", 547 __func__)); 548 } 549 ha->notify_link_up_comp = 0; 550 } 551 552exit_wait: 553 return status; 554} 555 556static int qla4_83xx_pre_loopback_config(struct scsi_qla_host *ha, 557 uint32_t *mbox_cmd) 558{ 559 uint32_t config = 0; 560 int status = QLA_SUCCESS; 561 562 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); 563 564 status = qla4_83xx_get_port_config(ha, &config); 565 if (status != QLA_SUCCESS) 566 goto exit_pre_loopback_config; 567 568 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Default port config=%08X\n", 569 __func__, config)); 570 571 if ((config & ENABLE_INTERNAL_LOOPBACK) || 572 (config & ENABLE_EXTERNAL_LOOPBACK)) { 573 ql4_printk(KERN_INFO, ha, "%s: Loopback diagnostics already in progress. Invalid request\n", 574 __func__); 575 goto exit_pre_loopback_config; 576 } 577 578 if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) 579 config |= ENABLE_INTERNAL_LOOPBACK; 580 581 if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) 582 config |= ENABLE_EXTERNAL_LOOPBACK; 583 584 config &= ~ENABLE_DCBX; 585 586 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: New port config=%08X\n", 587 __func__, config)); 588 589 ha->notify_idc_comp = 1; 590 ha->notify_link_up_comp = 1; 591 592 /* get the link state */ 593 qla4xxx_get_firmware_state(ha); 594 595 status = qla4_83xx_set_port_config(ha, &config); 596 if (status != QLA_SUCCESS) { 597 ha->notify_idc_comp = 0; 598 ha->notify_link_up_comp = 0; 599 goto exit_pre_loopback_config; 600 } 601exit_pre_loopback_config: 602 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, 603 STATUS(status))); 604 return status; 605} 606 607static int qla4_83xx_post_loopback_config(struct scsi_qla_host *ha, 608 uint32_t *mbox_cmd) 609{ 610 int status = QLA_SUCCESS; 611 uint32_t config = 0; 612 613 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); 614 615 status = qla4_83xx_get_port_config(ha, &config); 616 if (status != QLA_SUCCESS) 617 goto exit_post_loopback_config; 618 619 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: port config=%08X\n", __func__, 620 config)); 621 622 if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) 623 config &= ~ENABLE_INTERNAL_LOOPBACK; 624 else if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) 625 config &= ~ENABLE_EXTERNAL_LOOPBACK; 626 627 config |= ENABLE_DCBX; 628 629 DEBUG2(ql4_printk(KERN_INFO, ha, 630 "%s: Restore default port config=%08X\n", __func__, 631 config)); 632 633 ha->notify_idc_comp = 1; 634 if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) 635 ha->notify_link_up_comp = 1; 636 637 status = qla4_83xx_set_port_config(ha, &config); 638 if (status != QLA_SUCCESS) { 639 ql4_printk(KERN_INFO, ha, "%s: Scheduling adapter reset\n", 640 __func__); 641 set_bit(DPC_RESET_HA, &ha->dpc_flags); 642 clear_bit(AF_LOOPBACK, &ha->flags); 643 goto exit_post_loopback_config; 644 } 645 646exit_post_loopback_config: 647 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, 648 STATUS(status))); 649 return status; 650} 651 652static void qla4xxx_execute_diag_loopback_cmd(struct bsg_job *bsg_job) 653{ 654 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 655 struct scsi_qla_host *ha = to_qla_host(host); 656 struct iscsi_bsg_request *bsg_req = bsg_job->request; 657 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 658 uint8_t *rsp_ptr = NULL; 659 uint32_t mbox_cmd[MBOX_REG_COUNT]; 660 uint32_t mbox_sts[MBOX_REG_COUNT]; 661 int wait_for_link = 1; 662 int status = QLA_ERROR; 663 664 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); 665 666 bsg_reply->reply_payload_rcv_len = 0; 667 668 if (test_bit(AF_LOOPBACK, &ha->flags)) { 669 ql4_printk(KERN_INFO, ha, "%s: Loopback Diagnostics already in progress. Invalid Request\n", 670 __func__); 671 bsg_reply->result = DID_ERROR << 16; 672 goto exit_loopback_cmd; 673 } 674 675 if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 676 ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", 677 __func__); 678 bsg_reply->result = DID_ERROR << 16; 679 goto exit_loopback_cmd; 680 } 681 682 memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], 683 sizeof(uint32_t) * MBOX_REG_COUNT); 684 685 if (is_qla8032(ha) || is_qla8042(ha)) { 686 status = qla4_83xx_pre_loopback_config(ha, mbox_cmd); 687 if (status != QLA_SUCCESS) { 688 bsg_reply->result = DID_ERROR << 16; 689 goto exit_loopback_cmd; 690 } 691 692 status = qla4_83xx_wait_for_loopback_config_comp(ha, 693 wait_for_link); 694 if (status != QLA_SUCCESS) { 695 bsg_reply->result = DID_TIME_OUT << 16; 696 goto restore; 697 } 698 } 699 700 DEBUG2(ql4_printk(KERN_INFO, ha, 701 "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", 702 __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], 703 mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], 704 mbox_cmd[7])); 705 706 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], 707 &mbox_sts[0]); 708 709 if (status == QLA_SUCCESS) 710 bsg_reply->result = DID_OK << 16; 711 else 712 bsg_reply->result = DID_ERROR << 16; 713 714 DEBUG2(ql4_printk(KERN_INFO, ha, 715 "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", 716 __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], 717 mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], 718 mbox_sts[7])); 719 720 /* Send mbox_sts to application */ 721 bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); 722 rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); 723 memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); 724restore: 725 if (is_qla8032(ha) || is_qla8042(ha)) { 726 status = qla4_83xx_post_loopback_config(ha, mbox_cmd); 727 if (status != QLA_SUCCESS) { 728 bsg_reply->result = DID_ERROR << 16; 729 goto exit_loopback_cmd; 730 } 731 732 /* for pre_loopback_config() wait for LINK UP only 733 * if PHY LINK is UP */ 734 if (!(ha->addl_fw_state & FW_ADDSTATE_LINK_UP)) 735 wait_for_link = 0; 736 737 status = qla4_83xx_wait_for_loopback_config_comp(ha, 738 wait_for_link); 739 if (status != QLA_SUCCESS) { 740 bsg_reply->result = DID_TIME_OUT << 16; 741 goto exit_loopback_cmd; 742 } 743 } 744exit_loopback_cmd: 745 DEBUG2(ql4_printk(KERN_INFO, ha, 746 "%s: bsg_reply->result = x%x, status = %s\n", 747 __func__, bsg_reply->result, STATUS(status))); 748 bsg_job_done(bsg_job, bsg_reply->result, 749 bsg_reply->reply_payload_rcv_len); 750} 751 752static int qla4xxx_execute_diag_test(struct bsg_job *bsg_job) 753{ 754 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 755 struct scsi_qla_host *ha = to_qla_host(host); 756 struct iscsi_bsg_request *bsg_req = bsg_job->request; 757 uint32_t diag_cmd; 758 int rval = -EINVAL; 759 760 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); 761 762 diag_cmd = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 763 if (diag_cmd == MBOX_CMD_DIAG_TEST) { 764 switch (bsg_req->rqst_data.h_vendor.vendor_cmd[2]) { 765 case QL_DIAG_CMD_TEST_DDR_SIZE: 766 case QL_DIAG_CMD_TEST_DDR_RW: 767 case QL_DIAG_CMD_TEST_ONCHIP_MEM_RW: 768 case QL_DIAG_CMD_TEST_NVRAM: 769 case QL_DIAG_CMD_TEST_FLASH_ROM: 770 case QL_DIAG_CMD_TEST_DMA_XFER: 771 case QL_DIAG_CMD_SELF_DDR_RW: 772 case QL_DIAG_CMD_SELF_ONCHIP_MEM_RW: 773 /* Execute diag test for adapter RAM/FLASH */ 774 ql4xxx_execute_diag_cmd(bsg_job); 775 /* Always return success as we want to sent bsg_reply 776 * to Application */ 777 rval = QLA_SUCCESS; 778 break; 779 780 case QL_DIAG_CMD_TEST_INT_LOOPBACK: 781 case QL_DIAG_CMD_TEST_EXT_LOOPBACK: 782 /* Execute diag test for Network */ 783 qla4xxx_execute_diag_loopback_cmd(bsg_job); 784 /* Always return success as we want to sent bsg_reply 785 * to Application */ 786 rval = QLA_SUCCESS; 787 break; 788 default: 789 ql4_printk(KERN_ERR, ha, "%s: Invalid diag test: 0x%x\n", 790 __func__, 791 bsg_req->rqst_data.h_vendor.vendor_cmd[2]); 792 } 793 } else if ((diag_cmd == MBOX_CMD_SET_LED_CONFIG) || 794 (diag_cmd == MBOX_CMD_GET_LED_CONFIG)) { 795 ql4xxx_execute_diag_cmd(bsg_job); 796 rval = QLA_SUCCESS; 797 } else { 798 ql4_printk(KERN_ERR, ha, "%s: Invalid diag cmd: 0x%x\n", 799 __func__, diag_cmd); 800 } 801 802 return rval; 803} 804 805/** 806 * qla4xxx_process_vendor_specific - handle vendor specific bsg request 807 * @bsg_job: iscsi_bsg_job to handle 808 **/ 809int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) 810{ 811 struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 812 struct iscsi_bsg_request *bsg_req = bsg_job->request; 813 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 814 struct scsi_qla_host *ha = to_qla_host(host); 815 816 switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { 817 case QLISCSI_VND_READ_FLASH: 818 return qla4xxx_read_flash(bsg_job); 819 820 case QLISCSI_VND_UPDATE_FLASH: 821 return qla4xxx_update_flash(bsg_job); 822 823 case QLISCSI_VND_GET_ACB_STATE: 824 return qla4xxx_get_acb_state(bsg_job); 825 826 case QLISCSI_VND_READ_NVRAM: 827 return qla4xxx_read_nvram(bsg_job); 828 829 case QLISCSI_VND_UPDATE_NVRAM: 830 return qla4xxx_update_nvram(bsg_job); 831 832 case QLISCSI_VND_RESTORE_DEFAULTS: 833 return qla4xxx_restore_defaults(bsg_job); 834 835 case QLISCSI_VND_GET_ACB: 836 return qla4xxx_bsg_get_acb(bsg_job); 837 838 case QLISCSI_VND_DIAG_TEST: 839 return qla4xxx_execute_diag_test(bsg_job); 840 841 default: 842 ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " 843 "0x%x\n", __func__, bsg_req->msgcode); 844 bsg_reply->result = (DID_ERROR << 16); 845 bsg_reply->reply_payload_rcv_len = 0; 846 bsg_job_done(bsg_job, bsg_reply->result, 847 bsg_reply->reply_payload_rcv_len); 848 return -ENOSYS; 849 } 850} 851 852/** 853 * qla4xxx_bsg_request - handle bsg request from ISCSI transport 854 * @bsg_job: iscsi_bsg_job to handle 855 */ 856int qla4xxx_bsg_request(struct bsg_job *bsg_job) 857{ 858 struct iscsi_bsg_request *bsg_req = bsg_job->request; 859 struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 860 struct scsi_qla_host *ha = to_qla_host(host); 861 862 switch (bsg_req->msgcode) { 863 case ISCSI_BSG_HST_VENDOR: 864 return qla4xxx_process_vendor_specific(bsg_job); 865 866 default: 867 ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n", 868 __func__, bsg_req->msgcode); 869 } 870 871 return -ENOSYS; 872}