diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 758 |
1 files changed, 570 insertions, 188 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 38b1d38afca5..5529b2a39741 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, |
@@ -116,7 +126,8 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
116 | .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD | | 126 | .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD | |
117 | CAP_DATA_PATH_OFFLOAD, | 127 | CAP_DATA_PATH_OFFLOAD, |
118 | .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | | 128 | .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | |
119 | ISCSI_TARGET_NAME | ISCSI_TPGT, | 129 | ISCSI_TARGET_NAME | ISCSI_TPGT | |
130 | ISCSI_TARGET_ALIAS, | ||
120 | .host_param_mask = ISCSI_HOST_HWADDRESS | | 131 | .host_param_mask = ISCSI_HOST_HWADDRESS | |
121 | ISCSI_HOST_IPADDRESS | | 132 | ISCSI_HOST_IPADDRESS | |
122 | ISCSI_HOST_INITIATOR_NAME, | 133 | ISCSI_HOST_INITIATOR_NAME, |
@@ -152,15 +163,12 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | |||
152 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | 163 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { |
153 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); | 164 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); |
154 | 165 | ||
155 | DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count " | 166 | DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " |
156 | "of (%d) secs exhausted, marking device DEAD.\n", | 167 | "of (%d) secs exhausted, marking device DEAD.\n", |
157 | ha->host_no, __func__, ddb_entry->fw_ddb_index, | 168 | ha->host_no, __func__, ddb_entry->fw_ddb_index, |
158 | ha->port_down_retry_count)); | 169 | ha->port_down_retry_count)); |
159 | 170 | ||
160 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc " | 171 | 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 | } | 172 | } |
165 | } | 173 | } |
166 | 174 | ||
@@ -203,6 +211,10 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, | |||
203 | case ISCSI_PARAM_TPGT: | 211 | case ISCSI_PARAM_TPGT: |
204 | len = sprintf(buf, "%u\n", ddb_entry->tpgt); | 212 | len = sprintf(buf, "%u\n", ddb_entry->tpgt); |
205 | break; | 213 | break; |
214 | case ISCSI_PARAM_TARGET_ALIAS: | ||
215 | len = snprintf(buf, PAGE_SIZE - 1, "%s\n", | ||
216 | ddb_entry->iscsi_alias); | ||
217 | break; | ||
206 | default: | 218 | default: |
207 | return -ENOSYS; | 219 | return -ENOSYS; |
208 | } | 220 | } |
@@ -362,19 +374,37 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha) | |||
362 | * @ha: Pointer to host adapter structure. | 374 | * @ha: Pointer to host adapter structure. |
363 | * @ddb_entry: Pointer to device database entry | 375 | * @ddb_entry: Pointer to device database entry |
364 | * | 376 | * |
365 | * This routine marks a device missing and resets the relogin retry count. | 377 | * This routine marks a device missing and close connection. |
366 | **/ | 378 | **/ |
367 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, | 379 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, |
368 | struct ddb_entry *ddb_entry) | 380 | struct ddb_entry *ddb_entry) |
369 | { | 381 | { |
370 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); | 382 | if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) { |
371 | DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n", | 383 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); |
372 | ha->host_no, ddb_entry->bus, ddb_entry->target, | 384 | DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n", |
373 | ddb_entry->fw_ddb_index)); | 385 | ha->host_no, ddb_entry->fw_ddb_index)); |
386 | } else | ||
387 | DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no, | ||
388 | ddb_entry->fw_ddb_index)) | ||
389 | |||
374 | iscsi_block_session(ddb_entry->sess); | 390 | iscsi_block_session(ddb_entry->sess); |
375 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); | 391 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); |
376 | } | 392 | } |
377 | 393 | ||
394 | /** | ||
395 | * qla4xxx_mark_all_devices_missing - mark all devices as missing. | ||
396 | * @ha: Pointer to host adapter structure. | ||
397 | * | ||
398 | * This routine marks a device missing and resets the relogin retry count. | ||
399 | **/ | ||
400 | void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) | ||
401 | { | ||
402 | struct ddb_entry *ddb_entry, *ddbtemp; | ||
403 | list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { | ||
404 | qla4xxx_mark_device_missing(ha, ddb_entry); | ||
405 | } | ||
406 | } | ||
407 | |||
378 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | 408 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, |
379 | struct ddb_entry *ddb_entry, | 409 | struct ddb_entry *ddb_entry, |
380 | struct scsi_cmnd *cmd, | 410 | struct scsi_cmnd *cmd, |
@@ -463,7 +493,13 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, | |||
463 | return SCSI_MLQUEUE_TARGET_BUSY; | 493 | return SCSI_MLQUEUE_TARGET_BUSY; |
464 | } | 494 | } |
465 | 495 | ||
466 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | 496 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
497 | test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | ||
498 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
499 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
500 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
501 | !test_bit(AF_ONLINE, &ha->flags) || | ||
502 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) | ||
467 | goto qc_host_busy; | 503 | goto qc_host_busy; |
468 | 504 | ||
469 | spin_unlock_irq(ha->host->host_lock); | 505 | spin_unlock_irq(ha->host->host_lock); |
@@ -524,7 +560,15 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
524 | ha->srb_mempool = NULL; | 560 | ha->srb_mempool = NULL; |
525 | 561 | ||
526 | /* release io space registers */ | 562 | /* release io space registers */ |
527 | if (ha->reg) | 563 | if (is_qla8022(ha)) { |
564 | if (ha->nx_pcibase) | ||
565 | iounmap( | ||
566 | (struct device_reg_82xx __iomem *)ha->nx_pcibase); | ||
567 | |||
568 | if (ha->nx_db_wr_ptr) | ||
569 | iounmap( | ||
570 | (struct device_reg_82xx __iomem *)ha->nx_db_wr_ptr); | ||
571 | } else if (ha->reg) | ||
528 | iounmap(ha->reg); | 572 | iounmap(ha->reg); |
529 | pci_release_regions(ha->pdev); | 573 | pci_release_regions(ha->pdev); |
530 | } | 574 | } |
@@ -549,8 +593,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) | |||
549 | ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len, | 593 | ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len, |
550 | &ha->queues_dma, GFP_KERNEL); | 594 | &ha->queues_dma, GFP_KERNEL); |
551 | if (ha->queues == NULL) { | 595 | if (ha->queues == NULL) { |
552 | dev_warn(&ha->pdev->dev, | 596 | ql4_printk(KERN_WARNING, ha, |
553 | "Memory Allocation failed - queues.\n"); | 597 | "Memory Allocation failed - queues.\n"); |
554 | 598 | ||
555 | goto mem_alloc_error_exit; | 599 | goto mem_alloc_error_exit; |
556 | } | 600 | } |
@@ -586,8 +630,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) | |||
586 | ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, | 630 | ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, |
587 | mempool_free_slab, srb_cachep); | 631 | mempool_free_slab, srb_cachep); |
588 | if (ha->srb_mempool == NULL) { | 632 | if (ha->srb_mempool == NULL) { |
589 | dev_warn(&ha->pdev->dev, | 633 | ql4_printk(KERN_WARNING, ha, |
590 | "Memory Allocation failed - SRB Pool.\n"); | 634 | "Memory Allocation failed - SRB Pool.\n"); |
591 | 635 | ||
592 | goto mem_alloc_error_exit; | 636 | goto mem_alloc_error_exit; |
593 | } | 637 | } |
@@ -600,6 +644,74 @@ mem_alloc_error_exit: | |||
600 | } | 644 | } |
601 | 645 | ||
602 | /** | 646 | /** |
647 | * qla4_8xxx_check_fw_alive - Check firmware health | ||
648 | * @ha: Pointer to host adapter structure. | ||
649 | * | ||
650 | * Context: Interrupt | ||
651 | **/ | ||
652 | static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | ||
653 | { | ||
654 | uint32_t fw_heartbeat_counter, halt_status; | ||
655 | |||
656 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
657 | |||
658 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | ||
659 | ha->seconds_since_last_heartbeat++; | ||
660 | /* FW not alive after 2 seconds */ | ||
661 | if (ha->seconds_since_last_heartbeat == 2) { | ||
662 | ha->seconds_since_last_heartbeat = 0; | ||
663 | halt_status = qla4_8xxx_rd_32(ha, | ||
664 | QLA82XX_PEG_HALT_STATUS1); | ||
665 | /* Since we cannot change dev_state in interrupt | ||
666 | * context, set appropriate DPC flag then wakeup | ||
667 | * DPC */ | ||
668 | if (halt_status & HALT_STATUS_UNRECOVERABLE) | ||
669 | set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); | ||
670 | else { | ||
671 | printk("scsi%ld: %s: detect abort needed!\n", | ||
672 | ha->host_no, __func__); | ||
673 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
674 | } | ||
675 | qla4xxx_wake_dpc(ha); | ||
676 | } | ||
677 | } | ||
678 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * qla4_8xxx_watchdog - Poll dev state | ||
683 | * @ha: Pointer to host adapter structure. | ||
684 | * | ||
685 | * Context: Interrupt | ||
686 | **/ | ||
687 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | ||
688 | { | ||
689 | uint32_t dev_state; | ||
690 | |||
691 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
692 | |||
693 | /* don't poll if reset is going on */ | ||
694 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) { | ||
695 | if (dev_state == QLA82XX_DEV_NEED_RESET && | ||
696 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
697 | printk("scsi%ld: %s: HW State: NEED RESET!\n", | ||
698 | ha->host_no, __func__); | ||
699 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
700 | qla4xxx_wake_dpc(ha); | ||
701 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | ||
702 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
703 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", | ||
704 | ha->host_no, __func__); | ||
705 | set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); | ||
706 | qla4xxx_wake_dpc(ha); | ||
707 | } else { | ||
708 | /* Check firmware health */ | ||
709 | qla4_8xxx_check_fw_alive(ha); | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /** | ||
603 | * qla4xxx_timer - checks every second for work to do. | 715 | * qla4xxx_timer - checks every second for work to do. |
604 | * @ha: Pointer to host adapter structure. | 716 | * @ha: Pointer to host adapter structure. |
605 | **/ | 717 | **/ |
@@ -608,6 +720,16 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
608 | struct ddb_entry *ddb_entry, *dtemp; | 720 | struct ddb_entry *ddb_entry, *dtemp; |
609 | int start_dpc = 0; | 721 | int start_dpc = 0; |
610 | 722 | ||
723 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | ||
724 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | ||
725 | __func__)); | ||
726 | return; | ||
727 | } | ||
728 | |||
729 | if (is_qla8022(ha)) { | ||
730 | qla4_8xxx_watchdog(ha); | ||
731 | } | ||
732 | |||
611 | /* Search for relogin's to time-out and port down retry. */ | 733 | /* Search for relogin's to time-out and port down retry. */ |
612 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { | 734 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { |
613 | /* Count down time between sending relogins */ | 735 | /* Count down time between sending relogins */ |
@@ -624,7 +746,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
624 | set_bit(DPC_RELOGIN_DEVICE, | 746 | set_bit(DPC_RELOGIN_DEVICE, |
625 | &ha->dpc_flags); | 747 | &ha->dpc_flags); |
626 | set_bit(DF_RELOGIN, &ddb_entry->flags); | 748 | set_bit(DF_RELOGIN, &ddb_entry->flags); |
627 | DEBUG2(printk("scsi%ld: %s: index [%d]" | 749 | DEBUG2(printk("scsi%ld: %s: ddb [%d]" |
628 | " login device\n", | 750 | " login device\n", |
629 | ha->host_no, __func__, | 751 | ha->host_no, __func__, |
630 | ddb_entry->fw_ddb_index)); | 752 | ddb_entry->fw_ddb_index)); |
@@ -647,7 +769,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
647 | DDB_DS_SESSION_FAILED) { | 769 | DDB_DS_SESSION_FAILED) { |
648 | /* Reset retry relogin timer */ | 770 | /* Reset retry relogin timer */ |
649 | atomic_inc(&ddb_entry->relogin_retry_count); | 771 | atomic_inc(&ddb_entry->relogin_retry_count); |
650 | DEBUG2(printk("scsi%ld: index[%d] relogin" | 772 | DEBUG2(printk("scsi%ld: ddb [%d] relogin" |
651 | " timed out-retrying" | 773 | " timed out-retrying" |
652 | " relogin (%d)\n", | 774 | " relogin (%d)\n", |
653 | ha->host_no, | 775 | ha->host_no, |
@@ -656,7 +778,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
656 | relogin_retry_count)) | 778 | relogin_retry_count)) |
657 | ); | 779 | ); |
658 | start_dpc++; | 780 | start_dpc++; |
659 | DEBUG(printk("scsi%ld:%d:%d: index [%d] " | 781 | DEBUG(printk("scsi%ld:%d:%d: ddb [%d] " |
660 | "initate relogin after" | 782 | "initate relogin after" |
661 | " %d seconds\n", | 783 | " %d seconds\n", |
662 | ha->host_no, ddb_entry->bus, | 784 | ha->host_no, ddb_entry->bus, |
@@ -671,31 +793,35 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
671 | } | 793 | } |
672 | } | 794 | } |
673 | 795 | ||
674 | /* Check for heartbeat interval. */ | 796 | if (!is_qla8022(ha)) { |
675 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && | 797 | /* Check for heartbeat interval. */ |
676 | ha->heartbeat_interval != 0) { | 798 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && |
677 | ha->seconds_since_last_heartbeat++; | 799 | ha->heartbeat_interval != 0) { |
678 | if (ha->seconds_since_last_heartbeat > | 800 | ha->seconds_since_last_heartbeat++; |
679 | ha->heartbeat_interval + 2) | 801 | if (ha->seconds_since_last_heartbeat > |
680 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 802 | ha->heartbeat_interval + 2) |
803 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
804 | } | ||
681 | } | 805 | } |
682 | 806 | ||
683 | |||
684 | /* Wakeup the dpc routine for this adapter, if needed. */ | 807 | /* Wakeup the dpc routine for this adapter, if needed. */ |
685 | if ((start_dpc || | 808 | if ((start_dpc || |
686 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 809 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
687 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || | 810 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || |
688 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || | 811 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || |
689 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 812 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || |
690 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 813 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
691 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || | 814 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || |
692 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || | 815 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || |
816 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
817 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
693 | test_bit(DPC_AEN, &ha->dpc_flags)) && | 818 | test_bit(DPC_AEN, &ha->dpc_flags)) && |
819 | !test_bit(AF_DPC_SCHEDULED, &ha->flags) && | ||
694 | ha->dpc_thread) { | 820 | ha->dpc_thread) { |
695 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" | 821 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" |
696 | " - dpc flags = 0x%lx\n", | 822 | " - dpc flags = 0x%lx\n", |
697 | ha->host_no, __func__, ha->dpc_flags)); | 823 | ha->host_no, __func__, ha->dpc_flags)); |
698 | queue_work(ha->dpc_thread, &ha->dpc_work); | 824 | qla4xxx_wake_dpc(ha); |
699 | } | 825 | } |
700 | 826 | ||
701 | /* Reschedule timer thread to call us back in one second */ | 827 | /* Reschedule timer thread to call us back in one second */ |
@@ -714,16 +840,15 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
714 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | 840 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) |
715 | { | 841 | { |
716 | uint32_t index = 0; | 842 | uint32_t index = 0; |
717 | int stat = QLA_SUCCESS; | ||
718 | unsigned long flags; | 843 | unsigned long flags; |
719 | struct scsi_cmnd *cmd; | 844 | 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 | 845 | ||
726 | while (wait_cnt) { | 846 | unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ); |
847 | |||
848 | DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to " | ||
849 | "complete\n", WAIT_CMD_TOV)); | ||
850 | |||
851 | while (!time_after_eq(jiffies, wtime)) { | ||
727 | spin_lock_irqsave(&ha->hardware_lock, flags); | 852 | spin_lock_irqsave(&ha->hardware_lock, flags); |
728 | /* Find a command that hasn't completed. */ | 853 | /* Find a command that hasn't completed. */ |
729 | for (index = 0; index < ha->host->can_queue; index++) { | 854 | for (index = 0; index < ha->host->can_queue; index++) { |
@@ -734,31 +859,26 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | |||
734 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 859 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
735 | 860 | ||
736 | /* If No Commands are pending, wait is complete */ | 861 | /* If No Commands are pending, wait is complete */ |
737 | if (index == ha->host->can_queue) { | 862 | if (index == ha->host->can_queue) |
738 | break; | 863 | 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 | 864 | ||
752 | return stat; | 865 | msleep(1000); |
866 | } | ||
867 | /* If we timed out on waiting for commands to come back | ||
868 | * return ERROR. */ | ||
869 | return QLA_ERROR; | ||
753 | } | 870 | } |
754 | 871 | ||
755 | void qla4xxx_hw_reset(struct scsi_qla_host *ha) | 872 | int qla4xxx_hw_reset(struct scsi_qla_host *ha) |
756 | { | 873 | { |
757 | uint32_t ctrl_status; | 874 | uint32_t ctrl_status; |
758 | unsigned long flags = 0; | 875 | unsigned long flags = 0; |
759 | 876 | ||
760 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); | 877 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); |
761 | 878 | ||
879 | if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) | ||
880 | return QLA_ERROR; | ||
881 | |||
762 | spin_lock_irqsave(&ha->hardware_lock, flags); | 882 | spin_lock_irqsave(&ha->hardware_lock, flags); |
763 | 883 | ||
764 | /* | 884 | /* |
@@ -774,6 +894,7 @@ void qla4xxx_hw_reset(struct scsi_qla_host *ha) | |||
774 | readl(&ha->reg->ctrl_status); | 894 | readl(&ha->reg->ctrl_status); |
775 | 895 | ||
776 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 896 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
897 | return QLA_SUCCESS; | ||
777 | } | 898 | } |
778 | 899 | ||
779 | /** | 900 | /** |
@@ -872,15 +993,16 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha) | |||
872 | } | 993 | } |
873 | 994 | ||
874 | /** | 995 | /** |
875 | * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. | 996 | * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S. |
876 | * @ha: Pointer to host adapter structure. | 997 | * @ha: Pointer to host adapter structure. |
998 | * @res: returned scsi status | ||
877 | * | 999 | * |
878 | * This routine is called just prior to a HARD RESET to return all | 1000 | * This routine is called just prior to a HARD RESET to return all |
879 | * outstanding commands back to the Operating System. | 1001 | * outstanding commands back to the Operating System. |
880 | * Caller should make sure that the following locks are released | 1002 | * Caller should make sure that the following locks are released |
881 | * before this calling routine: Hardware lock, and io_request_lock. | 1003 | * before this calling routine: Hardware lock, and io_request_lock. |
882 | **/ | 1004 | **/ |
883 | static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | 1005 | static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res) |
884 | { | 1006 | { |
885 | struct srb *srb; | 1007 | struct srb *srb; |
886 | int i; | 1008 | int i; |
@@ -890,74 +1012,116 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | |||
890 | for (i = 0; i < ha->host->can_queue; i++) { | 1012 | for (i = 0; i < ha->host->can_queue; i++) { |
891 | srb = qla4xxx_del_from_active_array(ha, i); | 1013 | srb = qla4xxx_del_from_active_array(ha, i); |
892 | if (srb != NULL) { | 1014 | if (srb != NULL) { |
893 | srb->cmd->result = DID_RESET << 16; | 1015 | srb->cmd->result = res; |
894 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); | 1016 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); |
895 | } | 1017 | } |
896 | } | 1018 | } |
897 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1019 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
898 | } | 1020 | } |
899 | 1021 | ||
1022 | void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) | ||
1023 | { | ||
1024 | clear_bit(AF_ONLINE, &ha->flags); | ||
1025 | |||
1026 | /* Disable the board */ | ||
1027 | ql4_printk(KERN_INFO, ha, "Disabling the board\n"); | ||
1028 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); | ||
1029 | |||
1030 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
1031 | qla4xxx_mark_all_devices_missing(ha); | ||
1032 | clear_bit(AF_INIT_DONE, &ha->flags); | ||
1033 | } | ||
1034 | |||
900 | /** | 1035 | /** |
901 | * qla4xxx_recover_adapter - recovers adapter after a fatal error | 1036 | * qla4xxx_recover_adapter - recovers adapter after a fatal error |
902 | * @ha: Pointer to host adapter structure. | 1037 | * @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 | **/ | 1038 | **/ |
908 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | 1039 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) |
909 | uint8_t renew_ddb_list) | ||
910 | { | 1040 | { |
911 | int status; | 1041 | int status = QLA_ERROR; |
1042 | uint8_t reset_chip = 0; | ||
912 | 1043 | ||
913 | /* Stall incoming I/O until we are done */ | 1044 | /* Stall incoming I/O until we are done */ |
1045 | scsi_block_requests(ha->host); | ||
914 | clear_bit(AF_ONLINE, &ha->flags); | 1046 | clear_bit(AF_ONLINE, &ha->flags); |
915 | 1047 | ||
916 | DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, | 1048 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__)); |
917 | __func__)); | ||
918 | 1049 | ||
919 | /* Wait for outstanding commands to complete. | 1050 | set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); |
920 | * Stalls the driver for max 30 secs | ||
921 | */ | ||
922 | status = qla4xxx_cmd_wait(ha); | ||
923 | 1051 | ||
924 | qla4xxx_disable_intrs(ha); | 1052 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
1053 | reset_chip = 1; | ||
925 | 1054 | ||
926 | /* Flush any pending ddb changed AENs */ | 1055 | /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific) |
927 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1056 | * do not reset adapter, jump to initialize_adapter */ |
1057 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
1058 | status = QLA_SUCCESS; | ||
1059 | goto recover_ha_init_adapter; | ||
1060 | } | ||
928 | 1061 | ||
929 | qla4xxx_flush_active_srbs(ha); | 1062 | /* For the ISP-82xx adapter, issue a stop_firmware if invoked |
1063 | * from eh_host_reset or ioctl module */ | ||
1064 | if (is_qla8022(ha) && !reset_chip && | ||
1065 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { | ||
1066 | |||
1067 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1068 | "scsi%ld: %s - Performing stop_firmware...\n", | ||
1069 | ha->host_no, __func__)); | ||
1070 | status = ha->isp_ops->reset_firmware(ha); | ||
1071 | if (status == QLA_SUCCESS) { | ||
1072 | qla4xxx_cmd_wait(ha); | ||
1073 | ha->isp_ops->disable_intrs(ha); | ||
1074 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
1075 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | ||
1076 | } else { | ||
1077 | /* If the stop_firmware fails then | ||
1078 | * reset the entire chip */ | ||
1079 | reset_chip = 1; | ||
1080 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1081 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1082 | } | ||
1083 | } | ||
930 | 1084 | ||
931 | /* Reset the firmware. If successful, function | 1085 | /* Issue full chip reset if recovering from a catastrophic error, |
932 | * returns with ISP interrupts enabled. | 1086 | * or if stop_firmware fails for ISP-82xx. |
933 | */ | 1087 | * This is the default case for ISP-4xxx */ |
934 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 1088 | if (!is_qla8022(ha) || reset_chip) { |
935 | ha->host_no, __func__)); | 1089 | qla4xxx_cmd_wait(ha); |
936 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1090 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
937 | status = qla4xxx_soft_reset(ha); | 1091 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
938 | else | 1092 | DEBUG2(ql4_printk(KERN_INFO, ha, |
939 | status = QLA_ERROR; | 1093 | "scsi%ld: %s - Performing chip reset..\n", |
1094 | ha->host_no, __func__)); | ||
1095 | status = ha->isp_ops->reset_chip(ha); | ||
1096 | } | ||
940 | 1097 | ||
941 | /* Flush any pending ddb changed AENs */ | 1098 | /* Flush any pending ddb changed AENs */ |
942 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1099 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
943 | 1100 | ||
944 | /* Re-initialize firmware. If successful, function returns | 1101 | recover_ha_init_adapter: |
945 | * with ISP interrupts enabled */ | 1102 | /* Upon successful firmware/chip reset, re-initialize the adapter */ |
946 | if (status == QLA_SUCCESS) { | 1103 | if (status == QLA_SUCCESS) { |
947 | DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n", | 1104 | /* For ISP-4xxx, force function 1 to always initialize |
948 | ha->host_no, __func__)); | 1105 | * before function 3 to prevent both funcions from |
949 | 1106 | * stepping on top of the other */ | |
950 | /* If successful, AF_ONLINE flag set in | 1107 | if (!is_qla8022(ha) && (ha->mac_index == 3)) |
951 | * qla4xxx_initialize_adapter */ | 1108 | ssleep(6); |
952 | status = qla4xxx_initialize_adapter(ha, renew_ddb_list); | 1109 | |
1110 | /* NOTE: AF_ONLINE flag set upon successful completion of | ||
1111 | * qla4xxx_initialize_adapter */ | ||
1112 | status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); | ||
953 | } | 1113 | } |
954 | 1114 | ||
955 | /* Failed adapter initialization? | 1115 | /* Retry failed adapter initialization, if necessary |
956 | * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */ | 1116 | * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific) |
957 | if ((test_bit(AF_ONLINE, &ha->flags) == 0) && | 1117 | * case to prevent ping-pong resets between functions */ |
958 | (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { | 1118 | if (!test_bit(AF_ONLINE, &ha->flags) && |
1119 | !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
959 | /* Adapter initialization failed, see if we can retry | 1120 | /* Adapter initialization failed, see if we can retry |
960 | * resetting the ha */ | 1121 | * resetting the ha. |
1122 | * Since we don't want to block the DPC for too long | ||
1123 | * with multiple resets in the same thread, | ||
1124 | * utilize DPC to retry */ | ||
961 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { | 1125 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { |
962 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; | 1126 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; |
963 | DEBUG2(printk("scsi%ld: recover adapter - retrying " | 1127 | DEBUG2(printk("scsi%ld: recover adapter - retrying " |
@@ -982,29 +1146,43 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
982 | DEBUG2(printk("scsi%ld: recover adapter " | 1146 | DEBUG2(printk("scsi%ld: recover adapter " |
983 | "failed - board disabled\n", | 1147 | "failed - board disabled\n", |
984 | ha->host_no)); | 1148 | ha->host_no)); |
985 | qla4xxx_flush_active_srbs(ha); | 1149 | qla4xxx_dead_adapter_cleanup(ha); |
986 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1150 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
987 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1151 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
988 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, | 1152 | clear_bit(DPC_RESET_HA_FW_CONTEXT, |
989 | &ha->dpc_flags); | 1153 | &ha->dpc_flags); |
990 | status = QLA_ERROR; | 1154 | status = QLA_ERROR; |
991 | } | 1155 | } |
992 | } | 1156 | } |
993 | } else { | 1157 | } else { |
994 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1158 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
995 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags); | 1159 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
996 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1160 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
997 | } | 1161 | } |
998 | 1162 | ||
999 | ha->adapter_error_count++; | 1163 | ha->adapter_error_count++; |
1000 | 1164 | ||
1001 | if (status == QLA_SUCCESS) | 1165 | if (test_bit(AF_ONLINE, &ha->flags)) |
1002 | qla4xxx_enable_intrs(ha); | 1166 | ha->isp_ops->enable_intrs(ha); |
1167 | |||
1168 | scsi_unblock_requests(ha->host); | ||
1169 | |||
1170 | clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
1171 | DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, | ||
1172 | status == QLA_ERROR ? "FAILED" : "SUCCEDED")); | ||
1003 | 1173 | ||
1004 | DEBUG2(printk("scsi%ld: recover adapter .. DONE\n", ha->host_no)); | ||
1005 | return status; | 1174 | return status; |
1006 | } | 1175 | } |
1007 | 1176 | ||
1177 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | ||
1178 | { | ||
1179 | if (ha->dpc_thread && | ||
1180 | !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { | ||
1181 | set_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1182 | queue_work(ha->dpc_thread, &ha->dpc_work); | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1008 | /** | 1186 | /** |
1009 | * qla4xxx_do_dpc - dpc routine | 1187 | * qla4xxx_do_dpc - dpc routine |
1010 | * @data: in our case pointer to adapter structure | 1188 | * @data: in our case pointer to adapter structure |
@@ -1024,21 +1202,47 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1024 | int status = QLA_ERROR; | 1202 | int status = QLA_ERROR; |
1025 | 1203 | ||
1026 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." | 1204 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." |
1027 | "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n", | 1205 | "flags = 0x%08lx, dpc_flags = 0x%08lx\n", |
1028 | ha->host_no, __func__, ha->flags, ha->dpc_flags, | 1206 | ha->host_no, __func__, ha->flags, ha->dpc_flags)) |
1029 | readw(&ha->reg->ctrl_status))); | ||
1030 | 1207 | ||
1031 | /* Initialization not yet finished. Don't do anything yet. */ | 1208 | /* Initialization not yet finished. Don't do anything yet. */ |
1032 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1209 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
1033 | return; | 1210 | return; |
1034 | 1211 | ||
1035 | if (adapter_up(ha) || | 1212 | /* HBA is in the process of being permanently disabled. |
1036 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 1213 | * Don't process anything */ |
1214 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) | ||
1215 | return; | ||
1216 | |||
1217 | if (is_qla8022(ha)) { | ||
1218 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { | ||
1219 | qla4_8xxx_idc_lock(ha); | ||
1220 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
1221 | QLA82XX_DEV_FAILED); | ||
1222 | qla4_8xxx_idc_unlock(ha); | ||
1223 | ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
1224 | qla4_8xxx_device_state_handler(ha); | ||
1225 | } | ||
1226 | if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
1227 | qla4_8xxx_need_qsnt_handler(ha); | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) && | ||
1232 | (test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
1037 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 1233 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
1038 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { | 1234 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) { |
1039 | if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 1235 | if (ql4xdontresethba) { |
1040 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | 1236 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", |
1041 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); | 1237 | ha->host_no, __func__)); |
1238 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1239 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | ||
1240 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1241 | goto dpc_post_reset_ha; | ||
1242 | } | ||
1243 | if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || | ||
1244 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | ||
1245 | qla4xxx_recover_adapter(ha); | ||
1042 | 1246 | ||
1043 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | 1247 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { |
1044 | uint8_t wait_time = RESET_INTR_TOV; | 1248 | uint8_t wait_time = RESET_INTR_TOV; |
@@ -1053,18 +1257,18 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1053 | DEBUG2(printk("scsi%ld: %s: SR|FSR " | 1257 | DEBUG2(printk("scsi%ld: %s: SR|FSR " |
1054 | "bit not cleared-- resetting\n", | 1258 | "bit not cleared-- resetting\n", |
1055 | ha->host_no, __func__)); | 1259 | ha->host_no, __func__)); |
1056 | qla4xxx_flush_active_srbs(ha); | 1260 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
1057 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { | 1261 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { |
1058 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1262 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
1059 | status = qla4xxx_initialize_adapter(ha, | 1263 | status = qla4xxx_recover_adapter(ha); |
1060 | PRESERVE_DDB_LIST); | ||
1061 | } | 1264 | } |
1062 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | 1265 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); |
1063 | if (status == QLA_SUCCESS) | 1266 | if (status == QLA_SUCCESS) |
1064 | qla4xxx_enable_intrs(ha); | 1267 | ha->isp_ops->enable_intrs(ha); |
1065 | } | 1268 | } |
1066 | } | 1269 | } |
1067 | 1270 | ||
1271 | dpc_post_reset_ha: | ||
1068 | /* ---- process AEN? --- */ | 1272 | /* ---- process AEN? --- */ |
1069 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | 1273 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) |
1070 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); | 1274 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); |
@@ -1102,13 +1306,11 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1102 | DDB_DS_SESSION_ACTIVE) { | 1306 | DDB_DS_SESSION_ACTIVE) { |
1103 | atomic_set(&ddb_entry->state, | 1307 | atomic_set(&ddb_entry->state, |
1104 | DDB_STATE_ONLINE); | 1308 | DDB_STATE_ONLINE); |
1105 | dev_info(&ha->pdev->dev, | 1309 | ql4_printk(KERN_INFO, ha, |
1106 | "scsi%ld: %s: ddb[%d]" | 1310 | "scsi%ld: %s: ddb[%d]" |
1107 | " os[%d] marked" | 1311 | " marked ONLINE\n", |
1108 | " ONLINE\n", | ||
1109 | ha->host_no, __func__, | 1312 | ha->host_no, __func__, |
1110 | ddb_entry->fw_ddb_index, | 1313 | ddb_entry->fw_ddb_index); |
1111 | ddb_entry->os_target_id); | ||
1112 | 1314 | ||
1113 | iscsi_unblock_session( | 1315 | iscsi_unblock_session( |
1114 | ddb_entry->sess); | 1316 | ddb_entry->sess); |
@@ -1144,6 +1346,7 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1144 | } | 1346 | } |
1145 | } | 1347 | } |
1146 | } | 1348 | } |
1349 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1147 | } | 1350 | } |
1148 | 1351 | ||
1149 | /** | 1352 | /** |
@@ -1155,30 +1358,99 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1155 | 1358 | ||
1156 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { | 1359 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { |
1157 | /* Turn-off interrupts on the card. */ | 1360 | /* Turn-off interrupts on the card. */ |
1158 | qla4xxx_disable_intrs(ha); | 1361 | ha->isp_ops->disable_intrs(ha); |
1159 | } | 1362 | } |
1160 | 1363 | ||
1364 | /* Remove timer thread, if present */ | ||
1365 | if (ha->timer_active) | ||
1366 | qla4xxx_stop_timer(ha); | ||
1367 | |||
1161 | /* Kill the kernel thread for this host */ | 1368 | /* Kill the kernel thread for this host */ |
1162 | if (ha->dpc_thread) | 1369 | if (ha->dpc_thread) |
1163 | destroy_workqueue(ha->dpc_thread); | 1370 | destroy_workqueue(ha->dpc_thread); |
1164 | 1371 | ||
1165 | /* Issue Soft Reset to put firmware in unknown state */ | 1372 | /* Put firmware in known state */ |
1166 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1373 | ha->isp_ops->reset_firmware(ha); |
1167 | qla4xxx_hw_reset(ha); | ||
1168 | 1374 | ||
1169 | /* Remove timer thread, if present */ | 1375 | if (is_qla8022(ha)) { |
1170 | if (ha->timer_active) | 1376 | qla4_8xxx_idc_lock(ha); |
1171 | qla4xxx_stop_timer(ha); | 1377 | qla4_8xxx_clear_drv_active(ha); |
1378 | qla4_8xxx_idc_unlock(ha); | ||
1379 | } | ||
1172 | 1380 | ||
1173 | /* Detach interrupts */ | 1381 | /* Detach interrupts */ |
1174 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) | 1382 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) |
1175 | free_irq(ha->pdev->irq, ha); | 1383 | qla4xxx_free_irqs(ha); |
1176 | 1384 | ||
1177 | /* free extra memory */ | 1385 | /* free extra memory */ |
1178 | qla4xxx_mem_free(ha); | 1386 | qla4xxx_mem_free(ha); |
1387 | } | ||
1388 | |||
1389 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) | ||
1390 | { | ||
1391 | int status = 0; | ||
1392 | uint8_t revision_id; | ||
1393 | unsigned long mem_base, mem_len, db_base, db_len; | ||
1394 | struct pci_dev *pdev = ha->pdev; | ||
1395 | |||
1396 | status = pci_request_regions(pdev, DRIVER_NAME); | ||
1397 | if (status) { | ||
1398 | printk(KERN_WARNING | ||
1399 | "scsi(%ld) Failed to reserve PIO regions (%s) " | ||
1400 | "status=%d\n", ha->host_no, pci_name(pdev), status); | ||
1401 | goto iospace_error_exit; | ||
1402 | } | ||
1403 | |||
1404 | pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id); | ||
1405 | DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n", | ||
1406 | __func__, revision_id)); | ||
1407 | ha->revision_id = revision_id; | ||
1408 | |||
1409 | /* remap phys address */ | ||
1410 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | ||
1411 | mem_len = pci_resource_len(pdev, 0); | ||
1412 | DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n", | ||
1413 | __func__, mem_base, mem_len)); | ||
1414 | |||
1415 | /* mapping of pcibase pointer */ | ||
1416 | ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len); | ||
1417 | if (!ha->nx_pcibase) { | ||
1418 | printk(KERN_ERR | ||
1419 | "cannot remap MMIO (%s), aborting\n", pci_name(pdev)); | ||
1420 | pci_release_regions(ha->pdev); | ||
1421 | goto iospace_error_exit; | ||
1422 | } | ||
1179 | 1423 | ||
1180 | pci_disable_device(ha->pdev); | 1424 | /* Mapping of IO base pointer, door bell read and write pointer */ |
1181 | 1425 | ||
1426 | /* mapping of IO base pointer */ | ||
1427 | ha->qla4_8xxx_reg = | ||
1428 | (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase + | ||
1429 | 0xbc000 + (ha->pdev->devfn << 11)); | ||
1430 | |||
1431 | db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ | ||
1432 | db_len = pci_resource_len(pdev, 4); | ||
1433 | |||
1434 | /* mapping of doorbell write pointer */ | ||
1435 | ha->nx_db_wr_ptr = (unsigned long)ioremap(db_base + | ||
1436 | (ha->pdev->devfn << 12), 4); | ||
1437 | if (!ha->nx_db_wr_ptr) { | ||
1438 | printk(KERN_ERR | ||
1439 | "cannot remap MMIO doorbell-write (%s), aborting\n", | ||
1440 | pci_name(pdev)); | ||
1441 | goto iospace_error_exit; | ||
1442 | } | ||
1443 | /* mapping of doorbell read pointer */ | ||
1444 | ha->nx_db_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + | ||
1445 | (ha->pdev->devfn * 8); | ||
1446 | if (!ha->nx_db_rd_ptr) | ||
1447 | printk(KERN_ERR | ||
1448 | "cannot remap MMIO doorbell-read (%s), aborting\n", | ||
1449 | pci_name(pdev)); | ||
1450 | return 0; | ||
1451 | |||
1452 | iospace_error_exit: | ||
1453 | return -ENOMEM; | ||
1182 | } | 1454 | } |
1183 | 1455 | ||
1184 | /*** | 1456 | /*** |
@@ -1188,7 +1460,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1188 | * This routines maps HBA's registers from the pci address space | 1460 | * This routines maps HBA's registers from the pci address space |
1189 | * into the kernel virtual address space for memory mapped i/o. | 1461 | * into the kernel virtual address space for memory mapped i/o. |
1190 | **/ | 1462 | **/ |
1191 | static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | 1463 | int qla4xxx_iospace_config(struct scsi_qla_host *ha) |
1192 | { | 1464 | { |
1193 | unsigned long pio, pio_len, pio_flags; | 1465 | unsigned long pio, pio_len, pio_flags; |
1194 | unsigned long mmio, mmio_len, mmio_flags; | 1466 | unsigned long mmio, mmio_len, mmio_flags; |
@@ -1198,12 +1470,12 @@ static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | |||
1198 | pio_flags = pci_resource_flags(ha->pdev, 0); | 1470 | pio_flags = pci_resource_flags(ha->pdev, 0); |
1199 | if (pio_flags & IORESOURCE_IO) { | 1471 | if (pio_flags & IORESOURCE_IO) { |
1200 | if (pio_len < MIN_IOBASE_LEN) { | 1472 | if (pio_len < MIN_IOBASE_LEN) { |
1201 | dev_warn(&ha->pdev->dev, | 1473 | ql4_printk(KERN_WARNING, ha, |
1202 | "Invalid PCI I/O region size\n"); | 1474 | "Invalid PCI I/O region size\n"); |
1203 | pio = 0; | 1475 | pio = 0; |
1204 | } | 1476 | } |
1205 | } else { | 1477 | } else { |
1206 | dev_warn(&ha->pdev->dev, "region #0 not a PIO resource\n"); | 1478 | ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n"); |
1207 | pio = 0; | 1479 | pio = 0; |
1208 | } | 1480 | } |
1209 | 1481 | ||
@@ -1213,20 +1485,21 @@ static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | |||
1213 | mmio_flags = pci_resource_flags(ha->pdev, 1); | 1485 | mmio_flags = pci_resource_flags(ha->pdev, 1); |
1214 | 1486 | ||
1215 | if (!(mmio_flags & IORESOURCE_MEM)) { | 1487 | if (!(mmio_flags & IORESOURCE_MEM)) { |
1216 | dev_err(&ha->pdev->dev, | 1488 | ql4_printk(KERN_ERR, ha, |
1217 | "region #0 not an MMIO resource, aborting\n"); | 1489 | "region #0 not an MMIO resource, aborting\n"); |
1218 | 1490 | ||
1219 | goto iospace_error_exit; | 1491 | goto iospace_error_exit; |
1220 | } | 1492 | } |
1493 | |||
1221 | if (mmio_len < MIN_IOBASE_LEN) { | 1494 | if (mmio_len < MIN_IOBASE_LEN) { |
1222 | dev_err(&ha->pdev->dev, | 1495 | ql4_printk(KERN_ERR, ha, |
1223 | "Invalid PCI mem region size, aborting\n"); | 1496 | "Invalid PCI mem region size, aborting\n"); |
1224 | goto iospace_error_exit; | 1497 | goto iospace_error_exit; |
1225 | } | 1498 | } |
1226 | 1499 | ||
1227 | if (pci_request_regions(ha->pdev, DRIVER_NAME)) { | 1500 | if (pci_request_regions(ha->pdev, DRIVER_NAME)) { |
1228 | dev_warn(&ha->pdev->dev, | 1501 | ql4_printk(KERN_WARNING, ha, |
1229 | "Failed to reserve PIO/MMIO regions\n"); | 1502 | "Failed to reserve PIO/MMIO regions\n"); |
1230 | 1503 | ||
1231 | goto iospace_error_exit; | 1504 | goto iospace_error_exit; |
1232 | } | 1505 | } |
@@ -1235,8 +1508,8 @@ static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | |||
1235 | ha->pio_length = pio_len; | 1508 | ha->pio_length = pio_len; |
1236 | ha->reg = ioremap(mmio, MIN_IOBASE_LEN); | 1509 | ha->reg = ioremap(mmio, MIN_IOBASE_LEN); |
1237 | if (!ha->reg) { | 1510 | if (!ha->reg) { |
1238 | dev_err(&ha->pdev->dev, | 1511 | ql4_printk(KERN_ERR, ha, |
1239 | "cannot remap MMIO, aborting\n"); | 1512 | "cannot remap MMIO, aborting\n"); |
1240 | 1513 | ||
1241 | goto iospace_error_exit; | 1514 | goto iospace_error_exit; |
1242 | } | 1515 | } |
@@ -1247,6 +1520,60 @@ iospace_error_exit: | |||
1247 | return -ENOMEM; | 1520 | return -ENOMEM; |
1248 | } | 1521 | } |
1249 | 1522 | ||
1523 | static struct isp_operations qla4xxx_isp_ops = { | ||
1524 | .iospace_config = qla4xxx_iospace_config, | ||
1525 | .pci_config = qla4xxx_pci_config, | ||
1526 | .disable_intrs = qla4xxx_disable_intrs, | ||
1527 | .enable_intrs = qla4xxx_enable_intrs, | ||
1528 | .start_firmware = qla4xxx_start_firmware, | ||
1529 | .intr_handler = qla4xxx_intr_handler, | ||
1530 | .interrupt_service_routine = qla4xxx_interrupt_service_routine, | ||
1531 | .reset_chip = qla4xxx_soft_reset, | ||
1532 | .reset_firmware = qla4xxx_hw_reset, | ||
1533 | .queue_iocb = qla4xxx_queue_iocb, | ||
1534 | .complete_iocb = qla4xxx_complete_iocb, | ||
1535 | .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, | ||
1536 | .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, | ||
1537 | .get_sys_info = qla4xxx_get_sys_info, | ||
1538 | }; | ||
1539 | |||
1540 | static struct isp_operations qla4_8xxx_isp_ops = { | ||
1541 | .iospace_config = qla4_8xxx_iospace_config, | ||
1542 | .pci_config = qla4_8xxx_pci_config, | ||
1543 | .disable_intrs = qla4_8xxx_disable_intrs, | ||
1544 | .enable_intrs = qla4_8xxx_enable_intrs, | ||
1545 | .start_firmware = qla4_8xxx_load_risc, | ||
1546 | .intr_handler = qla4_8xxx_intr_handler, | ||
1547 | .interrupt_service_routine = qla4_8xxx_interrupt_service_routine, | ||
1548 | .reset_chip = qla4_8xxx_isp_reset, | ||
1549 | .reset_firmware = qla4_8xxx_stop_firmware, | ||
1550 | .queue_iocb = qla4_8xxx_queue_iocb, | ||
1551 | .complete_iocb = qla4_8xxx_complete_iocb, | ||
1552 | .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out, | ||
1553 | .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in, | ||
1554 | .get_sys_info = qla4_8xxx_get_sys_info, | ||
1555 | }; | ||
1556 | |||
1557 | uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1558 | { | ||
1559 | return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out); | ||
1560 | } | ||
1561 | |||
1562 | uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1563 | { | ||
1564 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out)); | ||
1565 | } | ||
1566 | |||
1567 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1568 | { | ||
1569 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); | ||
1570 | } | ||
1571 | |||
1572 | uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1573 | { | ||
1574 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in)); | ||
1575 | } | ||
1576 | |||
1250 | /** | 1577 | /** |
1251 | * qla4xxx_probe_adapter - callback function to probe HBA | 1578 | * qla4xxx_probe_adapter - callback function to probe HBA |
1252 | * @pdev: pointer to pci_dev structure | 1579 | * @pdev: pointer to pci_dev structure |
@@ -1264,6 +1591,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1264 | struct scsi_qla_host *ha; | 1591 | struct scsi_qla_host *ha; |
1265 | uint8_t init_retry_count = 0; | 1592 | uint8_t init_retry_count = 0; |
1266 | char buf[34]; | 1593 | char buf[34]; |
1594 | struct qla4_8xxx_legacy_intr_set *nx_legacy_intr; | ||
1267 | 1595 | ||
1268 | if (pci_enable_device(pdev)) | 1596 | if (pci_enable_device(pdev)) |
1269 | return -1; | 1597 | return -1; |
@@ -1284,12 +1612,30 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1284 | ha->host = host; | 1612 | ha->host = host; |
1285 | ha->host_no = host->host_no; | 1613 | ha->host_no = host->host_no; |
1286 | 1614 | ||
1615 | /* Setup Runtime configurable options */ | ||
1616 | if (is_qla8022(ha)) { | ||
1617 | ha->isp_ops = &qla4_8xxx_isp_ops; | ||
1618 | rwlock_init(&ha->hw_lock); | ||
1619 | ha->qdr_sn_window = -1; | ||
1620 | ha->ddr_mn_window = -1; | ||
1621 | ha->curr_window = 255; | ||
1622 | ha->func_num = PCI_FUNC(ha->pdev->devfn); | ||
1623 | nx_legacy_intr = &legacy_intr[ha->func_num]; | ||
1624 | ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; | ||
1625 | ha->nx_legacy_intr.tgt_status_reg = | ||
1626 | nx_legacy_intr->tgt_status_reg; | ||
1627 | ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; | ||
1628 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; | ||
1629 | } else { | ||
1630 | ha->isp_ops = &qla4xxx_isp_ops; | ||
1631 | } | ||
1632 | |||
1287 | /* Configure PCI I/O space. */ | 1633 | /* Configure PCI I/O space. */ |
1288 | ret = qla4xxx_iospace_config(ha); | 1634 | ret = ha->isp_ops->iospace_config(ha); |
1289 | if (ret) | 1635 | if (ret) |
1290 | goto probe_failed; | 1636 | goto probe_failed_ioconfig; |
1291 | 1637 | ||
1292 | dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", | 1638 | ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n", |
1293 | pdev->device, pdev->irq, ha->reg); | 1639 | pdev->device, pdev->irq, ha->reg); |
1294 | 1640 | ||
1295 | qla4xxx_config_dma_addressing(ha); | 1641 | qla4xxx_config_dma_addressing(ha); |
@@ -1299,32 +1645,41 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1299 | INIT_LIST_HEAD(&ha->free_srb_q); | 1645 | INIT_LIST_HEAD(&ha->free_srb_q); |
1300 | 1646 | ||
1301 | mutex_init(&ha->mbox_sem); | 1647 | mutex_init(&ha->mbox_sem); |
1648 | init_completion(&ha->mbx_intr_comp); | ||
1302 | 1649 | ||
1303 | spin_lock_init(&ha->hardware_lock); | 1650 | spin_lock_init(&ha->hardware_lock); |
1304 | 1651 | ||
1305 | /* Allocate dma buffers */ | 1652 | /* Allocate dma buffers */ |
1306 | if (qla4xxx_mem_alloc(ha)) { | 1653 | if (qla4xxx_mem_alloc(ha)) { |
1307 | dev_warn(&ha->pdev->dev, | 1654 | ql4_printk(KERN_WARNING, ha, |
1308 | "[ERROR] Failed to allocate memory for adapter\n"); | 1655 | "[ERROR] Failed to allocate memory for adapter\n"); |
1309 | 1656 | ||
1310 | ret = -ENOMEM; | 1657 | ret = -ENOMEM; |
1311 | goto probe_failed; | 1658 | goto probe_failed; |
1312 | } | 1659 | } |
1313 | 1660 | ||
1661 | if (is_qla8022(ha)) | ||
1662 | (void) qla4_8xxx_get_flash_info(ha); | ||
1663 | |||
1314 | /* | 1664 | /* |
1315 | * Initialize the Host adapter request/response queues and | 1665 | * Initialize the Host adapter request/response queues and |
1316 | * firmware | 1666 | * firmware |
1317 | * NOTE: interrupts enabled upon successful completion | 1667 | * NOTE: interrupts enabled upon successful completion |
1318 | */ | 1668 | */ |
1319 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1669 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1320 | while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) { | 1670 | while ((!test_bit(AF_ONLINE, &ha->flags)) && |
1671 | init_retry_count++ < MAX_INIT_RETRIES) { | ||
1321 | DEBUG2(printk("scsi: %s: retrying adapter initialization " | 1672 | DEBUG2(printk("scsi: %s: retrying adapter initialization " |
1322 | "(%d)\n", __func__, init_retry_count)); | 1673 | "(%d)\n", __func__, init_retry_count)); |
1323 | qla4xxx_soft_reset(ha); | 1674 | |
1675 | if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) | ||
1676 | continue; | ||
1677 | |||
1324 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1678 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1325 | } | 1679 | } |
1326 | if (status == QLA_ERROR) { | 1680 | |
1327 | dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); | 1681 | if (!test_bit(AF_ONLINE, &ha->flags)) { |
1682 | ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); | ||
1328 | 1683 | ||
1329 | ret = -ENODEV; | 1684 | ret = -ENODEV; |
1330 | goto probe_failed; | 1685 | goto probe_failed; |
@@ -1340,8 +1695,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1340 | 1695 | ||
1341 | ret = scsi_init_shared_tag_map(host, MAX_SRBS); | 1696 | ret = scsi_init_shared_tag_map(host, MAX_SRBS); |
1342 | if (ret) { | 1697 | if (ret) { |
1343 | dev_warn(&ha->pdev->dev, "scsi_init_shared_tag_map failed\n"); | 1698 | ql4_printk(KERN_WARNING, ha, |
1344 | goto probe_failed; | 1699 | "scsi_init_shared_tag_map failed\n"); |
1700 | goto probe_failed; | ||
1345 | } | 1701 | } |
1346 | 1702 | ||
1347 | /* Startup the kernel thread for this host adapter. */ | 1703 | /* Startup the kernel thread for this host adapter. */ |
@@ -1350,24 +1706,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1350 | sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no); | 1706 | sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no); |
1351 | ha->dpc_thread = create_singlethread_workqueue(buf); | 1707 | ha->dpc_thread = create_singlethread_workqueue(buf); |
1352 | if (!ha->dpc_thread) { | 1708 | if (!ha->dpc_thread) { |
1353 | dev_warn(&ha->pdev->dev, "Unable to start DPC thread!\n"); | 1709 | ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); |
1354 | ret = -ENODEV; | 1710 | ret = -ENODEV; |
1355 | goto probe_failed; | 1711 | goto probe_failed; |
1356 | } | 1712 | } |
1357 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); | 1713 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); |
1358 | 1714 | ||
1359 | ret = request_irq(pdev->irq, qla4xxx_intr_handler, | 1715 | /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc |
1360 | IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha); | 1716 | * (which is called indirectly by qla4xxx_initialize_adapter), |
1361 | if (ret) { | 1717 | * so that irqs will be registered after crbinit but before |
1362 | dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d" | 1718 | * mbx_intr_enable. |
1363 | " already in use.\n", pdev->irq); | 1719 | */ |
1364 | goto probe_failed; | 1720 | if (!is_qla8022(ha)) { |
1721 | ret = qla4xxx_request_irqs(ha); | ||
1722 | if (ret) { | ||
1723 | ql4_printk(KERN_WARNING, ha, "Failed to reserve " | ||
1724 | "interrupt %d already in use.\n", pdev->irq); | ||
1725 | goto probe_failed; | ||
1726 | } | ||
1365 | } | 1727 | } |
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 | 1728 | ||
1370 | qla4xxx_enable_intrs(ha); | 1729 | ha->isp_ops->enable_intrs(ha); |
1371 | 1730 | ||
1372 | /* Start timer thread. */ | 1731 | /* Start timer thread. */ |
1373 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); | 1732 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); |
@@ -1391,6 +1750,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1391 | 1750 | ||
1392 | probe_failed: | 1751 | probe_failed: |
1393 | qla4xxx_free_adapter(ha); | 1752 | qla4xxx_free_adapter(ha); |
1753 | |||
1754 | probe_failed_ioconfig: | ||
1394 | scsi_host_put(ha->host); | 1755 | scsi_host_put(ha->host); |
1395 | 1756 | ||
1396 | probe_disable_device: | 1757 | probe_disable_device: |
@@ -1409,10 +1770,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1409 | 1770 | ||
1410 | ha = pci_get_drvdata(pdev); | 1771 | ha = pci_get_drvdata(pdev); |
1411 | 1772 | ||
1412 | qla4xxx_disable_intrs(ha); | 1773 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); |
1413 | |||
1414 | while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | ||
1415 | ssleep(1); | ||
1416 | 1774 | ||
1417 | /* remove devs from iscsi_sessions to scsi_devices */ | 1775 | /* remove devs from iscsi_sessions to scsi_devices */ |
1418 | qla4xxx_free_ddb_list(ha); | 1776 | qla4xxx_free_ddb_list(ha); |
@@ -1423,6 +1781,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1423 | 1781 | ||
1424 | scsi_host_put(ha->host); | 1782 | scsi_host_put(ha->host); |
1425 | 1783 | ||
1784 | pci_disable_device(pdev); | ||
1426 | pci_set_drvdata(pdev, NULL); | 1785 | pci_set_drvdata(pdev, NULL); |
1427 | } | 1786 | } |
1428 | 1787 | ||
@@ -1479,7 +1838,8 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) | |||
1479 | * | 1838 | * |
1480 | * This routine removes and returns the srb at the specified index | 1839 | * This routine removes and returns the srb at the specified index |
1481 | **/ | 1840 | **/ |
1482 | struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index) | 1841 | struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, |
1842 | uint32_t index) | ||
1483 | { | 1843 | { |
1484 | struct srb *srb = NULL; | 1844 | struct srb *srb = NULL; |
1485 | struct scsi_cmnd *cmd = NULL; | 1845 | struct scsi_cmnd *cmd = NULL; |
@@ -1605,7 +1965,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) | |||
1605 | int ret = SUCCESS; | 1965 | int ret = SUCCESS; |
1606 | int wait = 0; | 1966 | int wait = 0; |
1607 | 1967 | ||
1608 | dev_info(&ha->pdev->dev, | 1968 | ql4_printk(KERN_INFO, ha, |
1609 | "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n", | 1969 | "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n", |
1610 | ha->host_no, id, lun, cmd, serial); | 1970 | ha->host_no, id, lun, cmd, serial); |
1611 | 1971 | ||
@@ -1637,7 +1997,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) | |||
1637 | } | 1997 | } |
1638 | } | 1998 | } |
1639 | 1999 | ||
1640 | dev_info(&ha->pdev->dev, | 2000 | ql4_printk(KERN_INFO, ha, |
1641 | "scsi%ld:%d:%d: Abort command - %s\n", | 2001 | "scsi%ld:%d:%d: Abort command - %s\n", |
1642 | ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed"); | 2002 | ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed"); |
1643 | 2003 | ||
@@ -1660,7 +2020,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
1660 | if (!ddb_entry) | 2020 | if (!ddb_entry) |
1661 | return ret; | 2021 | return ret; |
1662 | 2022 | ||
1663 | dev_info(&ha->pdev->dev, | 2023 | ret = iscsi_block_scsi_eh(cmd); |
2024 | if (ret) | ||
2025 | return ret; | ||
2026 | ret = FAILED; | ||
2027 | |||
2028 | ql4_printk(KERN_INFO, ha, | ||
1664 | "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, | 2029 | "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, |
1665 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 2030 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
1666 | 2031 | ||
@@ -1673,13 +2038,13 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
1673 | /* FIXME: wait for hba to go online */ | 2038 | /* FIXME: wait for hba to go online */ |
1674 | stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); | 2039 | stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); |
1675 | if (stat != QLA_SUCCESS) { | 2040 | if (stat != QLA_SUCCESS) { |
1676 | dev_info(&ha->pdev->dev, "DEVICE RESET FAILED. %d\n", stat); | 2041 | ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat); |
1677 | goto eh_dev_reset_done; | 2042 | goto eh_dev_reset_done; |
1678 | } | 2043 | } |
1679 | 2044 | ||
1680 | if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), | 2045 | if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), |
1681 | cmd->device)) { | 2046 | cmd->device)) { |
1682 | dev_info(&ha->pdev->dev, | 2047 | ql4_printk(KERN_INFO, ha, |
1683 | "DEVICE RESET FAILED - waiting for " | 2048 | "DEVICE RESET FAILED - waiting for " |
1684 | "commands.\n"); | 2049 | "commands.\n"); |
1685 | goto eh_dev_reset_done; | 2050 | goto eh_dev_reset_done; |
@@ -1690,7 +2055,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
1690 | MM_LUN_RESET) != QLA_SUCCESS) | 2055 | MM_LUN_RESET) != QLA_SUCCESS) |
1691 | goto eh_dev_reset_done; | 2056 | goto eh_dev_reset_done; |
1692 | 2057 | ||
1693 | dev_info(&ha->pdev->dev, | 2058 | ql4_printk(KERN_INFO, ha, |
1694 | "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", | 2059 | "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", |
1695 | ha->host_no, cmd->device->channel, cmd->device->id, | 2060 | ha->host_no, cmd->device->channel, cmd->device->id, |
1696 | cmd->device->lun); | 2061 | cmd->device->lun); |
@@ -1712,11 +2077,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) | |||
1712 | { | 2077 | { |
1713 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 2078 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
1714 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 2079 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
1715 | int stat; | 2080 | int stat, ret; |
1716 | 2081 | ||
1717 | if (!ddb_entry) | 2082 | if (!ddb_entry) |
1718 | return FAILED; | 2083 | return FAILED; |
1719 | 2084 | ||
2085 | ret = iscsi_block_scsi_eh(cmd); | ||
2086 | if (ret) | ||
2087 | return ret; | ||
2088 | |||
1720 | starget_printk(KERN_INFO, scsi_target(cmd->device), | 2089 | starget_printk(KERN_INFO, scsi_target(cmd->device), |
1721 | "WARM TARGET RESET ISSUED.\n"); | 2090 | "WARM TARGET RESET ISSUED.\n"); |
1722 | 2091 | ||
@@ -1769,7 +2138,13 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1769 | 2138 | ||
1770 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; | 2139 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; |
1771 | 2140 | ||
1772 | dev_info(&ha->pdev->dev, | 2141 | if (ql4xdontresethba) { |
2142 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", | ||
2143 | ha->host_no, __func__)); | ||
2144 | return FAILED; | ||
2145 | } | ||
2146 | |||
2147 | ql4_printk(KERN_INFO, ha, | ||
1773 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, | 2148 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, |
1774 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 2149 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
1775 | 2150 | ||
@@ -1781,20 +2156,22 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1781 | return FAILED; | 2156 | return FAILED; |
1782 | } | 2157 | } |
1783 | 2158 | ||
1784 | /* make sure the dpc thread is stopped while we reset the hba */ | 2159 | if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
1785 | clear_bit(AF_ONLINE, &ha->flags); | 2160 | if (is_qla8022(ha)) |
1786 | flush_workqueue(ha->dpc_thread); | 2161 | set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
2162 | else | ||
2163 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2164 | } | ||
1787 | 2165 | ||
1788 | if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) | 2166 | if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) |
1789 | return_status = SUCCESS; | 2167 | return_status = SUCCESS; |
1790 | 2168 | ||
1791 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", | 2169 | ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n", |
1792 | return_status == FAILED ? "FAILED" : "SUCCEDED"); | 2170 | return_status == FAILED ? "FAILED" : "SUCCEDED"); |
1793 | 2171 | ||
1794 | return return_status; | 2172 | return return_status; |
1795 | } | 2173 | } |
1796 | 2174 | ||
1797 | |||
1798 | static struct pci_device_id qla4xxx_pci_tbl[] = { | 2175 | static struct pci_device_id qla4xxx_pci_tbl[] = { |
1799 | { | 2176 | { |
1800 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2177 | .vendor = PCI_VENDOR_ID_QLOGIC, |
@@ -1814,6 +2191,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { | |||
1814 | .subvendor = PCI_ANY_ID, | 2191 | .subvendor = PCI_ANY_ID, |
1815 | .subdevice = PCI_ANY_ID, | 2192 | .subdevice = PCI_ANY_ID, |
1816 | }, | 2193 | }, |
2194 | { | ||
2195 | .vendor = PCI_VENDOR_ID_QLOGIC, | ||
2196 | .device = PCI_DEVICE_ID_QLOGIC_ISP8022, | ||
2197 | .subvendor = PCI_ANY_ID, | ||
2198 | .subdevice = PCI_ANY_ID, | ||
2199 | }, | ||
1817 | {0, 0}, | 2200 | {0, 0}, |
1818 | }; | 2201 | }; |
1819 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); | 2202 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); |
@@ -1869,7 +2252,6 @@ no_srp_cache: | |||
1869 | 2252 | ||
1870 | static void __exit qla4xxx_module_exit(void) | 2253 | static void __exit qla4xxx_module_exit(void) |
1871 | { | 2254 | { |
1872 | ql4_mod_unload = 1; | ||
1873 | pci_unregister_driver(&qla4xxx_pci_driver); | 2255 | pci_unregister_driver(&qla4xxx_pci_driver); |
1874 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); | 2256 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); |
1875 | kmem_cache_destroy(srb_cachep); | 2257 | kmem_cache_destroy(srb_cachep); |