diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 140 |
1 files changed, 128 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index acca898ce0a2..a6bb8d0ecf13 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -379,12 +379,17 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
379 | static int | 379 | static int |
380 | qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | 380 | qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) |
381 | { | 381 | { |
382 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 382 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
383 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 383 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
384 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | 384 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); |
385 | srb_t *sp; | 385 | srb_t *sp; |
386 | int rval; | 386 | int rval; |
387 | 387 | ||
388 | if (unlikely(pci_channel_offline(ha->pdev))) { | ||
389 | cmd->result = DID_REQUEUE << 16; | ||
390 | goto qc_fail_command; | ||
391 | } | ||
392 | |||
388 | rval = fc_remote_port_chkready(rport); | 393 | rval = fc_remote_port_chkready(rport); |
389 | if (rval) { | 394 | if (rval) { |
390 | cmd->result = rval; | 395 | cmd->result = rval; |
@@ -440,13 +445,18 @@ qc_fail_command: | |||
440 | static int | 445 | static int |
441 | qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | 446 | qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) |
442 | { | 447 | { |
443 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 448 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
444 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 449 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
445 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | 450 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); |
446 | srb_t *sp; | 451 | srb_t *sp; |
447 | int rval; | 452 | int rval; |
448 | scsi_qla_host_t *pha = to_qla_parent(ha); | 453 | scsi_qla_host_t *pha = to_qla_parent(ha); |
449 | 454 | ||
455 | if (unlikely(pci_channel_offline(ha->pdev))) { | ||
456 | cmd->result = DID_REQUEUE << 16; | ||
457 | goto qc24_fail_command; | ||
458 | } | ||
459 | |||
450 | rval = fc_remote_port_chkready(rport); | 460 | rval = fc_remote_port_chkready(rport); |
451 | if (rval) { | 461 | if (rval) { |
452 | cmd->result = rval; | 462 | cmd->result = rval; |
@@ -653,7 +663,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) | |||
653 | static int | 663 | static int |
654 | qla2xxx_eh_abort(struct scsi_cmnd *cmd) | 664 | qla2xxx_eh_abort(struct scsi_cmnd *cmd) |
655 | { | 665 | { |
656 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 666 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
657 | srb_t *sp; | 667 | srb_t *sp; |
658 | int ret, i; | 668 | int ret, i; |
659 | unsigned int id, lun; | 669 | unsigned int id, lun; |
@@ -793,7 +803,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
793 | static int | 803 | static int |
794 | qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | 804 | qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) |
795 | { | 805 | { |
796 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 806 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
797 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 807 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
798 | int ret = FAILED; | 808 | int ret = FAILED; |
799 | unsigned int id, lun; | 809 | unsigned int id, lun; |
@@ -922,7 +932,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) | |||
922 | static int | 932 | static int |
923 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | 933 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) |
924 | { | 934 | { |
925 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 935 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
926 | scsi_qla_host_t *pha = to_qla_parent(ha); | 936 | scsi_qla_host_t *pha = to_qla_parent(ha); |
927 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 937 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
928 | int ret = FAILED; | 938 | int ret = FAILED; |
@@ -982,7 +992,7 @@ eh_bus_reset_done: | |||
982 | static int | 992 | static int |
983 | qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | 993 | qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) |
984 | { | 994 | { |
985 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 995 | scsi_qla_host_t *ha = shost_priv(cmd->device->host); |
986 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 996 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
987 | int ret = FAILED; | 997 | int ret = FAILED; |
988 | unsigned int id, lun; | 998 | unsigned int id, lun; |
@@ -1132,7 +1142,7 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) | |||
1132 | static int | 1142 | static int |
1133 | qla2xxx_slave_configure(struct scsi_device *sdev) | 1143 | qla2xxx_slave_configure(struct scsi_device *sdev) |
1134 | { | 1144 | { |
1135 | scsi_qla_host_t *ha = to_qla_host(sdev->host); | 1145 | scsi_qla_host_t *ha = shost_priv(sdev->host); |
1136 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); | 1146 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); |
1137 | 1147 | ||
1138 | if (sdev->tagged_supported) | 1148 | if (sdev->tagged_supported) |
@@ -1384,7 +1394,7 @@ static struct isp_operations qla25xx_isp_ops = { | |||
1384 | .beacon_on = qla24xx_beacon_on, | 1394 | .beacon_on = qla24xx_beacon_on, |
1385 | .beacon_off = qla24xx_beacon_off, | 1395 | .beacon_off = qla24xx_beacon_off, |
1386 | .beacon_blink = qla24xx_beacon_blink, | 1396 | .beacon_blink = qla24xx_beacon_blink, |
1387 | .read_optrom = qla24xx_read_optrom_data, | 1397 | .read_optrom = qla25xx_read_optrom_data, |
1388 | .write_optrom = qla24xx_write_optrom_data, | 1398 | .write_optrom = qla24xx_write_optrom_data, |
1389 | .get_flash_version = qla24xx_get_flash_version, | 1399 | .get_flash_version = qla24xx_get_flash_version, |
1390 | }; | 1400 | }; |
@@ -1533,7 +1543,7 @@ iospace_error_exit: | |||
1533 | static void | 1543 | static void |
1534 | qla2xxx_scan_start(struct Scsi_Host *shost) | 1544 | qla2xxx_scan_start(struct Scsi_Host *shost) |
1535 | { | 1545 | { |
1536 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; | 1546 | scsi_qla_host_t *ha = shost_priv(shost); |
1537 | 1547 | ||
1538 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | 1548 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); |
1539 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 1549 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
@@ -1543,7 +1553,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) | |||
1543 | static int | 1553 | static int |
1544 | qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) | 1554 | qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) |
1545 | { | 1555 | { |
1546 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; | 1556 | scsi_qla_host_t *ha = shost_priv(shost); |
1547 | 1557 | ||
1548 | if (!ha->host) | 1558 | if (!ha->host) |
1549 | return 1; | 1559 | return 1; |
@@ -1571,6 +1581,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1571 | if (pci_enable_device(pdev)) | 1581 | if (pci_enable_device(pdev)) |
1572 | goto probe_out; | 1582 | goto probe_out; |
1573 | 1583 | ||
1584 | if (pci_find_aer_capability(pdev)) | ||
1585 | if (pci_enable_pcie_error_reporting(pdev)) | ||
1586 | goto probe_out; | ||
1587 | |||
1574 | sht = &qla2x00_driver_template; | 1588 | sht = &qla2x00_driver_template; |
1575 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || | 1589 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || |
1576 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || | 1590 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || |
@@ -1586,7 +1600,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1586 | } | 1600 | } |
1587 | 1601 | ||
1588 | /* Clear our data area */ | 1602 | /* Clear our data area */ |
1589 | ha = (scsi_qla_host_t *)host->hostdata; | 1603 | ha = shost_priv(host); |
1590 | memset(ha, 0, sizeof(scsi_qla_host_t)); | 1604 | memset(ha, 0, sizeof(scsi_qla_host_t)); |
1591 | 1605 | ||
1592 | ha->pdev = pdev; | 1606 | ha->pdev = pdev; |
@@ -2423,7 +2437,6 @@ qla2x00_do_dpc(void *data) | |||
2423 | if (atomic_read(&fcport->state) != FCS_ONLINE && | 2437 | if (atomic_read(&fcport->state) != FCS_ONLINE && |
2424 | fcport->login_retry) { | 2438 | fcport->login_retry) { |
2425 | 2439 | ||
2426 | fcport->login_retry--; | ||
2427 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 2440 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
2428 | if (fcport->flags & | 2441 | if (fcport->flags & |
2429 | FCF_TAPE_PRESENT) | 2442 | FCF_TAPE_PRESENT) |
@@ -2439,6 +2452,7 @@ qla2x00_do_dpc(void *data) | |||
2439 | qla2x00_local_device_login( | 2452 | qla2x00_local_device_login( |
2440 | ha, fcport); | 2453 | ha, fcport); |
2441 | 2454 | ||
2455 | fcport->login_retry--; | ||
2442 | if (status == QLA_SUCCESS) { | 2456 | if (status == QLA_SUCCESS) { |
2443 | fcport->old_loop_id = fcport->loop_id; | 2457 | fcport->old_loop_id = fcport->loop_id; |
2444 | 2458 | ||
@@ -2456,6 +2470,8 @@ qla2x00_do_dpc(void *data) | |||
2456 | } else { | 2470 | } else { |
2457 | fcport->login_retry = 0; | 2471 | fcport->login_retry = 0; |
2458 | } | 2472 | } |
2473 | if (fcport->login_retry == 0) | ||
2474 | fcport->loop_id = FC_NO_LOOP_ID; | ||
2459 | } | 2475 | } |
2460 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) | 2476 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) |
2461 | break; | 2477 | break; |
@@ -2814,6 +2830,105 @@ qla2x00_release_firmware(void) | |||
2814 | up(&qla_fw_lock); | 2830 | up(&qla_fw_lock); |
2815 | } | 2831 | } |
2816 | 2832 | ||
2833 | static pci_ers_result_t | ||
2834 | qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | ||
2835 | { | ||
2836 | switch (state) { | ||
2837 | case pci_channel_io_normal: | ||
2838 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
2839 | case pci_channel_io_frozen: | ||
2840 | pci_disable_device(pdev); | ||
2841 | return PCI_ERS_RESULT_NEED_RESET; | ||
2842 | case pci_channel_io_perm_failure: | ||
2843 | qla2x00_remove_one(pdev); | ||
2844 | return PCI_ERS_RESULT_DISCONNECT; | ||
2845 | } | ||
2846 | return PCI_ERS_RESULT_NEED_RESET; | ||
2847 | } | ||
2848 | |||
2849 | static pci_ers_result_t | ||
2850 | qla2xxx_pci_mmio_enabled(struct pci_dev *pdev) | ||
2851 | { | ||
2852 | int risc_paused = 0; | ||
2853 | uint32_t stat; | ||
2854 | unsigned long flags; | ||
2855 | scsi_qla_host_t *ha = pci_get_drvdata(pdev); | ||
2856 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
2857 | struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; | ||
2858 | |||
2859 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2860 | if (IS_QLA2100(ha) || IS_QLA2200(ha)){ | ||
2861 | stat = RD_REG_DWORD(®->hccr); | ||
2862 | if (stat & HCCR_RISC_PAUSE) | ||
2863 | risc_paused = 1; | ||
2864 | } else if (IS_QLA23XX(ha)) { | ||
2865 | stat = RD_REG_DWORD(®->u.isp2300.host_status); | ||
2866 | if (stat & HSR_RISC_PAUSED) | ||
2867 | risc_paused = 1; | ||
2868 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
2869 | stat = RD_REG_DWORD(®24->host_status); | ||
2870 | if (stat & HSRX_RISC_PAUSED) | ||
2871 | risc_paused = 1; | ||
2872 | } | ||
2873 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2874 | |||
2875 | if (risc_paused) { | ||
2876 | qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, " | ||
2877 | "Dumping firmware!\n"); | ||
2878 | ha->isp_ops->fw_dump(ha, 0); | ||
2879 | |||
2880 | return PCI_ERS_RESULT_NEED_RESET; | ||
2881 | } else | ||
2882 | return PCI_ERS_RESULT_RECOVERED; | ||
2883 | } | ||
2884 | |||
2885 | static pci_ers_result_t | ||
2886 | qla2xxx_pci_slot_reset(struct pci_dev *pdev) | ||
2887 | { | ||
2888 | pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; | ||
2889 | scsi_qla_host_t *ha = pci_get_drvdata(pdev); | ||
2890 | |||
2891 | if (pci_enable_device(pdev)) { | ||
2892 | qla_printk(KERN_WARNING, ha, | ||
2893 | "Can't re-enable PCI device after reset.\n"); | ||
2894 | |||
2895 | return ret; | ||
2896 | } | ||
2897 | pci_set_master(pdev); | ||
2898 | |||
2899 | if (ha->isp_ops->pci_config(ha)) | ||
2900 | return ret; | ||
2901 | |||
2902 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | ||
2903 | if (qla2x00_abort_isp(ha)== QLA_SUCCESS) | ||
2904 | ret = PCI_ERS_RESULT_RECOVERED; | ||
2905 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | ||
2906 | |||
2907 | return ret; | ||
2908 | } | ||
2909 | |||
2910 | static void | ||
2911 | qla2xxx_pci_resume(struct pci_dev *pdev) | ||
2912 | { | ||
2913 | scsi_qla_host_t *ha = pci_get_drvdata(pdev); | ||
2914 | int ret; | ||
2915 | |||
2916 | ret = qla2x00_wait_for_hba_online(ha); | ||
2917 | if (ret != QLA_SUCCESS) { | ||
2918 | qla_printk(KERN_ERR, ha, | ||
2919 | "the device failed to resume I/O " | ||
2920 | "from slot/link_reset"); | ||
2921 | } | ||
2922 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
2923 | } | ||
2924 | |||
2925 | static struct pci_error_handlers qla2xxx_err_handler = { | ||
2926 | .error_detected = qla2xxx_pci_error_detected, | ||
2927 | .mmio_enabled = qla2xxx_pci_mmio_enabled, | ||
2928 | .slot_reset = qla2xxx_pci_slot_reset, | ||
2929 | .resume = qla2xxx_pci_resume, | ||
2930 | }; | ||
2931 | |||
2817 | static struct pci_device_id qla2xxx_pci_tbl[] = { | 2932 | static struct pci_device_id qla2xxx_pci_tbl[] = { |
2818 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, | 2933 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, |
2819 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, | 2934 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, |
@@ -2839,6 +2954,7 @@ static struct pci_driver qla2xxx_pci_driver = { | |||
2839 | .id_table = qla2xxx_pci_tbl, | 2954 | .id_table = qla2xxx_pci_tbl, |
2840 | .probe = qla2x00_probe_one, | 2955 | .probe = qla2x00_probe_one, |
2841 | .remove = __devexit_p(qla2x00_remove_one), | 2956 | .remove = __devexit_p(qla2x00_remove_one), |
2957 | .err_handler = &qla2xxx_err_handler, | ||
2842 | }; | 2958 | }; |
2843 | 2959 | ||
2844 | /** | 2960 | /** |