]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/scsi/qla2xxx/qla_init.c
[SCSI] qla2xxx: The ISP82XX should be online while waiting for commands completion.
[karo-tx-linux.git] / drivers / scsi / qla2xxx / qla_init.c
index 259f511374933cb4d7463098c26e746809e75d1b..85b86b82b964ae8f73fce4edd07de524e5f07dcb 100644 (file)
@@ -498,6 +498,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        vha->flags.reset_active = 0;
        ha->flags.pci_channel_io_perm_failure = 0;
        ha->flags.eeh_busy = 0;
+       ha->flags.thermal_supported = 1;
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
        atomic_set(&vha->loop_state, LOOP_DOWN);
        vha->device_flags = DFLG_NO_CABLE;
@@ -1966,7 +1967,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
                } else {
                        /* Mailbox cmd failed. Timeout on min_wait. */
                        if (time_after_eq(jiffies, mtime) ||
-                           (IS_QLA82XX(ha) && ha->flags.fw_hung))
+                               ha->flags.isp82xx_fw_hung)
                                break;
                }
 
@@ -2023,6 +2024,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
            &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
        if (rval != QLA_SUCCESS) {
                if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
+                   IS_QLA8XXX_TYPE(ha) ||
                    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
                        DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
                            __func__, vha->host_no));
@@ -2928,6 +2930,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
        fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
 
        qla2x00_iidma_fcport(vha, fcport);
+       qla24xx_update_fcport_fcp_prio(vha, fcport);
        qla2x00_reg_remote_port(vha, fcport);
        atomic_set(&fcport->state, FCS_ONLINE);
 }
@@ -3844,6 +3847,37 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
        return (rval);
 }
 
+/*
+* qla2x00_perform_loop_resync
+* Description: This function will set the appropriate flags and call
+*              qla2x00_loop_resync. If successful loop will be resynced
+* Arguments : scsi_qla_host_t pointer
+* returm    : Success or Failure
+*/
+
+int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
+{
+       int32_t rval = 0;
+
+       if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
+               /*Configure the flags so that resync happens properly*/
+               atomic_set(&ha->loop_down_timer, 0);
+               if (!(ha->device_flags & DFLG_NO_CABLE)) {
+                       atomic_set(&ha->loop_state, LOOP_UP);
+                       set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+                       set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+                       set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+
+                       rval = qla2x00_loop_resync(ha);
+               } else
+                       atomic_set(&ha->loop_state, LOOP_DEAD);
+
+               clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
+       }
+
+       return rval;
+}
+
 void
 qla2x00_update_fcports(scsi_qla_host_t *base_vha)
 {
@@ -3857,7 +3891,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
        list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
                atomic_inc(&vha->vref_count);
                list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       if (fcport && fcport->drport &&
+                       if (fcport->drport &&
                            atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
                                spin_unlock_irqrestore(&ha->vport_slock, flags);
 
@@ -3871,14 +3905,51 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
        spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
+/*
+* qla82xx_quiescent_state_cleanup
+* Description: This function will block the new I/Os
+*              Its not aborting any I/Os as context
+*              is not destroyed during quiescence
+* Arguments: scsi_qla_host_t
+* return   : void
+*/
+void
+qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
+{
+       struct qla_hw_data *ha = vha->hw;
+       struct scsi_qla_host *vp;
+
+       qla_printk(KERN_INFO, ha,
+                       "Performing ISP error recovery - ha= %p.\n", ha);
+
+       atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+       if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
+               atomic_set(&vha->loop_state, LOOP_DOWN);
+               qla2x00_mark_all_devices_lost(vha, 0);
+               list_for_each_entry(vp, &ha->vp_list, list)
+                       qla2x00_mark_all_devices_lost(vha, 0);
+       } else {
+               if (!atomic_read(&vha->loop_down_timer))
+                       atomic_set(&vha->loop_down_timer,
+                                       LOOP_DOWN_TIME);
+       }
+       /* Wait for pending cmds to complete */
+       qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
+}
+
 void
 qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
-       struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
+       struct scsi_qla_host *vp;
        unsigned long flags;
+       fc_port_t *fcport;
 
-       vha->flags.online = 0;
+       /* For ISP82XX, driver waits for completion of the commands.
+        * online flag should be set.
+        */
+       if (!IS_QLA82XX(ha))
+               vha->flags.online = 0;
        ha->flags.chip_reset_done = 0;
        clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
        ha->qla_stats.total_isp_aborts++;
@@ -3886,7 +3957,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        qla_printk(KERN_INFO, ha,
            "Performing ISP error recovery - ha= %p.\n", ha);
 
-       /* Chip reset does not apply to 82XX */
+       /* For ISP82XX, reset_chip is just disabling interrupts.
+        * Driver waits for the completion of the commands.
+        * the interrupts need to be enabled.
+        */
        if (!IS_QLA82XX(ha))
                ha->isp_ops->reset_chip(vha);
 
@@ -3896,7 +3970,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
                qla2x00_mark_all_devices_lost(vha, 0);
 
                spin_lock_irqsave(&ha->vport_slock, flags);
-               list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
+               list_for_each_entry(vp, &ha->vp_list, list) {
                        atomic_inc(&vp->vref_count);
                        spin_unlock_irqrestore(&ha->vport_slock, flags);
 
@@ -3912,14 +3986,31 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
                            LOOP_DOWN_TIME);
        }
 
+       /* Clear all async request states across all VPs. */
+       list_for_each_entry(fcport, &vha->vp_fcports, list)
+               fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       list_for_each_entry(vp, &ha->vp_list, list) {
+               atomic_inc(&vp->vref_count);
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+               list_for_each_entry(fcport, &vp->vp_fcports, list)
+                       fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               atomic_dec(&vp->vref_count);
+       }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        if (!ha->flags.eeh_busy) {
                /* Make sure for ISP 82XX IO DMA is complete */
                if (IS_QLA82XX(ha)) {
-                       if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
-                               WAIT_HOST) == QLA_SUCCESS) {
-                               DEBUG2(qla_printk(KERN_INFO, ha,
-                               "Done wait for pending commands\n"));
-                       }
+                       qla82xx_chip_reset_cleanup(vha);
+
+                       /* Done waiting for pending commands.
+                        * Reset the online flag.
+                        */
+                       vha->flags.online = 0;
                }
 
                /* Requeue all commands in outstanding command list. */
@@ -5410,7 +5501,7 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
  *     the tag (priority) value is returned.
  *
  * Input:
- *     ha = adapter block po
+ *     vha = scsi host structure pointer.
  *     fcport = port structure pointer.
  *
  * Return:
@@ -5504,7 +5595,7 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
  *     Activates fcp priority for the logged in fc port
  *
  * Input:
- *     ha = adapter block pointer.
+ *     vha = scsi host structure pointer.
  *     fcp = port structure pointer.
  *
  * Return:
@@ -5514,25 +5605,24 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
  *     Kernel context.
  */
 int
-qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport)
+qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
 {
        int ret;
        uint8_t priority;
        uint16_t mb[5];
 
-       if (atomic_read(&fcport->state) == FCS_UNCONFIGURED ||
-               fcport->port_type != FCT_TARGET ||
-               fcport->loop_id == FC_NO_LOOP_ID)
+       if (fcport->port_type != FCT_TARGET ||
+           fcport->loop_id == FC_NO_LOOP_ID)
                return QLA_FUNCTION_FAILED;
 
-       priority = qla24xx_get_fcp_prio(ha, fcport);
-       ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb);
+       priority = qla24xx_get_fcp_prio(vha, fcport);
+       ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
        if (ret == QLA_SUCCESS)
                fcport->fcp_prio = priority;
        else
                DEBUG2(printk(KERN_WARNING
                        "scsi(%ld): Unable to activate fcp priority, "
-                       " ret=0x%x\n", ha->host_no, ret));
+                       " ret=0x%x\n", vha->host_no, ret));
 
        return  ret;
 }