return status;
 }
 
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
 {
-#define QL4_LOCK_DRVR_WAIT     300
-#define QL4_LOCK_DRVR_SLEEP    100
+#define QL4_LOCK_DRVR_WAIT     30
+#define QL4_LOCK_DRVR_SLEEP    1
 
        int drvr_wait = QL4_LOCK_DRVR_WAIT;
        while (drvr_wait) {
-               if (ql4xxx_lock_drvr(a) == 0) {
-                       msleep(QL4_LOCK_DRVR_SLEEP);
+               if (ql4xxx_lock_drvr(ha) == 0) {
+                       ssleep(QL4_LOCK_DRVR_SLEEP);
                        if (drvr_wait) {
                                DEBUG2(printk("scsi%ld: %s: Waiting for "
-                                             "Global Init Semaphore...n",
-                                             a->host_no,
-                                             __func__));
+                                             "Global Init Semaphore(%d)...n",
+                                             ha->host_no,
+                                             __func__, drvr_wait));
                        }
                        drvr_wait -= QL4_LOCK_DRVR_SLEEP;
                } else {
                        DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
-                                     "acquired.n", a->host_no, __func__));
+                                     "acquired.n", ha->host_no, __func__));
                        return QLA_SUCCESS;
                }
        }
 
        u_long wait_count;
        uint32_t intr_status;
        unsigned long flags = 0;
-       DECLARE_WAITQUEUE(wait, current);
-
-       mutex_lock(&ha->mbox_sem);
-
-       /* Mailbox code active */
-       set_bit(AF_MBOX_COMMAND, &ha->flags);
 
        /* Make sure that pointers are valid */
        if (!mbx_cmd || !mbx_sts) {
                DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
                              "pointer\n", ha->host_no, __func__));
-               goto mbox_exit;
+               return status;
+       }
+       /* Mailbox code active */
+       wait_count = MBOX_TOV * 100;
+
+       while (wait_count--) {
+               mutex_lock(&ha->mbox_sem);
+               if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
+                       set_bit(AF_MBOX_COMMAND, &ha->flags);
+                       mutex_unlock(&ha->mbox_sem);
+                       break;
+               }
+               mutex_unlock(&ha->mbox_sem);
+               if (!wait_count) {
+                       DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
+                               ha->host_no, __func__));
+                       return status;
+               }
+               msleep(10);
        }
 
        /* To prevent overwriting mailbox registers for a command that has
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Wait for completion */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&ha->mailbox_wait_queue, &wait);
 
        /*
         * If we don't want status, don't wait for the mailbox command to
         */
        if (outCount == 0) {
                status = QLA_SUCCESS;
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&ha->mailbox_wait_queue, &wait);
                goto mbox_exit;
        }
        /* Wait for command to complete */
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                msleep(10);
        }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&ha->mailbox_wait_queue, &wait);
 
        /* Check for mailbox timeout. */
        if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 mbox_exit:
+       mutex_lock(&ha->mbox_sem);
        clear_bit(AF_MBOX_COMMAND, &ha->flags);
-       clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
        mutex_unlock(&ha->mbox_sem);
+       clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
 
        return status;
 }
 
                 "Option to enable extended error logging, "
                 "Default is 0 - no logging, 1 - debug logging");
 
+int ql4_mod_unload = 0;
+
 /*
  * SCSI host template entry points
  */
                goto qc_host_busy;
        }
 
+       if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+               goto qc_host_busy;
+
        spin_unlock_irq(ha->host->host_lock);
 
        srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
        return stat;
 }
 
-/**
- * qla4xxx_soft_reset - performs soft reset.
- * @ha: Pointer to host adapter structure.
- **/
-int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
 {
-       uint32_t max_wait_time;
-       unsigned long flags = 0;
-       int status = QLA_ERROR;
        uint32_t ctrl_status;
+       unsigned long flags = 0;
+
+       DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
        readl(&ha->reg->ctrl_status);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+/**
+ * qla4xxx_soft_reset - performs soft reset.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+{
+       uint32_t max_wait_time;
+       unsigned long flags = 0;
+       int status = QLA_ERROR;
+       uint32_t ctrl_status;
+
+       qla4xxx_hw_reset(ha);
 
        /* Wait until the Network Reset Intr bit is cleared */
        max_wait_time = RESET_INTR_TOV;
        struct scsi_qla_host *ha =
                container_of(work, struct scsi_qla_host, dpc_work);
        struct ddb_entry *ddb_entry, *dtemp;
+       int status = QLA_ERROR;
 
        DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
-               "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
-               ha->host_no, __func__, ha->flags, ha->dpc_flags));
+               "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
+               ha->host_no, __func__, ha->flags, ha->dpc_flags,
+               readw(&ha->reg->ctrl_status)));
 
        /* Initialization not yet finished. Don't do anything yet. */
        if (!test_bit(AF_INIT_DONE, &ha->flags))
                        test_bit(DPC_RESET_HA, &ha->dpc_flags))
                        qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
 
-               if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
+               if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
                        uint8_t wait_time = RESET_INTR_TOV;
-                       unsigned long flags = 0;
-
-                       qla4xxx_flush_active_srbs(ha);
 
-                       spin_lock_irqsave(&ha->hardware_lock, flags);
                        while ((readw(&ha->reg->ctrl_status) &
                                (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
                                if (--wait_time == 0)
                                        break;
-
-                               spin_unlock_irqrestore(&ha->hardware_lock,
-                                                      flags);
-
                                msleep(1000);
-
-                               spin_lock_irqsave(&ha->hardware_lock, flags);
                        }
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
                        if (wait_time == 0)
                                DEBUG2(printk("scsi%ld: %s: SR|FSR "
                                              "bit not cleared-- resetting\n",
                                              ha->host_no, __func__));
+                       qla4xxx_flush_active_srbs(ha);
+                       if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
+                               qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+                               status = qla4xxx_initialize_adapter(ha,
+                                               PRESERVE_DDB_LIST);
+                       }
+                       clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+                       if (status == QLA_SUCCESS)
+                               qla4xxx_enable_intrs(ha);
                }
        }
 
 
        /* Issue Soft Reset to put firmware in unknown state */
        if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
-               qla4xxx_soft_reset(ha);
+               qla4xxx_hw_reset(ha);
 
        /* Remove timer thread, if present */
        if (ha->timer_active)
        INIT_LIST_HEAD(&ha->free_srb_q);
 
        mutex_init(&ha->mbox_sem);
-       init_waitqueue_head(&ha->mailbox_wait_queue);
 
        spin_lock_init(&ha->hardware_lock);
 
 
 static void __exit qla4xxx_module_exit(void)
 {
+       ql4_mod_unload = 1;
        pci_unregister_driver(&qla4xxx_pci_driver);
        iscsi_unregister_transport(&qla4xxx_iscsi_transport);
        kmem_cache_destroy(srb_cachep);