return res;
 }
 
+static int eh_reset_phy_helper(struct sas_phy *phy)
+{
+       int tmf_resp;
+
+       tmf_resp = sas_phy_reset(phy, 1);
+       if (tmf_resp)
+               SAS_DPRINTK("Hard reset of phy %d failed 0x%x\n",
+                           phy->identify.phy_identifier,
+                           tmf_resp);
+
+       return tmf_resp;
+}
+
 void sas_scsi_recover_host(struct Scsi_Host *shost)
 {
        struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
        LIST_HEAD(error_q);
        struct scsi_cmnd *cmd, *n;
        enum task_disposition res = TASK_IS_DONE;
-       int tmf_resp;
+       int tmf_resp, need_reset;
        struct sas_internal *i = to_sas_internal(shost->transportt);
+       struct sas_phy *task_sas_phy = NULL;
 
        spin_lock_irqsave(shost->host_lock, flags);
        list_splice_init(&shost->eh_cmd_q, &error_q);
                        SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
                        continue;
                }
+
+               spin_lock_irqsave(&task->task_state_lock, flags);
+               need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
+               if (need_reset)
+                       task_sas_phy = task->dev->port->phy;
+               spin_unlock_irqrestore(&task->task_state_lock, flags);
+
                SAS_DPRINTK("trying to find task 0x%p\n", task);
                res = sas_scsi_find_task(task);
 
                        SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
                                    task);
                        task->task_done(task);
+                       if (need_reset)
+                               eh_reset_phy_helper(task_sas_phy);
                        continue;
                case TASK_IS_ABORTED:
                        SAS_DPRINTK("%s: task 0x%p is aborted\n",
                                    __FUNCTION__, task);
                        task->task_done(task);
+                       if (need_reset)
+                               eh_reset_phy_helper(task_sas_phy);
                        continue;
                case TASK_IS_AT_LU:
                        SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
                                            SAS_ADDR(task->dev),
                                            cmd->device->lun);
                                task->task_done(task);
+                               if (need_reset)
+                                       eh_reset_phy_helper(task_sas_phy);
                                sas_scsi_clear_queue_lu(&error_q, cmd);
                                goto Again;
                        }
                                SAS_DPRINTK("I_T %016llx recovered\n",
                                            SAS_ADDR(task->dev->sas_addr));
                                task->task_done(task);
+                               if (need_reset)
+                                       eh_reset_phy_helper(task_sas_phy);
                                sas_scsi_clear_queue_I_T(&error_q, task->dev);
                                goto Again;
                        }
                                        SAS_DPRINTK("clear nexus port:%d "
                                                    "succeeded\n", port->id);
                                        task->task_done(task);
+                                       if (need_reset)
+                                               eh_reset_phy_helper(task_sas_phy);
                                        sas_scsi_clear_queue_port(&error_q,
                                                                  port);
                                        goto Again;
                                        SAS_DPRINTK("clear nexus ha "
                                                    "succeeded\n");
                                        task->task_done(task);
+                                       if (need_reset)
+                                               eh_reset_phy_helper(task_sas_phy);
                                        goto out;
                                }
                        }
                                    cmd->device->lun);
 
                        task->task_done(task);
+                       if (need_reset)
+                               eh_reset_phy_helper(task_sas_phy);
                        goto clear_q;
                }
        }