diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 295 |
1 files changed, 285 insertions, 10 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ee9d4015243..b09993a0657 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -96,7 +96,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, | |||
96 | if (!capable(CAP_SYS_ADMIN)) | 96 | if (!capable(CAP_SYS_ADMIN)) |
97 | return 0; | 97 | return 0; |
98 | 98 | ||
99 | /* Read NVRAM data from cache. */ | 99 | if (IS_NOCACHE_VPD_TYPE(ha)) |
100 | ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_nvram << 2, | ||
101 | ha->nvram_size); | ||
100 | return memory_read_from_buffer(buf, count, &off, ha->nvram, | 102 | return memory_read_from_buffer(buf, count, &off, ha->nvram, |
101 | ha->nvram_size); | 103 | ha->nvram_size); |
102 | } | 104 | } |
@@ -111,7 +113,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
111 | struct qla_hw_data *ha = vha->hw; | 113 | struct qla_hw_data *ha = vha->hw; |
112 | uint16_t cnt; | 114 | uint16_t cnt; |
113 | 115 | ||
114 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) | 116 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size || |
117 | !ha->isp_ops->write_nvram) | ||
115 | return 0; | 118 | return 0; |
116 | 119 | ||
117 | /* Checksum NVRAM. */ | 120 | /* Checksum NVRAM. */ |
@@ -137,12 +140,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
137 | *iter = chksum; | 140 | *iter = chksum; |
138 | } | 141 | } |
139 | 142 | ||
143 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
144 | qla_printk(KERN_WARNING, ha, | ||
145 | "HBA not online, failing NVRAM update.\n"); | ||
146 | return -EAGAIN; | ||
147 | } | ||
148 | |||
140 | /* Write NVRAM. */ | 149 | /* Write NVRAM. */ |
141 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); | 150 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); |
142 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, | 151 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, |
143 | count); | 152 | count); |
144 | 153 | ||
154 | /* NVRAM settings take effect immediately. */ | ||
145 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 155 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
156 | qla2xxx_wake_dpc(vha); | ||
157 | qla2x00_wait_for_chip_reset(vha); | ||
146 | 158 | ||
147 | return (count); | 159 | return (count); |
148 | } | 160 | } |
@@ -330,6 +342,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
330 | if (ha->optrom_state != QLA_SWRITING) | 342 | if (ha->optrom_state != QLA_SWRITING) |
331 | break; | 343 | break; |
332 | 344 | ||
345 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
346 | qla_printk(KERN_WARNING, ha, | ||
347 | "HBA not online, failing flash update.\n"); | ||
348 | return -EAGAIN; | ||
349 | } | ||
350 | |||
333 | DEBUG2(qla_printk(KERN_INFO, ha, | 351 | DEBUG2(qla_printk(KERN_INFO, ha, |
334 | "Writing flash region -- 0x%x/0x%x.\n", | 352 | "Writing flash region -- 0x%x/0x%x.\n", |
335 | ha->optrom_region_start, ha->optrom_region_size)); | 353 | ha->optrom_region_start, ha->optrom_region_size)); |
@@ -364,7 +382,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, | |||
364 | if (!capable(CAP_SYS_ADMIN)) | 382 | if (!capable(CAP_SYS_ADMIN)) |
365 | return 0; | 383 | return 0; |
366 | 384 | ||
367 | /* Read NVRAM data from cache. */ | 385 | if (IS_NOCACHE_VPD_TYPE(ha)) |
386 | ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2, | ||
387 | ha->vpd_size); | ||
368 | return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); | 388 | return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); |
369 | } | 389 | } |
370 | 390 | ||
@@ -376,14 +396,35 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
376 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | 396 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, |
377 | struct device, kobj))); | 397 | struct device, kobj))); |
378 | struct qla_hw_data *ha = vha->hw; | 398 | struct qla_hw_data *ha = vha->hw; |
399 | uint8_t *tmp_data; | ||
379 | 400 | ||
380 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) | 401 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size || |
402 | !ha->isp_ops->write_nvram) | ||
381 | return 0; | 403 | return 0; |
382 | 404 | ||
405 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
406 | qla_printk(KERN_WARNING, ha, | ||
407 | "HBA not online, failing VPD update.\n"); | ||
408 | return -EAGAIN; | ||
409 | } | ||
410 | |||
383 | /* Write NVRAM. */ | 411 | /* Write NVRAM. */ |
384 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); | 412 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); |
385 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); | 413 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); |
386 | 414 | ||
415 | /* Update flash version information for 4Gb & above. */ | ||
416 | if (!IS_FWI2_CAPABLE(ha)) | ||
417 | goto done; | ||
418 | |||
419 | tmp_data = vmalloc(256); | ||
420 | if (!tmp_data) { | ||
421 | qla_printk(KERN_WARNING, ha, | ||
422 | "Unable to allocate memory for VPD information update.\n"); | ||
423 | goto done; | ||
424 | } | ||
425 | ha->isp_ops->get_flash_version(vha, tmp_data); | ||
426 | vfree(tmp_data); | ||
427 | done: | ||
387 | return count; | 428 | return count; |
388 | } | 429 | } |
389 | 430 | ||
@@ -458,6 +499,199 @@ static struct bin_attribute sysfs_sfp_attr = { | |||
458 | .read = qla2x00_sysfs_read_sfp, | 499 | .read = qla2x00_sysfs_read_sfp, |
459 | }; | 500 | }; |
460 | 501 | ||
502 | static ssize_t | ||
503 | qla2x00_sysfs_write_reset(struct kobject *kobj, | ||
504 | struct bin_attribute *bin_attr, | ||
505 | char *buf, loff_t off, size_t count) | ||
506 | { | ||
507 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
508 | struct device, kobj))); | ||
509 | struct qla_hw_data *ha = vha->hw; | ||
510 | int type; | ||
511 | |||
512 | if (off != 0) | ||
513 | return 0; | ||
514 | |||
515 | type = simple_strtol(buf, NULL, 10); | ||
516 | switch (type) { | ||
517 | case 0x2025c: | ||
518 | qla_printk(KERN_INFO, ha, | ||
519 | "Issuing ISP reset on (%ld).\n", vha->host_no); | ||
520 | |||
521 | scsi_block_requests(vha->host); | ||
522 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
523 | qla2xxx_wake_dpc(vha); | ||
524 | qla2x00_wait_for_chip_reset(vha); | ||
525 | scsi_unblock_requests(vha->host); | ||
526 | break; | ||
527 | case 0x2025d: | ||
528 | if (!IS_QLA81XX(ha)) | ||
529 | break; | ||
530 | |||
531 | qla_printk(KERN_INFO, ha, | ||
532 | "Issuing MPI reset on (%ld).\n", vha->host_no); | ||
533 | |||
534 | /* Make sure FC side is not in reset */ | ||
535 | qla2x00_wait_for_hba_online(vha); | ||
536 | |||
537 | /* Issue MPI reset */ | ||
538 | scsi_block_requests(vha->host); | ||
539 | if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS) | ||
540 | qla_printk(KERN_WARNING, ha, | ||
541 | "MPI reset failed on (%ld).\n", vha->host_no); | ||
542 | scsi_unblock_requests(vha->host); | ||
543 | break; | ||
544 | } | ||
545 | return count; | ||
546 | } | ||
547 | |||
548 | static struct bin_attribute sysfs_reset_attr = { | ||
549 | .attr = { | ||
550 | .name = "reset", | ||
551 | .mode = S_IWUSR, | ||
552 | }, | ||
553 | .size = 0, | ||
554 | .write = qla2x00_sysfs_write_reset, | ||
555 | }; | ||
556 | |||
557 | static ssize_t | ||
558 | qla2x00_sysfs_write_edc(struct kobject *kobj, | ||
559 | struct bin_attribute *bin_attr, | ||
560 | char *buf, loff_t off, size_t count) | ||
561 | { | ||
562 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
563 | struct device, kobj))); | ||
564 | struct qla_hw_data *ha = vha->hw; | ||
565 | uint16_t dev, adr, opt, len; | ||
566 | int rval; | ||
567 | |||
568 | ha->edc_data_len = 0; | ||
569 | |||
570 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8) | ||
571 | return 0; | ||
572 | |||
573 | if (!ha->edc_data) { | ||
574 | ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
575 | &ha->edc_data_dma); | ||
576 | if (!ha->edc_data) { | ||
577 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
578 | "Unable to allocate memory for EDC write.\n")); | ||
579 | return 0; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | dev = le16_to_cpup((void *)&buf[0]); | ||
584 | adr = le16_to_cpup((void *)&buf[2]); | ||
585 | opt = le16_to_cpup((void *)&buf[4]); | ||
586 | len = le16_to_cpup((void *)&buf[6]); | ||
587 | |||
588 | if (!(opt & BIT_0)) | ||
589 | if (len == 0 || len > DMA_POOL_SIZE || len > count - 8) | ||
590 | return -EINVAL; | ||
591 | |||
592 | memcpy(ha->edc_data, &buf[8], len); | ||
593 | |||
594 | rval = qla2x00_write_edc(vha, dev, adr, ha->edc_data_dma, | ||
595 | ha->edc_data, len, opt); | ||
596 | if (rval != QLA_SUCCESS) { | ||
597 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
598 | "Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n", | ||
599 | rval, dev, adr, opt, len, *buf)); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | return count; | ||
604 | } | ||
605 | |||
606 | static struct bin_attribute sysfs_edc_attr = { | ||
607 | .attr = { | ||
608 | .name = "edc", | ||
609 | .mode = S_IWUSR, | ||
610 | }, | ||
611 | .size = 0, | ||
612 | .write = qla2x00_sysfs_write_edc, | ||
613 | }; | ||
614 | |||
615 | static ssize_t | ||
616 | qla2x00_sysfs_write_edc_status(struct kobject *kobj, | ||
617 | struct bin_attribute *bin_attr, | ||
618 | char *buf, loff_t off, size_t count) | ||
619 | { | ||
620 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
621 | struct device, kobj))); | ||
622 | struct qla_hw_data *ha = vha->hw; | ||
623 | uint16_t dev, adr, opt, len; | ||
624 | int rval; | ||
625 | |||
626 | ha->edc_data_len = 0; | ||
627 | |||
628 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8) | ||
629 | return 0; | ||
630 | |||
631 | if (!ha->edc_data) { | ||
632 | ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
633 | &ha->edc_data_dma); | ||
634 | if (!ha->edc_data) { | ||
635 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
636 | "Unable to allocate memory for EDC status.\n")); | ||
637 | return 0; | ||
638 | } | ||
639 | } | ||
640 | |||
641 | dev = le16_to_cpup((void *)&buf[0]); | ||
642 | adr = le16_to_cpup((void *)&buf[2]); | ||
643 | opt = le16_to_cpup((void *)&buf[4]); | ||
644 | len = le16_to_cpup((void *)&buf[6]); | ||
645 | |||
646 | if (!(opt & BIT_0)) | ||
647 | if (len == 0 || len > DMA_POOL_SIZE) | ||
648 | return -EINVAL; | ||
649 | |||
650 | memset(ha->edc_data, 0, len); | ||
651 | rval = qla2x00_read_edc(vha, dev, adr, ha->edc_data_dma, | ||
652 | ha->edc_data, len, opt); | ||
653 | if (rval != QLA_SUCCESS) { | ||
654 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
655 | "Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n", | ||
656 | rval, dev, adr, opt, len)); | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | ha->edc_data_len = len; | ||
661 | |||
662 | return count; | ||
663 | } | ||
664 | |||
665 | static ssize_t | ||
666 | qla2x00_sysfs_read_edc_status(struct kobject *kobj, | ||
667 | struct bin_attribute *bin_attr, | ||
668 | char *buf, loff_t off, size_t count) | ||
669 | { | ||
670 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
671 | struct device, kobj))); | ||
672 | struct qla_hw_data *ha = vha->hw; | ||
673 | |||
674 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count == 0) | ||
675 | return 0; | ||
676 | |||
677 | if (!ha->edc_data || ha->edc_data_len == 0 || ha->edc_data_len > count) | ||
678 | return -EINVAL; | ||
679 | |||
680 | memcpy(buf, ha->edc_data, ha->edc_data_len); | ||
681 | |||
682 | return ha->edc_data_len; | ||
683 | } | ||
684 | |||
685 | static struct bin_attribute sysfs_edc_status_attr = { | ||
686 | .attr = { | ||
687 | .name = "edc_status", | ||
688 | .mode = S_IRUSR | S_IWUSR, | ||
689 | }, | ||
690 | .size = 0, | ||
691 | .write = qla2x00_sysfs_write_edc_status, | ||
692 | .read = qla2x00_sysfs_read_edc_status, | ||
693 | }; | ||
694 | |||
461 | static struct sysfs_entry { | 695 | static struct sysfs_entry { |
462 | char *name; | 696 | char *name; |
463 | struct bin_attribute *attr; | 697 | struct bin_attribute *attr; |
@@ -469,6 +703,9 @@ static struct sysfs_entry { | |||
469 | { "optrom_ctl", &sysfs_optrom_ctl_attr, }, | 703 | { "optrom_ctl", &sysfs_optrom_ctl_attr, }, |
470 | { "vpd", &sysfs_vpd_attr, 1 }, | 704 | { "vpd", &sysfs_vpd_attr, 1 }, |
471 | { "sfp", &sysfs_sfp_attr, 1 }, | 705 | { "sfp", &sysfs_sfp_attr, 1 }, |
706 | { "reset", &sysfs_reset_attr, }, | ||
707 | { "edc", &sysfs_edc_attr, 2 }, | ||
708 | { "edc_status", &sysfs_edc_status_attr, 2 }, | ||
472 | { NULL }, | 709 | { NULL }, |
473 | }; | 710 | }; |
474 | 711 | ||
@@ -482,6 +719,8 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) | |||
482 | for (iter = bin_file_entries; iter->name; iter++) { | 719 | for (iter = bin_file_entries; iter->name; iter++) { |
483 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw)) | 720 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw)) |
484 | continue; | 721 | continue; |
722 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) | ||
723 | continue; | ||
485 | 724 | ||
486 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, | 725 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, |
487 | iter->attr); | 726 | iter->attr); |
@@ -502,6 +741,8 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha) | |||
502 | for (iter = bin_file_entries; iter->name; iter++) { | 741 | for (iter = bin_file_entries; iter->name; iter++) { |
503 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) | 742 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) |
504 | continue; | 743 | continue; |
744 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) | ||
745 | continue; | ||
505 | 746 | ||
506 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | 747 | sysfs_remove_bin_file(&host->shost_gendev.kobj, |
507 | iter->attr); | 748 | iter->attr); |
@@ -818,9 +1059,33 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, | |||
818 | if (!IS_QLA81XX(ha)) | 1059 | if (!IS_QLA81XX(ha)) |
819 | return snprintf(buf, PAGE_SIZE, "\n"); | 1060 | return snprintf(buf, PAGE_SIZE, "\n"); |
820 | 1061 | ||
821 | return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x (%x)\n", | 1062 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", |
822 | ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2], | 1063 | ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2], |
823 | ha->mpi_version[3], ha->mpi_capabilities); | 1064 | ha->mpi_capabilities); |
1065 | } | ||
1066 | |||
1067 | static ssize_t | ||
1068 | qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr, | ||
1069 | char *buf) | ||
1070 | { | ||
1071 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1072 | struct qla_hw_data *ha = vha->hw; | ||
1073 | |||
1074 | if (!IS_QLA81XX(ha)) | ||
1075 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1076 | |||
1077 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", | ||
1078 | ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]); | ||
1079 | } | ||
1080 | |||
1081 | static ssize_t | ||
1082 | qla2x00_flash_block_size_show(struct device *dev, | ||
1083 | struct device_attribute *attr, char *buf) | ||
1084 | { | ||
1085 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1086 | struct qla_hw_data *ha = vha->hw; | ||
1087 | |||
1088 | return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size); | ||
824 | } | 1089 | } |
825 | 1090 | ||
826 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); | 1091 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); |
@@ -848,6 +1113,9 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, | |||
848 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, | 1113 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, |
849 | NULL); | 1114 | NULL); |
850 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); | 1115 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); |
1116 | static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); | ||
1117 | static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, | ||
1118 | NULL); | ||
851 | 1119 | ||
852 | struct device_attribute *qla2x00_host_attrs[] = { | 1120 | struct device_attribute *qla2x00_host_attrs[] = { |
853 | &dev_attr_driver_version, | 1121 | &dev_attr_driver_version, |
@@ -868,6 +1136,8 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
868 | &dev_attr_optrom_fw_version, | 1136 | &dev_attr_optrom_fw_version, |
869 | &dev_attr_total_isp_aborts, | 1137 | &dev_attr_total_isp_aborts, |
870 | &dev_attr_mpi_version, | 1138 | &dev_attr_mpi_version, |
1139 | &dev_attr_phy_version, | ||
1140 | &dev_attr_flash_block_size, | ||
871 | NULL, | 1141 | NULL, |
872 | }; | 1142 | }; |
873 | 1143 | ||
@@ -1012,7 +1282,10 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
1012 | if (!fcport) | 1282 | if (!fcport) |
1013 | return; | 1283 | return; |
1014 | 1284 | ||
1015 | qla2x00_abort_fcport_cmds(fcport); | 1285 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) |
1286 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); | ||
1287 | else | ||
1288 | qla2x00_abort_fcport_cmds(fcport); | ||
1016 | 1289 | ||
1017 | /* | 1290 | /* |
1018 | * Transport has effectively 'deleted' the rport, clear | 1291 | * Transport has effectively 'deleted' the rport, clear |
@@ -1032,16 +1305,18 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) | |||
1032 | if (!fcport) | 1305 | if (!fcport) |
1033 | return; | 1306 | return; |
1034 | 1307 | ||
1308 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { | ||
1309 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); | ||
1310 | return; | ||
1311 | } | ||
1035 | /* | 1312 | /* |
1036 | * At this point all fcport's software-states are cleared. Perform any | 1313 | * At this point all fcport's software-states are cleared. Perform any |
1037 | * final cleanup of firmware resources (PCBs and XCBs). | 1314 | * final cleanup of firmware resources (PCBs and XCBs). |
1038 | */ | 1315 | */ |
1039 | if (fcport->loop_id != FC_NO_LOOP_ID) { | 1316 | if (fcport->loop_id != FC_NO_LOOP_ID) |
1040 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, | 1317 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, |
1041 | fcport->loop_id, fcport->d_id.b.domain, | 1318 | fcport->loop_id, fcport->d_id.b.domain, |
1042 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 1319 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
1043 | fcport->loop_id = FC_NO_LOOP_ID; | ||
1044 | } | ||
1045 | 1320 | ||
1046 | qla2x00_abort_fcport_cmds(fcport); | 1321 | qla2x00_abort_fcport_cmds(fcport); |
1047 | } | 1322 | } |