aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid C Somayajulu <david.somayajulu@qlogic.com>2007-01-22 15:26:11 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-01-27 10:15:46 -0500
commit477ffb9d8732f30e7ab2d20f6ed0c22bad37a4a5 (patch)
treed8633736db9eb4609d935bc5ff0c1a8fba5d07f4
parent938e2ac0b7ac72d264783b0b548eb6078c295294 (diff)
[SCSI] qla4xxx: bug fixes
The included patch fixes the following issues: 1. qla3xxx/qla4xxx co-existence issue which can result in a lockup when qla3xxx driver is unloaded, or when ifdown; ifup is performed on one of the interfaces correponding to qla3xxx. This is because qla4xxx HBA supports one ethernet and iscsi interfaces per port. Both iscsi and ethernet interfaces share the same state machine. The problem has to do with synchronizing access to the state machine in the event of a reset 2. mutex_lock() is sometimes not followed by mutex_unlock() prior to invoking a msleep() in qla4xxx_mailbox_command() Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c18
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c35
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c64
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
7 files changed, 73 insertions, 52 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 4249e52a5592..6f4cf2dd2f4a 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -418,7 +418,6 @@ struct scsi_qla_host {
418 * concurrently. 418 * concurrently.
419 */ 419 */
420 struct mutex mbox_sem; 420 struct mutex mbox_sem;
421 wait_queue_head_t mailbox_wait_queue;
422 421
423 /* temporary mailbox status registers */ 422 /* temporary mailbox status registers */
424 volatile uint8_t mbox_status_count; 423 volatile uint8_t mbox_status_count;
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 2122967bbf0b..e021eb5db2b2 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
76extern int ql4xextended_error_logging; 76extern int ql4xextended_error_logging;
77extern int ql4xdiscoverywait; 77extern int ql4xdiscoverywait;
78extern int ql4xdontresethba; 78extern int ql4xdontresethba;
79extern int ql4_mod_unload;
79#endif /* _QLA4x_GBL_H */ 80#endif /* _QLA4x_GBL_H */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index cc210f297a78..b907b06d72ab 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
958 return status; 958 return status;
959} 959}
960 960
961int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) 961int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
962{ 962{
963#define QL4_LOCK_DRVR_WAIT 300 963#define QL4_LOCK_DRVR_WAIT 30
964#define QL4_LOCK_DRVR_SLEEP 100 964#define QL4_LOCK_DRVR_SLEEP 1
965 965
966 int drvr_wait = QL4_LOCK_DRVR_WAIT; 966 int drvr_wait = QL4_LOCK_DRVR_WAIT;
967 while (drvr_wait) { 967 while (drvr_wait) {
968 if (ql4xxx_lock_drvr(a) == 0) { 968 if (ql4xxx_lock_drvr(ha) == 0) {
969 msleep(QL4_LOCK_DRVR_SLEEP); 969 ssleep(QL4_LOCK_DRVR_SLEEP);
970 if (drvr_wait) { 970 if (drvr_wait) {
971 DEBUG2(printk("scsi%ld: %s: Waiting for " 971 DEBUG2(printk("scsi%ld: %s: Waiting for "
972 "Global Init Semaphore...n", 972 "Global Init Semaphore(%d)...n",
973 a->host_no, 973 ha->host_no,
974 __func__)); 974 __func__, drvr_wait));
975 } 975 }
976 drvr_wait -= QL4_LOCK_DRVR_SLEEP; 976 drvr_wait -= QL4_LOCK_DRVR_SLEEP;
977 } else { 977 } else {
978 DEBUG2(printk("scsi%ld: %s: Global Init Semaphore " 978 DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
979 "acquired.n", a->host_no, __func__)); 979 "acquired.n", ha->host_no, __func__));
980 return QLA_SUCCESS; 980 return QLA_SUCCESS;
981 } 981 }
982 } 982 }
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index ef975e0dc87f..35b9e36a0e8d 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
433 readl(&ha->reg->mailbox[i]); 433 readl(&ha->reg->mailbox[i]);
434 434
435 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 435 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
436 wake_up(&ha->mailbox_wait_queue);
437 } 436 }
438 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { 437 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
439 /* Immediately process the AENs that don't require much work. 438 /* Immediately process the AENs that don't require much work.
@@ -686,7 +685,8 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
686 &ha->reg->ctrl_status); 685 &ha->reg->ctrl_status);
687 readl(&ha->reg->ctrl_status); 686 readl(&ha->reg->ctrl_status);
688 687
689 set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); 688 if (!ql4_mod_unload)
689 set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
690 690
691 break; 691 break;
692 } else if (intr_status & INTR_PENDING) { 692 } else if (intr_status & INTR_PENDING) {
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index b721dc5dd711..7f28657eef3f 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
29 u_long wait_count; 29 u_long wait_count;
30 uint32_t intr_status; 30 uint32_t intr_status;
31 unsigned long flags = 0; 31 unsigned long flags = 0;
32 DECLARE_WAITQUEUE(wait, current);
33
34 mutex_lock(&ha->mbox_sem);
35
36 /* Mailbox code active */
37 set_bit(AF_MBOX_COMMAND, &ha->flags);
38 32
39 /* Make sure that pointers are valid */ 33 /* Make sure that pointers are valid */
40 if (!mbx_cmd || !mbx_sts) { 34 if (!mbx_cmd || !mbx_sts) {
41 DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " 35 DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
42 "pointer\n", ha->host_no, __func__)); 36 "pointer\n", ha->host_no, __func__));
43 goto mbox_exit; 37 return status;
38 }
39 /* Mailbox code active */
40 wait_count = MBOX_TOV * 100;
41
42 while (wait_count--) {
43 mutex_lock(&ha->mbox_sem);
44 if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
45 set_bit(AF_MBOX_COMMAND, &ha->flags);
46 mutex_unlock(&ha->mbox_sem);
47 break;
48 }
49 mutex_unlock(&ha->mbox_sem);
50 if (!wait_count) {
51 DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
52 ha->host_no, __func__));
53 return status;
54 }
55 msleep(10);
44 } 56 }
45 57
46 /* To prevent overwriting mailbox registers for a command that has 58 /* To prevent overwriting mailbox registers for a command that has
@@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
73 spin_unlock_irqrestore(&ha->hardware_lock, flags); 85 spin_unlock_irqrestore(&ha->hardware_lock, flags);
74 86
75 /* Wait for completion */ 87 /* Wait for completion */
76 set_current_state(TASK_UNINTERRUPTIBLE);
77 add_wait_queue(&ha->mailbox_wait_queue, &wait);
78 88
79 /* 89 /*
80 * If we don't want status, don't wait for the mailbox command to 90 * If we don't want status, don't wait for the mailbox command to
@@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
83 */ 93 */
84 if (outCount == 0) { 94 if (outCount == 0) {
85 status = QLA_SUCCESS; 95 status = QLA_SUCCESS;
86 set_current_state(TASK_RUNNING);
87 remove_wait_queue(&ha->mailbox_wait_queue, &wait);
88 goto mbox_exit; 96 goto mbox_exit;
89 } 97 }
90 /* Wait for command to complete */ 98 /* Wait for command to complete */
@@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
108 spin_unlock_irqrestore(&ha->hardware_lock, flags); 116 spin_unlock_irqrestore(&ha->hardware_lock, flags);
109 msleep(10); 117 msleep(10);
110 } 118 }
111 set_current_state(TASK_RUNNING);
112 remove_wait_queue(&ha->mailbox_wait_queue, &wait);
113 119
114 /* Check for mailbox timeout. */ 120 /* Check for mailbox timeout. */
115 if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { 121 if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
@@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
155 spin_unlock_irqrestore(&ha->hardware_lock, flags); 161 spin_unlock_irqrestore(&ha->hardware_lock, flags);
156 162
157mbox_exit: 163mbox_exit:
164 mutex_lock(&ha->mbox_sem);
158 clear_bit(AF_MBOX_COMMAND, &ha->flags); 165 clear_bit(AF_MBOX_COMMAND, &ha->flags);
159 clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
160 mutex_unlock(&ha->mbox_sem); 166 mutex_unlock(&ha->mbox_sem);
167 clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
161 168
162 return status; 169 return status;
163} 170}
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 9ef693c8809a..81fb7bd44f01 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -40,6 +40,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
40 "Option to enable extended error logging, " 40 "Option to enable extended error logging, "
41 "Default is 0 - no logging, 1 - debug logging"); 41 "Default is 0 - no logging, 1 - debug logging");
42 42
43int ql4_mod_unload = 0;
44
43/* 45/*
44 * SCSI host template entry points 46 * SCSI host template entry points
45 */ 47 */
@@ -422,6 +424,9 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
422 goto qc_host_busy; 424 goto qc_host_busy;
423 } 425 }
424 426
427 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
428 goto qc_host_busy;
429
425 spin_unlock_irq(ha->host->host_lock); 430 spin_unlock_irq(ha->host->host_lock);
426 431
427 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done); 432 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
@@ -707,16 +712,12 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
707 return stat; 712 return stat;
708} 713}
709 714
710/** 715static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
711 * qla4xxx_soft_reset - performs soft reset.
712 * @ha: Pointer to host adapter structure.
713 **/
714int qla4xxx_soft_reset(struct scsi_qla_host *ha)
715{ 716{
716 uint32_t max_wait_time;
717 unsigned long flags = 0;
718 int status = QLA_ERROR;
719 uint32_t ctrl_status; 717 uint32_t ctrl_status;
718 unsigned long flags = 0;
719
720 DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
720 721
721 spin_lock_irqsave(&ha->hardware_lock, flags); 722 spin_lock_irqsave(&ha->hardware_lock, flags);
722 723
@@ -733,6 +734,20 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha)
733 readl(&ha->reg->ctrl_status); 734 readl(&ha->reg->ctrl_status);
734 735
735 spin_unlock_irqrestore(&ha->hardware_lock, flags); 736 spin_unlock_irqrestore(&ha->hardware_lock, flags);
737}
738
739/**
740 * qla4xxx_soft_reset - performs soft reset.
741 * @ha: Pointer to host adapter structure.
742 **/
743int qla4xxx_soft_reset(struct scsi_qla_host *ha)
744{
745 uint32_t max_wait_time;
746 unsigned long flags = 0;
747 int status = QLA_ERROR;
748 uint32_t ctrl_status;
749
750 qla4xxx_hw_reset(ha);
736 751
737 /* Wait until the Network Reset Intr bit is cleared */ 752 /* Wait until the Network Reset Intr bit is cleared */
738 max_wait_time = RESET_INTR_TOV; 753 max_wait_time = RESET_INTR_TOV;
@@ -966,10 +981,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
966 struct scsi_qla_host *ha = 981 struct scsi_qla_host *ha =
967 container_of(work, struct scsi_qla_host, dpc_work); 982 container_of(work, struct scsi_qla_host, dpc_work);
968 struct ddb_entry *ddb_entry, *dtemp; 983 struct ddb_entry *ddb_entry, *dtemp;
984 int status = QLA_ERROR;
969 985
970 DEBUG2(printk("scsi%ld: %s: DPC handler waking up." 986 DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
971 "flags = 0x%08lx, dpc_flags = 0x%08lx\n", 987 "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
972 ha->host_no, __func__, ha->flags, ha->dpc_flags)); 988 ha->host_no, __func__, ha->flags, ha->dpc_flags,
989 readw(&ha->reg->ctrl_status)));
973 990
974 /* Initialization not yet finished. Don't do anything yet. */ 991 /* Initialization not yet finished. Don't do anything yet. */
975 if (!test_bit(AF_INIT_DONE, &ha->flags)) 992 if (!test_bit(AF_INIT_DONE, &ha->flags))
@@ -983,31 +1000,28 @@ static void qla4xxx_do_dpc(struct work_struct *work)
983 test_bit(DPC_RESET_HA, &ha->dpc_flags)) 1000 test_bit(DPC_RESET_HA, &ha->dpc_flags))
984 qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); 1001 qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
985 1002
986 if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { 1003 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
987 uint8_t wait_time = RESET_INTR_TOV; 1004 uint8_t wait_time = RESET_INTR_TOV;
988 unsigned long flags = 0;
989
990 qla4xxx_flush_active_srbs(ha);
991 1005
992 spin_lock_irqsave(&ha->hardware_lock, flags);
993 while ((readw(&ha->reg->ctrl_status) & 1006 while ((readw(&ha->reg->ctrl_status) &
994 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) { 1007 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
995 if (--wait_time == 0) 1008 if (--wait_time == 0)
996 break; 1009 break;
997
998 spin_unlock_irqrestore(&ha->hardware_lock,
999 flags);
1000
1001 msleep(1000); 1010 msleep(1000);
1002
1003 spin_lock_irqsave(&ha->hardware_lock, flags);
1004 } 1011 }
1005 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1006
1007 if (wait_time == 0) 1012 if (wait_time == 0)
1008 DEBUG2(printk("scsi%ld: %s: SR|FSR " 1013 DEBUG2(printk("scsi%ld: %s: SR|FSR "
1009 "bit not cleared-- resetting\n", 1014 "bit not cleared-- resetting\n",
1010 ha->host_no, __func__)); 1015 ha->host_no, __func__));
1016 qla4xxx_flush_active_srbs(ha);
1017 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
1018 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1019 status = qla4xxx_initialize_adapter(ha,
1020 PRESERVE_DDB_LIST);
1021 }
1022 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1023 if (status == QLA_SUCCESS)
1024 qla4xxx_enable_intrs(ha);
1011 } 1025 }
1012 } 1026 }
1013 1027
@@ -1062,7 +1076,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
1062 1076
1063 /* Issue Soft Reset to put firmware in unknown state */ 1077 /* Issue Soft Reset to put firmware in unknown state */
1064 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) 1078 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
1065 qla4xxx_soft_reset(ha); 1079 qla4xxx_hw_reset(ha);
1066 1080
1067 /* Remove timer thread, if present */ 1081 /* Remove timer thread, if present */
1068 if (ha->timer_active) 1082 if (ha->timer_active)
@@ -1198,7 +1212,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
1198 INIT_LIST_HEAD(&ha->free_srb_q); 1212 INIT_LIST_HEAD(&ha->free_srb_q);
1199 1213
1200 mutex_init(&ha->mbox_sem); 1214 mutex_init(&ha->mbox_sem);
1201 init_waitqueue_head(&ha->mailbox_wait_queue);
1202 1215
1203 spin_lock_init(&ha->hardware_lock); 1216 spin_lock_init(&ha->hardware_lock);
1204 1217
@@ -1665,6 +1678,7 @@ no_srp_cache:
1665 1678
1666static void __exit qla4xxx_module_exit(void) 1679static void __exit qla4xxx_module_exit(void)
1667{ 1680{
1681 ql4_mod_unload = 1;
1668 pci_unregister_driver(&qla4xxx_pci_driver); 1682 pci_unregister_driver(&qla4xxx_pci_driver);
1669 iscsi_unregister_transport(&qla4xxx_iscsi_transport); 1683 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
1670 kmem_cache_destroy(srb_cachep); 1684 kmem_cache_destroy(srb_cachep);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 454e19c8ad68..e5183a697d1f 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
5 * See LICENSE.qla4xxx for copyright and licensing details. 5 * See LICENSE.qla4xxx for copyright and licensing details.
6 */ 6 */
7 7
8#define QLA4XXX_DRIVER_VERSION "5.00.07-k" 8#define QLA4XXX_DRIVER_VERSION "5.00.07-k1"