diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 678 |
1 files changed, 522 insertions, 156 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 38b1d38afca5..64a1288e06b4 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -30,22 +30,29 @@ static struct kmem_cache *srb_cachep; | |||
30 | * Module parameter information and variables | 30 | * Module parameter information and variables |
31 | */ | 31 | */ |
32 | int ql4xdiscoverywait = 60; | 32 | int ql4xdiscoverywait = 60; |
33 | module_param(ql4xdiscoverywait, int, S_IRUGO | S_IRUSR); | 33 | module_param(ql4xdiscoverywait, int, S_IRUGO | S_IWUSR); |
34 | MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time"); | 34 | MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time"); |
35 | |||
35 | int ql4xdontresethba = 0; | 36 | int ql4xdontresethba = 0; |
36 | module_param(ql4xdontresethba, int, S_IRUGO | S_IRUSR); | 37 | module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); |
37 | MODULE_PARM_DESC(ql4xdontresethba, | 38 | MODULE_PARM_DESC(ql4xdontresethba, |
38 | "Dont reset the HBA when the driver gets 0x8002 AEN " | 39 | "Don't reset the HBA for driver recovery \n" |
39 | " default it will reset hba :0" | 40 | " 0 - It will reset HBA (Default)\n" |
40 | " set to 1 to avoid resetting HBA"); | 41 | " 1 - It will NOT reset HBA"); |
41 | 42 | ||
42 | int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ | 43 | int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ |
43 | module_param(ql4xextended_error_logging, int, S_IRUGO | S_IRUSR); | 44 | module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR); |
44 | MODULE_PARM_DESC(ql4xextended_error_logging, | 45 | MODULE_PARM_DESC(ql4xextended_error_logging, |
45 | "Option to enable extended error logging, " | 46 | "Option to enable extended error logging, " |
46 | "Default is 0 - no logging, 1 - debug logging"); | 47 | "Default is 0 - no logging, 1 - debug logging"); |
47 | 48 | ||
48 | int ql4_mod_unload = 0; | 49 | int ql4xenablemsix = 1; |
50 | module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR); | ||
51 | MODULE_PARM_DESC(ql4xenablemsix, | ||
52 | "Set to enable MSI or MSI-X interrupt mechanism.\n" | ||
53 | " 0 = enable INTx interrupt mechanism.\n" | ||
54 | " 1 = enable MSI-X interrupt mechanism (Default).\n" | ||
55 | " 2 = enable MSI interrupt mechanism."); | ||
49 | 56 | ||
50 | #define QL4_DEF_QDEPTH 32 | 57 | #define QL4_DEF_QDEPTH 32 |
51 | 58 | ||
@@ -83,6 +90,9 @@ static int qla4xxx_slave_configure(struct scsi_device *device); | |||
83 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); | 90 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); |
84 | static void qla4xxx_scan_start(struct Scsi_Host *shost); | 91 | static void qla4xxx_scan_start(struct Scsi_Host *shost); |
85 | 92 | ||
93 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = | ||
94 | QLA82XX_LEGACY_INTR_CONFIG; | ||
95 | |||
86 | static struct scsi_host_template qla4xxx_driver_template = { | 96 | static struct scsi_host_template qla4xxx_driver_template = { |
87 | .module = THIS_MODULE, | 97 | .module = THIS_MODULE, |
88 | .name = DRIVER_NAME, | 98 | .name = DRIVER_NAME, |
@@ -152,15 +162,12 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | |||
152 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | 162 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { |
153 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); | 163 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); |
154 | 164 | ||
155 | DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count " | 165 | DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " |
156 | "of (%d) secs exhausted, marking device DEAD.\n", | 166 | "of (%d) secs exhausted, marking device DEAD.\n", |
157 | ha->host_no, __func__, ddb_entry->fw_ddb_index, | 167 | ha->host_no, __func__, ddb_entry->fw_ddb_index, |
158 | ha->port_down_retry_count)); | 168 | ha->port_down_retry_count)); |
159 | 169 | ||
160 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc " | 170 | qla4xxx_wake_dpc(ha); |
161 | "flags = 0x%lx\n", | ||
162 | ha->host_no, __func__, ha->dpc_flags)); | ||
163 | queue_work(ha->dpc_thread, &ha->dpc_work); | ||
164 | } | 171 | } |
165 | } | 172 | } |
166 | 173 | ||
@@ -362,19 +369,37 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha) | |||
362 | * @ha: Pointer to host adapter structure. | 369 | * @ha: Pointer to host adapter structure. |
363 | * @ddb_entry: Pointer to device database entry | 370 | * @ddb_entry: Pointer to device database entry |
364 | * | 371 | * |
365 | * This routine marks a device missing and resets the relogin retry count. | 372 | * This routine marks a device missing and close connection. |
366 | **/ | 373 | **/ |
367 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, | 374 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, |
368 | struct ddb_entry *ddb_entry) | 375 | struct ddb_entry *ddb_entry) |
369 | { | 376 | { |
370 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); | 377 | if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) { |
371 | DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n", | 378 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); |
372 | ha->host_no, ddb_entry->bus, ddb_entry->target, | 379 | DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n", |
373 | ddb_entry->fw_ddb_index)); | 380 | ha->host_no, ddb_entry->fw_ddb_index)); |
381 | } else | ||
382 | DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no, | ||
383 | ddb_entry->fw_ddb_index)) | ||
384 | |||
374 | iscsi_block_session(ddb_entry->sess); | 385 | iscsi_block_session(ddb_entry->sess); |
375 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); | 386 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); |
376 | } | 387 | } |
377 | 388 | ||
389 | /** | ||
390 | * qla4xxx_mark_all_devices_missing - mark all devices as missing. | ||
391 | * @ha: Pointer to host adapter structure. | ||
392 | * | ||
393 | * This routine marks a device missing and resets the relogin retry count. | ||
394 | **/ | ||
395 | void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) | ||
396 | { | ||
397 | struct ddb_entry *ddb_entry, *ddbtemp; | ||
398 | list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { | ||
399 | qla4xxx_mark_device_missing(ha, ddb_entry); | ||
400 | } | ||
401 | } | ||
402 | |||
378 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | 403 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, |
379 | struct ddb_entry *ddb_entry, | 404 | struct ddb_entry *ddb_entry, |
380 | struct scsi_cmnd *cmd, | 405 | struct scsi_cmnd *cmd, |
@@ -463,7 +488,13 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, | |||
463 | return SCSI_MLQUEUE_TARGET_BUSY; | 488 | return SCSI_MLQUEUE_TARGET_BUSY; |
464 | } | 489 | } |
465 | 490 | ||
466 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | 491 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
492 | test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | ||
493 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
494 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
495 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
496 | !test_bit(AF_ONLINE, &ha->flags) || | ||
497 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) | ||
467 | goto qc_host_busy; | 498 | goto qc_host_busy; |
468 | 499 | ||
469 | spin_unlock_irq(ha->host->host_lock); | 500 | spin_unlock_irq(ha->host->host_lock); |
@@ -524,7 +555,15 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
524 | ha->srb_mempool = NULL; | 555 | ha->srb_mempool = NULL; |
525 | 556 | ||
526 | /* release io space registers */ | 557 | /* release io space registers */ |
527 | if (ha->reg) | 558 | if (is_qla8022(ha)) { |
559 | if (ha->nx_pcibase) | ||
560 | iounmap( | ||
561 | (struct device_reg_82xx __iomem *)ha->nx_pcibase); | ||
562 | |||
563 | if (ha->nx_db_wr_ptr) | ||
564 | iounmap( | ||
565 | (struct device_reg_82xx __iomem *)ha->nx_db_wr_ptr); | ||
566 | } else if (ha->reg) | ||
528 | iounmap(ha->reg); | 567 | iounmap(ha->reg); |
529 | pci_release_regions(ha->pdev); | 568 | pci_release_regions(ha->pdev); |
530 | } | 569 | } |
@@ -600,6 +639,74 @@ mem_alloc_error_exit: | |||
600 | } | 639 | } |
601 | 640 | ||
602 | /** | 641 | /** |
642 | * qla4_8xxx_check_fw_alive - Check firmware health | ||
643 | * @ha: Pointer to host adapter structure. | ||
644 | * | ||
645 | * Context: Interrupt | ||
646 | **/ | ||
647 | static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | ||
648 | { | ||
649 | uint32_t fw_heartbeat_counter, halt_status; | ||
650 | |||
651 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
652 | |||
653 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | ||
654 | ha->seconds_since_last_heartbeat++; | ||
655 | /* FW not alive after 2 seconds */ | ||
656 | if (ha->seconds_since_last_heartbeat == 2) { | ||
657 | ha->seconds_since_last_heartbeat = 0; | ||
658 | halt_status = qla4_8xxx_rd_32(ha, | ||
659 | QLA82XX_PEG_HALT_STATUS1); | ||
660 | /* Since we cannot change dev_state in interrupt | ||
661 | * context, set appropriate DPC flag then wakeup | ||
662 | * DPC */ | ||
663 | if (halt_status & HALT_STATUS_UNRECOVERABLE) | ||
664 | set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); | ||
665 | else { | ||
666 | printk("scsi%ld: %s: detect abort needed!\n", | ||
667 | ha->host_no, __func__); | ||
668 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
669 | } | ||
670 | qla4xxx_wake_dpc(ha); | ||
671 | } | ||
672 | } | ||
673 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * qla4_8xxx_watchdog - Poll dev state | ||
678 | * @ha: Pointer to host adapter structure. | ||
679 | * | ||
680 | * Context: Interrupt | ||
681 | **/ | ||
682 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | ||
683 | { | ||
684 | uint32_t dev_state; | ||
685 | |||
686 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
687 | |||
688 | /* don't poll if reset is going on */ | ||
689 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) { | ||
690 | if (dev_state == QLA82XX_DEV_NEED_RESET && | ||
691 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
692 | printk("scsi%ld: %s: HW State: NEED RESET!\n", | ||
693 | ha->host_no, __func__); | ||
694 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
695 | qla4xxx_wake_dpc(ha); | ||
696 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | ||
697 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
698 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", | ||
699 | ha->host_no, __func__); | ||
700 | set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); | ||
701 | qla4xxx_wake_dpc(ha); | ||
702 | } else { | ||
703 | /* Check firmware health */ | ||
704 | qla4_8xxx_check_fw_alive(ha); | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | |||
709 | /** | ||
603 | * qla4xxx_timer - checks every second for work to do. | 710 | * qla4xxx_timer - checks every second for work to do. |
604 | * @ha: Pointer to host adapter structure. | 711 | * @ha: Pointer to host adapter structure. |
605 | **/ | 712 | **/ |
@@ -608,6 +715,16 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
608 | struct ddb_entry *ddb_entry, *dtemp; | 715 | struct ddb_entry *ddb_entry, *dtemp; |
609 | int start_dpc = 0; | 716 | int start_dpc = 0; |
610 | 717 | ||
718 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | ||
719 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | ||
720 | __func__)); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | if (is_qla8022(ha)) { | ||
725 | qla4_8xxx_watchdog(ha); | ||
726 | } | ||
727 | |||
611 | /* Search for relogin's to time-out and port down retry. */ | 728 | /* Search for relogin's to time-out and port down retry. */ |
612 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { | 729 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { |
613 | /* Count down time between sending relogins */ | 730 | /* Count down time between sending relogins */ |
@@ -624,7 +741,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
624 | set_bit(DPC_RELOGIN_DEVICE, | 741 | set_bit(DPC_RELOGIN_DEVICE, |
625 | &ha->dpc_flags); | 742 | &ha->dpc_flags); |
626 | set_bit(DF_RELOGIN, &ddb_entry->flags); | 743 | set_bit(DF_RELOGIN, &ddb_entry->flags); |
627 | DEBUG2(printk("scsi%ld: %s: index [%d]" | 744 | DEBUG2(printk("scsi%ld: %s: ddb [%d]" |
628 | " login device\n", | 745 | " login device\n", |
629 | ha->host_no, __func__, | 746 | ha->host_no, __func__, |
630 | ddb_entry->fw_ddb_index)); | 747 | ddb_entry->fw_ddb_index)); |
@@ -647,7 +764,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
647 | DDB_DS_SESSION_FAILED) { | 764 | DDB_DS_SESSION_FAILED) { |
648 | /* Reset retry relogin timer */ | 765 | /* Reset retry relogin timer */ |
649 | atomic_inc(&ddb_entry->relogin_retry_count); | 766 | atomic_inc(&ddb_entry->relogin_retry_count); |
650 | DEBUG2(printk("scsi%ld: index[%d] relogin" | 767 | DEBUG2(printk("scsi%ld: ddb [%d] relogin" |
651 | " timed out-retrying" | 768 | " timed out-retrying" |
652 | " relogin (%d)\n", | 769 | " relogin (%d)\n", |
653 | ha->host_no, | 770 | ha->host_no, |
@@ -656,7 +773,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
656 | relogin_retry_count)) | 773 | relogin_retry_count)) |
657 | ); | 774 | ); |
658 | start_dpc++; | 775 | start_dpc++; |
659 | DEBUG(printk("scsi%ld:%d:%d: index [%d] " | 776 | DEBUG(printk("scsi%ld:%d:%d: ddb [%d] " |
660 | "initate relogin after" | 777 | "initate relogin after" |
661 | " %d seconds\n", | 778 | " %d seconds\n", |
662 | ha->host_no, ddb_entry->bus, | 779 | ha->host_no, ddb_entry->bus, |
@@ -671,31 +788,35 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
671 | } | 788 | } |
672 | } | 789 | } |
673 | 790 | ||
674 | /* Check for heartbeat interval. */ | 791 | if (!is_qla8022(ha)) { |
675 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && | 792 | /* Check for heartbeat interval. */ |
676 | ha->heartbeat_interval != 0) { | 793 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && |
677 | ha->seconds_since_last_heartbeat++; | 794 | ha->heartbeat_interval != 0) { |
678 | if (ha->seconds_since_last_heartbeat > | 795 | ha->seconds_since_last_heartbeat++; |
679 | ha->heartbeat_interval + 2) | 796 | if (ha->seconds_since_last_heartbeat > |
680 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 797 | ha->heartbeat_interval + 2) |
798 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
799 | } | ||
681 | } | 800 | } |
682 | 801 | ||
683 | |||
684 | /* Wakeup the dpc routine for this adapter, if needed. */ | 802 | /* Wakeup the dpc routine for this adapter, if needed. */ |
685 | if ((start_dpc || | 803 | if ((start_dpc || |
686 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 804 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
687 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || | 805 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || |
688 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || | 806 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || |
689 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 807 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || |
690 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 808 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
691 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || | 809 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || |
692 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || | 810 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || |
811 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
812 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
693 | test_bit(DPC_AEN, &ha->dpc_flags)) && | 813 | test_bit(DPC_AEN, &ha->dpc_flags)) && |
814 | !test_bit(AF_DPC_SCHEDULED, &ha->flags) && | ||
694 | ha->dpc_thread) { | 815 | ha->dpc_thread) { |
695 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" | 816 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" |
696 | " - dpc flags = 0x%lx\n", | 817 | " - dpc flags = 0x%lx\n", |
697 | ha->host_no, __func__, ha->dpc_flags)); | 818 | ha->host_no, __func__, ha->dpc_flags)); |
698 | queue_work(ha->dpc_thread, &ha->dpc_work); | 819 | qla4xxx_wake_dpc(ha); |
699 | } | 820 | } |
700 | 821 | ||
701 | /* Reschedule timer thread to call us back in one second */ | 822 | /* Reschedule timer thread to call us back in one second */ |
@@ -714,16 +835,15 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
714 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | 835 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) |
715 | { | 836 | { |
716 | uint32_t index = 0; | 837 | uint32_t index = 0; |
717 | int stat = QLA_SUCCESS; | ||
718 | unsigned long flags; | 838 | unsigned long flags; |
719 | struct scsi_cmnd *cmd; | 839 | struct scsi_cmnd *cmd; |
720 | int wait_cnt = WAIT_CMD_TOV; /* | ||
721 | * Initialized for 30 seconds as we | ||
722 | * expect all commands to retuned | ||
723 | * ASAP. | ||
724 | */ | ||
725 | 840 | ||
726 | while (wait_cnt) { | 841 | unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ); |
842 | |||
843 | DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to " | ||
844 | "complete\n", WAIT_CMD_TOV)); | ||
845 | |||
846 | while (!time_after_eq(jiffies, wtime)) { | ||
727 | spin_lock_irqsave(&ha->hardware_lock, flags); | 847 | spin_lock_irqsave(&ha->hardware_lock, flags); |
728 | /* Find a command that hasn't completed. */ | 848 | /* Find a command that hasn't completed. */ |
729 | for (index = 0; index < ha->host->can_queue; index++) { | 849 | for (index = 0; index < ha->host->can_queue; index++) { |
@@ -734,31 +854,26 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | |||
734 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 854 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
735 | 855 | ||
736 | /* If No Commands are pending, wait is complete */ | 856 | /* If No Commands are pending, wait is complete */ |
737 | if (index == ha->host->can_queue) { | 857 | if (index == ha->host->can_queue) |
738 | break; | 858 | return QLA_SUCCESS; |
739 | } | ||
740 | |||
741 | /* If we timed out on waiting for commands to come back | ||
742 | * return ERROR. | ||
743 | */ | ||
744 | wait_cnt--; | ||
745 | if (wait_cnt == 0) | ||
746 | stat = QLA_ERROR; | ||
747 | else { | ||
748 | msleep(1000); | ||
749 | } | ||
750 | } /* End of While (wait_cnt) */ | ||
751 | 859 | ||
752 | return stat; | 860 | msleep(1000); |
861 | } | ||
862 | /* If we timed out on waiting for commands to come back | ||
863 | * return ERROR. */ | ||
864 | return QLA_ERROR; | ||
753 | } | 865 | } |
754 | 866 | ||
755 | void qla4xxx_hw_reset(struct scsi_qla_host *ha) | 867 | int qla4xxx_hw_reset(struct scsi_qla_host *ha) |
756 | { | 868 | { |
757 | uint32_t ctrl_status; | 869 | uint32_t ctrl_status; |
758 | unsigned long flags = 0; | 870 | unsigned long flags = 0; |
759 | 871 | ||
760 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); | 872 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); |
761 | 873 | ||
874 | if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) | ||
875 | return QLA_ERROR; | ||
876 | |||
762 | spin_lock_irqsave(&ha->hardware_lock, flags); | 877 | spin_lock_irqsave(&ha->hardware_lock, flags); |
763 | 878 | ||
764 | /* | 879 | /* |
@@ -774,6 +889,7 @@ void qla4xxx_hw_reset(struct scsi_qla_host *ha) | |||
774 | readl(&ha->reg->ctrl_status); | 889 | readl(&ha->reg->ctrl_status); |
775 | 890 | ||
776 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 891 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
892 | return QLA_SUCCESS; | ||
777 | } | 893 | } |
778 | 894 | ||
779 | /** | 895 | /** |
@@ -872,15 +988,16 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha) | |||
872 | } | 988 | } |
873 | 989 | ||
874 | /** | 990 | /** |
875 | * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. | 991 | * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S. |
876 | * @ha: Pointer to host adapter structure. | 992 | * @ha: Pointer to host adapter structure. |
993 | * @res: returned scsi status | ||
877 | * | 994 | * |
878 | * This routine is called just prior to a HARD RESET to return all | 995 | * This routine is called just prior to a HARD RESET to return all |
879 | * outstanding commands back to the Operating System. | 996 | * outstanding commands back to the Operating System. |
880 | * Caller should make sure that the following locks are released | 997 | * Caller should make sure that the following locks are released |
881 | * before this calling routine: Hardware lock, and io_request_lock. | 998 | * before this calling routine: Hardware lock, and io_request_lock. |
882 | **/ | 999 | **/ |
883 | static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | 1000 | static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res) |
884 | { | 1001 | { |
885 | struct srb *srb; | 1002 | struct srb *srb; |
886 | int i; | 1003 | int i; |
@@ -890,74 +1007,116 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | |||
890 | for (i = 0; i < ha->host->can_queue; i++) { | 1007 | for (i = 0; i < ha->host->can_queue; i++) { |
891 | srb = qla4xxx_del_from_active_array(ha, i); | 1008 | srb = qla4xxx_del_from_active_array(ha, i); |
892 | if (srb != NULL) { | 1009 | if (srb != NULL) { |
893 | srb->cmd->result = DID_RESET << 16; | 1010 | srb->cmd->result = res; |
894 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); | 1011 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); |
895 | } | 1012 | } |
896 | } | 1013 | } |
897 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1014 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
898 | } | 1015 | } |
899 | 1016 | ||
1017 | void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) | ||
1018 | { | ||
1019 | clear_bit(AF_ONLINE, &ha->flags); | ||
1020 | |||
1021 | /* Disable the board */ | ||
1022 | ql4_printk(KERN_INFO, ha, "Disabling the board\n"); | ||
1023 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); | ||
1024 | |||
1025 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
1026 | qla4xxx_mark_all_devices_missing(ha); | ||
1027 | clear_bit(AF_INIT_DONE, &ha->flags); | ||
1028 | } | ||
1029 | |||
900 | /** | 1030 | /** |
901 | * qla4xxx_recover_adapter - recovers adapter after a fatal error | 1031 | * qla4xxx_recover_adapter - recovers adapter after a fatal error |
902 | * @ha: Pointer to host adapter structure. | 1032 | * @ha: Pointer to host adapter structure. |
903 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list | ||
904 | * | ||
905 | * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild | ||
906 | * ddb list. | ||
907 | **/ | 1033 | **/ |
908 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | 1034 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) |
909 | uint8_t renew_ddb_list) | ||
910 | { | 1035 | { |
911 | int status; | 1036 | int status = QLA_ERROR; |
1037 | uint8_t reset_chip = 0; | ||
912 | 1038 | ||
913 | /* Stall incoming I/O until we are done */ | 1039 | /* Stall incoming I/O until we are done */ |
1040 | scsi_block_requests(ha->host); | ||
914 | clear_bit(AF_ONLINE, &ha->flags); | 1041 | clear_bit(AF_ONLINE, &ha->flags); |
915 | 1042 | ||
916 | DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, | 1043 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__)); |
917 | __func__)); | ||
918 | 1044 | ||
919 | /* Wait for outstanding commands to complete. | 1045 | set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); |
920 | * Stalls the driver for max 30 secs | ||
921 | */ | ||
922 | status = qla4xxx_cmd_wait(ha); | ||
923 | 1046 | ||
924 | qla4xxx_disable_intrs(ha); | 1047 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
1048 | reset_chip = 1; | ||
925 | 1049 | ||
926 | /* Flush any pending ddb changed AENs */ | 1050 | /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific) |
927 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1051 | * do not reset adapter, jump to initialize_adapter */ |
1052 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
1053 | status = QLA_SUCCESS; | ||
1054 | goto recover_ha_init_adapter; | ||
1055 | } | ||
928 | 1056 | ||
929 | qla4xxx_flush_active_srbs(ha); | 1057 | /* For the ISP-82xx adapter, issue a stop_firmware if invoked |
1058 | * from eh_host_reset or ioctl module */ | ||
1059 | if (is_qla8022(ha) && !reset_chip && | ||
1060 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { | ||
1061 | |||
1062 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1063 | "scsi%ld: %s - Performing stop_firmware...\n", | ||
1064 | ha->host_no, __func__)); | ||
1065 | status = ha->isp_ops->reset_firmware(ha); | ||
1066 | if (status == QLA_SUCCESS) { | ||
1067 | qla4xxx_cmd_wait(ha); | ||
1068 | ha->isp_ops->disable_intrs(ha); | ||
1069 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
1070 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | ||
1071 | } else { | ||
1072 | /* If the stop_firmware fails then | ||
1073 | * reset the entire chip */ | ||
1074 | reset_chip = 1; | ||
1075 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1076 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1077 | } | ||
1078 | } | ||
930 | 1079 | ||
931 | /* Reset the firmware. If successful, function | 1080 | /* Issue full chip reset if recovering from a catastrophic error, |
932 | * returns with ISP interrupts enabled. | 1081 | * or if stop_firmware fails for ISP-82xx. |
933 | */ | 1082 | * This is the default case for ISP-4xxx */ |
934 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 1083 | if (!is_qla8022(ha) || reset_chip) { |
935 | ha->host_no, __func__)); | 1084 | qla4xxx_cmd_wait(ha); |
936 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1085 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
937 | status = qla4xxx_soft_reset(ha); | 1086 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
938 | else | 1087 | DEBUG2(ql4_printk(KERN_INFO, ha, |
939 | status = QLA_ERROR; | 1088 | "scsi%ld: %s - Performing chip reset..\n", |
1089 | ha->host_no, __func__)); | ||
1090 | status = ha->isp_ops->reset_chip(ha); | ||
1091 | } | ||
940 | 1092 | ||
941 | /* Flush any pending ddb changed AENs */ | 1093 | /* Flush any pending ddb changed AENs */ |
942 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1094 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
943 | 1095 | ||
944 | /* Re-initialize firmware. If successful, function returns | 1096 | recover_ha_init_adapter: |
945 | * with ISP interrupts enabled */ | 1097 | /* Upon successful firmware/chip reset, re-initialize the adapter */ |
946 | if (status == QLA_SUCCESS) { | 1098 | if (status == QLA_SUCCESS) { |
947 | DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n", | 1099 | /* For ISP-4xxx, force function 1 to always initialize |
948 | ha->host_no, __func__)); | 1100 | * before function 3 to prevent both funcions from |
949 | 1101 | * stepping on top of the other */ | |
950 | /* If successful, AF_ONLINE flag set in | 1102 | if (!is_qla8022(ha) && (ha->mac_index == 3)) |
951 | * qla4xxx_initialize_adapter */ | 1103 | ssleep(6); |
952 | status = qla4xxx_initialize_adapter(ha, renew_ddb_list); | 1104 | |
1105 | /* NOTE: AF_ONLINE flag set upon successful completion of | ||
1106 | * qla4xxx_initialize_adapter */ | ||
1107 | status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); | ||
953 | } | 1108 | } |
954 | 1109 | ||
955 | /* Failed adapter initialization? | 1110 | /* Retry failed adapter initialization, if necessary |
956 | * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */ | 1111 | * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific) |
957 | if ((test_bit(AF_ONLINE, &ha->flags) == 0) && | 1112 | * case to prevent ping-pong resets between functions */ |
958 | (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { | 1113 | if (!test_bit(AF_ONLINE, &ha->flags) && |
1114 | !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
959 | /* Adapter initialization failed, see if we can retry | 1115 | /* Adapter initialization failed, see if we can retry |
960 | * resetting the ha */ | 1116 | * resetting the ha. |
1117 | * Since we don't want to block the DPC for too long | ||
1118 | * with multiple resets in the same thread, | ||
1119 | * utilize DPC to retry */ | ||
961 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { | 1120 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { |
962 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; | 1121 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; |
963 | DEBUG2(printk("scsi%ld: recover adapter - retrying " | 1122 | DEBUG2(printk("scsi%ld: recover adapter - retrying " |
@@ -982,29 +1141,43 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
982 | DEBUG2(printk("scsi%ld: recover adapter " | 1141 | DEBUG2(printk("scsi%ld: recover adapter " |
983 | "failed - board disabled\n", | 1142 | "failed - board disabled\n", |
984 | ha->host_no)); | 1143 | ha->host_no)); |
985 | qla4xxx_flush_active_srbs(ha); | 1144 | qla4xxx_dead_adapter_cleanup(ha); |
986 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1145 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
987 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1146 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
988 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, | 1147 | clear_bit(DPC_RESET_HA_FW_CONTEXT, |
989 | &ha->dpc_flags); | 1148 | &ha->dpc_flags); |
990 | status = QLA_ERROR; | 1149 | status = QLA_ERROR; |
991 | } | 1150 | } |
992 | } | 1151 | } |
993 | } else { | 1152 | } else { |
994 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1153 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
995 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags); | 1154 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
996 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1155 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
997 | } | 1156 | } |
998 | 1157 | ||
999 | ha->adapter_error_count++; | 1158 | ha->adapter_error_count++; |
1000 | 1159 | ||
1001 | if (status == QLA_SUCCESS) | 1160 | if (test_bit(AF_ONLINE, &ha->flags)) |
1002 | qla4xxx_enable_intrs(ha); | 1161 | ha->isp_ops->enable_intrs(ha); |
1162 | |||
1163 | scsi_unblock_requests(ha->host); | ||
1164 | |||
1165 | clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
1166 | DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, | ||
1167 | status == QLA_ERROR ? "FAILED" : "SUCCEDED")); | ||
1003 | 1168 | ||
1004 | DEBUG2(printk("scsi%ld: recover adapter .. DONE\n", ha->host_no)); | ||
1005 | return status; | 1169 | return status; |
1006 | } | 1170 | } |
1007 | 1171 | ||
1172 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | ||
1173 | { | ||
1174 | if (ha->dpc_thread && | ||
1175 | !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { | ||
1176 | set_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1177 | queue_work(ha->dpc_thread, &ha->dpc_work); | ||
1178 | } | ||
1179 | } | ||
1180 | |||
1008 | /** | 1181 | /** |
1009 | * qla4xxx_do_dpc - dpc routine | 1182 | * qla4xxx_do_dpc - dpc routine |
1010 | * @data: in our case pointer to adapter structure | 1183 | * @data: in our case pointer to adapter structure |
@@ -1024,21 +1197,47 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1024 | int status = QLA_ERROR; | 1197 | int status = QLA_ERROR; |
1025 | 1198 | ||
1026 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." | 1199 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." |
1027 | "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n", | 1200 | "flags = 0x%08lx, dpc_flags = 0x%08lx\n", |
1028 | ha->host_no, __func__, ha->flags, ha->dpc_flags, | 1201 | ha->host_no, __func__, ha->flags, ha->dpc_flags)) |
1029 | readw(&ha->reg->ctrl_status))); | ||
1030 | 1202 | ||
1031 | /* Initialization not yet finished. Don't do anything yet. */ | 1203 | /* Initialization not yet finished. Don't do anything yet. */ |
1032 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1204 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
1033 | return; | 1205 | return; |
1034 | 1206 | ||
1035 | if (adapter_up(ha) || | 1207 | /* HBA is in the process of being permanently disabled. |
1036 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 1208 | * Don't process anything */ |
1209 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) | ||
1210 | return; | ||
1211 | |||
1212 | if (is_qla8022(ha)) { | ||
1213 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { | ||
1214 | qla4_8xxx_idc_lock(ha); | ||
1215 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
1216 | QLA82XX_DEV_FAILED); | ||
1217 | qla4_8xxx_idc_unlock(ha); | ||
1218 | ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
1219 | qla4_8xxx_device_state_handler(ha); | ||
1220 | } | ||
1221 | if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
1222 | qla4_8xxx_need_qsnt_handler(ha); | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) && | ||
1227 | (test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
1037 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 1228 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
1038 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { | 1229 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) { |
1039 | if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 1230 | if (ql4xdontresethba) { |
1040 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | 1231 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", |
1041 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); | 1232 | ha->host_no, __func__)); |
1233 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1234 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | ||
1235 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1236 | goto dpc_post_reset_ha; | ||
1237 | } | ||
1238 | if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || | ||
1239 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | ||
1240 | qla4xxx_recover_adapter(ha); | ||
1042 | 1241 | ||
1043 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | 1242 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { |
1044 | uint8_t wait_time = RESET_INTR_TOV; | 1243 | uint8_t wait_time = RESET_INTR_TOV; |
@@ -1053,18 +1252,18 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1053 | DEBUG2(printk("scsi%ld: %s: SR|FSR " | 1252 | DEBUG2(printk("scsi%ld: %s: SR|FSR " |
1054 | "bit not cleared-- resetting\n", | 1253 | "bit not cleared-- resetting\n", |
1055 | ha->host_no, __func__)); | 1254 | ha->host_no, __func__)); |
1056 | qla4xxx_flush_active_srbs(ha); | 1255 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
1057 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { | 1256 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { |
1058 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1257 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
1059 | status = qla4xxx_initialize_adapter(ha, | 1258 | status = qla4xxx_recover_adapter(ha); |
1060 | PRESERVE_DDB_LIST); | ||
1061 | } | 1259 | } |
1062 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | 1260 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); |
1063 | if (status == QLA_SUCCESS) | 1261 | if (status == QLA_SUCCESS) |
1064 | qla4xxx_enable_intrs(ha); | 1262 | ha->isp_ops->enable_intrs(ha); |
1065 | } | 1263 | } |
1066 | } | 1264 | } |
1067 | 1265 | ||
1266 | dpc_post_reset_ha: | ||
1068 | /* ---- process AEN? --- */ | 1267 | /* ---- process AEN? --- */ |
1069 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | 1268 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) |
1070 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); | 1269 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); |
@@ -1104,11 +1303,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1104 | DDB_STATE_ONLINE); | 1303 | DDB_STATE_ONLINE); |
1105 | dev_info(&ha->pdev->dev, | 1304 | dev_info(&ha->pdev->dev, |
1106 | "scsi%ld: %s: ddb[%d]" | 1305 | "scsi%ld: %s: ddb[%d]" |
1107 | " os[%d] marked" | 1306 | " marked ONLINE\n", |
1108 | " ONLINE\n", | ||
1109 | ha->host_no, __func__, | 1307 | ha->host_no, __func__, |
1110 | ddb_entry->fw_ddb_index, | 1308 | ddb_entry->fw_ddb_index); |
1111 | ddb_entry->os_target_id); | ||
1112 | 1309 | ||
1113 | iscsi_unblock_session( | 1310 | iscsi_unblock_session( |
1114 | ddb_entry->sess); | 1311 | ddb_entry->sess); |
@@ -1144,6 +1341,7 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1144 | } | 1341 | } |
1145 | } | 1342 | } |
1146 | } | 1343 | } |
1344 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1147 | } | 1345 | } |
1148 | 1346 | ||
1149 | /** | 1347 | /** |
@@ -1155,30 +1353,99 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1155 | 1353 | ||
1156 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { | 1354 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { |
1157 | /* Turn-off interrupts on the card. */ | 1355 | /* Turn-off interrupts on the card. */ |
1158 | qla4xxx_disable_intrs(ha); | 1356 | ha->isp_ops->disable_intrs(ha); |
1159 | } | 1357 | } |
1160 | 1358 | ||
1359 | /* Remove timer thread, if present */ | ||
1360 | if (ha->timer_active) | ||
1361 | qla4xxx_stop_timer(ha); | ||
1362 | |||
1161 | /* Kill the kernel thread for this host */ | 1363 | /* Kill the kernel thread for this host */ |
1162 | if (ha->dpc_thread) | 1364 | if (ha->dpc_thread) |
1163 | destroy_workqueue(ha->dpc_thread); | 1365 | destroy_workqueue(ha->dpc_thread); |
1164 | 1366 | ||
1165 | /* Issue Soft Reset to put firmware in unknown state */ | 1367 | /* Put firmware in known state */ |
1166 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1368 | ha->isp_ops->reset_firmware(ha); |
1167 | qla4xxx_hw_reset(ha); | ||
1168 | 1369 | ||
1169 | /* Remove timer thread, if present */ | 1370 | if (is_qla8022(ha)) { |
1170 | if (ha->timer_active) | 1371 | qla4_8xxx_idc_lock(ha); |
1171 | qla4xxx_stop_timer(ha); | 1372 | qla4_8xxx_clear_drv_active(ha); |
1373 | qla4_8xxx_idc_unlock(ha); | ||
1374 | } | ||
1172 | 1375 | ||
1173 | /* Detach interrupts */ | 1376 | /* Detach interrupts */ |
1174 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) | 1377 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) |
1175 | free_irq(ha->pdev->irq, ha); | 1378 | qla4xxx_free_irqs(ha); |
1176 | 1379 | ||
1177 | /* free extra memory */ | 1380 | /* free extra memory */ |
1178 | qla4xxx_mem_free(ha); | 1381 | qla4xxx_mem_free(ha); |
1382 | } | ||
1383 | |||
1384 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) | ||
1385 | { | ||
1386 | int status = 0; | ||
1387 | uint8_t revision_id; | ||
1388 | unsigned long mem_base, mem_len, db_base, db_len; | ||
1389 | struct pci_dev *pdev = ha->pdev; | ||
1390 | |||
1391 | status = pci_request_regions(pdev, DRIVER_NAME); | ||
1392 | if (status) { | ||
1393 | printk(KERN_WARNING | ||
1394 | "scsi(%ld) Failed to reserve PIO regions (%s) " | ||
1395 | "status=%d\n", ha->host_no, pci_name(pdev), status); | ||
1396 | goto iospace_error_exit; | ||
1397 | } | ||
1398 | |||
1399 | pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id); | ||
1400 | DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n", | ||
1401 | __func__, revision_id)); | ||
1402 | ha->revision_id = revision_id; | ||
1179 | 1403 | ||
1180 | pci_disable_device(ha->pdev); | 1404 | /* remap phys address */ |
1405 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | ||
1406 | mem_len = pci_resource_len(pdev, 0); | ||
1407 | DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n", | ||
1408 | __func__, mem_base, mem_len)); | ||
1181 | 1409 | ||
1410 | /* mapping of pcibase pointer */ | ||
1411 | ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len); | ||
1412 | if (!ha->nx_pcibase) { | ||
1413 | printk(KERN_ERR | ||
1414 | "cannot remap MMIO (%s), aborting\n", pci_name(pdev)); | ||
1415 | pci_release_regions(ha->pdev); | ||
1416 | goto iospace_error_exit; | ||
1417 | } | ||
1418 | |||
1419 | /* Mapping of IO base pointer, door bell read and write pointer */ | ||
1420 | |||
1421 | /* mapping of IO base pointer */ | ||
1422 | ha->qla4_8xxx_reg = | ||
1423 | (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase + | ||
1424 | 0xbc000 + (ha->pdev->devfn << 11)); | ||
1425 | |||
1426 | db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ | ||
1427 | db_len = pci_resource_len(pdev, 4); | ||
1428 | |||
1429 | /* mapping of doorbell write pointer */ | ||
1430 | ha->nx_db_wr_ptr = (unsigned long)ioremap(db_base + | ||
1431 | (ha->pdev->devfn << 12), 4); | ||
1432 | if (!ha->nx_db_wr_ptr) { | ||
1433 | printk(KERN_ERR | ||
1434 | "cannot remap MMIO doorbell-write (%s), aborting\n", | ||
1435 | pci_name(pdev)); | ||
1436 | goto iospace_error_exit; | ||
1437 | } | ||
1438 | /* mapping of doorbell read pointer */ | ||
1439 | ha->nx_db_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + | ||
1440 | (ha->pdev->devfn * 8); | ||
1441 | if (!ha->nx_db_rd_ptr) | ||
1442 | printk(KERN_ERR | ||
1443 | "cannot remap MMIO doorbell-read (%s), aborting\n", | ||
1444 | pci_name(pdev)); | ||
1445 | return 0; | ||
1446 | |||
1447 | iospace_error_exit: | ||
1448 | return -ENOMEM; | ||
1182 | } | 1449 | } |
1183 | 1450 | ||
1184 | /*** | 1451 | /*** |
@@ -1188,7 +1455,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1188 | * This routines maps HBA's registers from the pci address space | 1455 | * This routines maps HBA's registers from the pci address space |
1189 | * into the kernel virtual address space for memory mapped i/o. | 1456 | * into the kernel virtual address space for memory mapped i/o. |
1190 | **/ | 1457 | **/ |
1191 | static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | 1458 | int qla4xxx_iospace_config(struct scsi_qla_host *ha) |
1192 | { | 1459 | { |
1193 | unsigned long pio, pio_len, pio_flags; | 1460 | unsigned long pio, pio_len, pio_flags; |
1194 | unsigned long mmio, mmio_len, mmio_flags; | 1461 | unsigned long mmio, mmio_len, mmio_flags; |
@@ -1247,6 +1514,60 @@ iospace_error_exit: | |||
1247 | return -ENOMEM; | 1514 | return -ENOMEM; |
1248 | } | 1515 | } |
1249 | 1516 | ||
1517 | static struct isp_operations qla4xxx_isp_ops = { | ||
1518 | .iospace_config = qla4xxx_iospace_config, | ||
1519 | .pci_config = qla4xxx_pci_config, | ||
1520 | .disable_intrs = qla4xxx_disable_intrs, | ||
1521 | .enable_intrs = qla4xxx_enable_intrs, | ||
1522 | .start_firmware = qla4xxx_start_firmware, | ||
1523 | .intr_handler = qla4xxx_intr_handler, | ||
1524 | .interrupt_service_routine = qla4xxx_interrupt_service_routine, | ||
1525 | .reset_chip = qla4xxx_soft_reset, | ||
1526 | .reset_firmware = qla4xxx_hw_reset, | ||
1527 | .queue_iocb = qla4xxx_queue_iocb, | ||
1528 | .complete_iocb = qla4xxx_complete_iocb, | ||
1529 | .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, | ||
1530 | .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, | ||
1531 | .get_sys_info = qla4xxx_get_sys_info, | ||
1532 | }; | ||
1533 | |||
1534 | static struct isp_operations qla4_8xxx_isp_ops = { | ||
1535 | .iospace_config = qla4_8xxx_iospace_config, | ||
1536 | .pci_config = qla4_8xxx_pci_config, | ||
1537 | .disable_intrs = qla4_8xxx_disable_intrs, | ||
1538 | .enable_intrs = qla4_8xxx_enable_intrs, | ||
1539 | .start_firmware = qla4_8xxx_load_risc, | ||
1540 | .intr_handler = qla4_8xxx_intr_handler, | ||
1541 | .interrupt_service_routine = qla4_8xxx_interrupt_service_routine, | ||
1542 | .reset_chip = qla4_8xxx_isp_reset, | ||
1543 | .reset_firmware = qla4_8xxx_stop_firmware, | ||
1544 | .queue_iocb = qla4_8xxx_queue_iocb, | ||
1545 | .complete_iocb = qla4_8xxx_complete_iocb, | ||
1546 | .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out, | ||
1547 | .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in, | ||
1548 | .get_sys_info = qla4_8xxx_get_sys_info, | ||
1549 | }; | ||
1550 | |||
1551 | uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1552 | { | ||
1553 | return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out); | ||
1554 | } | ||
1555 | |||
1556 | uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1557 | { | ||
1558 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out)); | ||
1559 | } | ||
1560 | |||
1561 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1562 | { | ||
1563 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); | ||
1564 | } | ||
1565 | |||
1566 | uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1567 | { | ||
1568 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in)); | ||
1569 | } | ||
1570 | |||
1250 | /** | 1571 | /** |
1251 | * qla4xxx_probe_adapter - callback function to probe HBA | 1572 | * qla4xxx_probe_adapter - callback function to probe HBA |
1252 | * @pdev: pointer to pci_dev structure | 1573 | * @pdev: pointer to pci_dev structure |
@@ -1264,6 +1585,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1264 | struct scsi_qla_host *ha; | 1585 | struct scsi_qla_host *ha; |
1265 | uint8_t init_retry_count = 0; | 1586 | uint8_t init_retry_count = 0; |
1266 | char buf[34]; | 1587 | char buf[34]; |
1588 | struct qla4_8xxx_legacy_intr_set *nx_legacy_intr; | ||
1267 | 1589 | ||
1268 | if (pci_enable_device(pdev)) | 1590 | if (pci_enable_device(pdev)) |
1269 | return -1; | 1591 | return -1; |
@@ -1284,10 +1606,28 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1284 | ha->host = host; | 1606 | ha->host = host; |
1285 | ha->host_no = host->host_no; | 1607 | ha->host_no = host->host_no; |
1286 | 1608 | ||
1609 | /* Setup Runtime configurable options */ | ||
1610 | if (is_qla8022(ha)) { | ||
1611 | ha->isp_ops = &qla4_8xxx_isp_ops; | ||
1612 | rwlock_init(&ha->hw_lock); | ||
1613 | ha->qdr_sn_window = -1; | ||
1614 | ha->ddr_mn_window = -1; | ||
1615 | ha->curr_window = 255; | ||
1616 | ha->func_num = PCI_FUNC(ha->pdev->devfn); | ||
1617 | nx_legacy_intr = &legacy_intr[ha->func_num]; | ||
1618 | ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; | ||
1619 | ha->nx_legacy_intr.tgt_status_reg = | ||
1620 | nx_legacy_intr->tgt_status_reg; | ||
1621 | ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; | ||
1622 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; | ||
1623 | } else { | ||
1624 | ha->isp_ops = &qla4xxx_isp_ops; | ||
1625 | } | ||
1626 | |||
1287 | /* Configure PCI I/O space. */ | 1627 | /* Configure PCI I/O space. */ |
1288 | ret = qla4xxx_iospace_config(ha); | 1628 | ret = ha->isp_ops->iospace_config(ha); |
1289 | if (ret) | 1629 | if (ret) |
1290 | goto probe_failed; | 1630 | goto probe_failed_ioconfig; |
1291 | 1631 | ||
1292 | dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", | 1632 | dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", |
1293 | pdev->device, pdev->irq, ha->reg); | 1633 | pdev->device, pdev->irq, ha->reg); |
@@ -1299,6 +1639,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1299 | INIT_LIST_HEAD(&ha->free_srb_q); | 1639 | INIT_LIST_HEAD(&ha->free_srb_q); |
1300 | 1640 | ||
1301 | mutex_init(&ha->mbox_sem); | 1641 | mutex_init(&ha->mbox_sem); |
1642 | init_completion(&ha->mbx_intr_comp); | ||
1302 | 1643 | ||
1303 | spin_lock_init(&ha->hardware_lock); | 1644 | spin_lock_init(&ha->hardware_lock); |
1304 | 1645 | ||
@@ -1311,19 +1652,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1311 | goto probe_failed; | 1652 | goto probe_failed; |
1312 | } | 1653 | } |
1313 | 1654 | ||
1655 | if (is_qla8022(ha)) | ||
1656 | (void) qla4_8xxx_get_flash_info(ha); | ||
1657 | |||
1314 | /* | 1658 | /* |
1315 | * Initialize the Host adapter request/response queues and | 1659 | * Initialize the Host adapter request/response queues and |
1316 | * firmware | 1660 | * firmware |
1317 | * NOTE: interrupts enabled upon successful completion | 1661 | * NOTE: interrupts enabled upon successful completion |
1318 | */ | 1662 | */ |
1319 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1663 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1320 | while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) { | 1664 | while ((!test_bit(AF_ONLINE, &ha->flags)) && |
1665 | init_retry_count++ < MAX_INIT_RETRIES) { | ||
1321 | DEBUG2(printk("scsi: %s: retrying adapter initialization " | 1666 | DEBUG2(printk("scsi: %s: retrying adapter initialization " |
1322 | "(%d)\n", __func__, init_retry_count)); | 1667 | "(%d)\n", __func__, init_retry_count)); |
1323 | qla4xxx_soft_reset(ha); | 1668 | |
1669 | if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) | ||
1670 | continue; | ||
1671 | |||
1324 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1672 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1325 | } | 1673 | } |
1326 | if (status == QLA_ERROR) { | 1674 | |
1675 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
1327 | dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); | 1676 | dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); |
1328 | 1677 | ||
1329 | ret = -ENODEV; | 1678 | ret = -ENODEV; |
@@ -1356,18 +1705,21 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1356 | } | 1705 | } |
1357 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); | 1706 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); |
1358 | 1707 | ||
1359 | ret = request_irq(pdev->irq, qla4xxx_intr_handler, | 1708 | /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc |
1360 | IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha); | 1709 | * (which is called indirectly by qla4xxx_initialize_adapter), |
1361 | if (ret) { | 1710 | * so that irqs will be registered after crbinit but before |
1362 | dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d" | 1711 | * mbx_intr_enable. |
1363 | " already in use.\n", pdev->irq); | 1712 | */ |
1364 | goto probe_failed; | 1713 | if (!is_qla8022(ha)) { |
1714 | ret = qla4xxx_request_irqs(ha); | ||
1715 | if (ret) { | ||
1716 | ql4_printk(KERN_WARNING, ha, "Failed to reserve " | ||
1717 | "interrupt %d already in use.\n", pdev->irq); | ||
1718 | goto probe_failed; | ||
1719 | } | ||
1365 | } | 1720 | } |
1366 | set_bit(AF_IRQ_ATTACHED, &ha->flags); | ||
1367 | host->irq = pdev->irq; | ||
1368 | DEBUG(printk("scsi%d: irq %d attached\n", ha->host_no, ha->pdev->irq)); | ||
1369 | 1721 | ||
1370 | qla4xxx_enable_intrs(ha); | 1722 | ha->isp_ops->enable_intrs(ha); |
1371 | 1723 | ||
1372 | /* Start timer thread. */ | 1724 | /* Start timer thread. */ |
1373 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); | 1725 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); |
@@ -1391,6 +1743,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1391 | 1743 | ||
1392 | probe_failed: | 1744 | probe_failed: |
1393 | qla4xxx_free_adapter(ha); | 1745 | qla4xxx_free_adapter(ha); |
1746 | |||
1747 | probe_failed_ioconfig: | ||
1394 | scsi_host_put(ha->host); | 1748 | scsi_host_put(ha->host); |
1395 | 1749 | ||
1396 | probe_disable_device: | 1750 | probe_disable_device: |
@@ -1409,10 +1763,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1409 | 1763 | ||
1410 | ha = pci_get_drvdata(pdev); | 1764 | ha = pci_get_drvdata(pdev); |
1411 | 1765 | ||
1412 | qla4xxx_disable_intrs(ha); | 1766 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); |
1413 | |||
1414 | while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | ||
1415 | ssleep(1); | ||
1416 | 1767 | ||
1417 | /* remove devs from iscsi_sessions to scsi_devices */ | 1768 | /* remove devs from iscsi_sessions to scsi_devices */ |
1418 | qla4xxx_free_ddb_list(ha); | 1769 | qla4xxx_free_ddb_list(ha); |
@@ -1423,6 +1774,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1423 | 1774 | ||
1424 | scsi_host_put(ha->host); | 1775 | scsi_host_put(ha->host); |
1425 | 1776 | ||
1777 | pci_disable_device(pdev); | ||
1426 | pci_set_drvdata(pdev, NULL); | 1778 | pci_set_drvdata(pdev, NULL); |
1427 | } | 1779 | } |
1428 | 1780 | ||
@@ -1479,7 +1831,8 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) | |||
1479 | * | 1831 | * |
1480 | * This routine removes and returns the srb at the specified index | 1832 | * This routine removes and returns the srb at the specified index |
1481 | **/ | 1833 | **/ |
1482 | struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index) | 1834 | struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, |
1835 | uint32_t index) | ||
1483 | { | 1836 | { |
1484 | struct srb *srb = NULL; | 1837 | struct srb *srb = NULL; |
1485 | struct scsi_cmnd *cmd = NULL; | 1838 | struct scsi_cmnd *cmd = NULL; |
@@ -1769,6 +2122,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1769 | 2122 | ||
1770 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; | 2123 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; |
1771 | 2124 | ||
2125 | if (ql4xdontresethba) { | ||
2126 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", | ||
2127 | ha->host_no, __func__)); | ||
2128 | return FAILED; | ||
2129 | } | ||
2130 | |||
1772 | dev_info(&ha->pdev->dev, | 2131 | dev_info(&ha->pdev->dev, |
1773 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, | 2132 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, |
1774 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 2133 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
@@ -1781,11 +2140,14 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1781 | return FAILED; | 2140 | return FAILED; |
1782 | } | 2141 | } |
1783 | 2142 | ||
1784 | /* make sure the dpc thread is stopped while we reset the hba */ | 2143 | if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
1785 | clear_bit(AF_ONLINE, &ha->flags); | 2144 | if (is_qla8022(ha)) |
1786 | flush_workqueue(ha->dpc_thread); | 2145 | set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
2146 | else | ||
2147 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2148 | } | ||
1787 | 2149 | ||
1788 | if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) | 2150 | if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) |
1789 | return_status = SUCCESS; | 2151 | return_status = SUCCESS; |
1790 | 2152 | ||
1791 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", | 2153 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", |
@@ -1794,7 +2156,6 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1794 | return return_status; | 2156 | return return_status; |
1795 | } | 2157 | } |
1796 | 2158 | ||
1797 | |||
1798 | static struct pci_device_id qla4xxx_pci_tbl[] = { | 2159 | static struct pci_device_id qla4xxx_pci_tbl[] = { |
1799 | { | 2160 | { |
1800 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2161 | .vendor = PCI_VENDOR_ID_QLOGIC, |
@@ -1814,6 +2175,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { | |||
1814 | .subvendor = PCI_ANY_ID, | 2175 | .subvendor = PCI_ANY_ID, |
1815 | .subdevice = PCI_ANY_ID, | 2176 | .subdevice = PCI_ANY_ID, |
1816 | }, | 2177 | }, |
2178 | { | ||
2179 | .vendor = PCI_VENDOR_ID_QLOGIC, | ||
2180 | .device = PCI_DEVICE_ID_QLOGIC_ISP8022, | ||
2181 | .subvendor = PCI_ANY_ID, | ||
2182 | .subdevice = PCI_ANY_ID, | ||
2183 | }, | ||
1817 | {0, 0}, | 2184 | {0, 0}, |
1818 | }; | 2185 | }; |
1819 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); | 2186 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); |
@@ -1869,7 +2236,6 @@ no_srp_cache: | |||
1869 | 2236 | ||
1870 | static void __exit qla4xxx_module_exit(void) | 2237 | static void __exit qla4xxx_module_exit(void) |
1871 | { | 2238 | { |
1872 | ql4_mod_unload = 1; | ||
1873 | pci_unregister_driver(&qla4xxx_pci_driver); | 2239 | pci_unregister_driver(&qla4xxx_pci_driver); |
1874 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); | 2240 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); |
1875 | kmem_cache_destroy(srb_cachep); | 2241 | kmem_cache_destroy(srb_cachep); |