mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
[SCSI] libsas: fix mixed topology recovery
If we have a domain with sas and sata devices there may still be sas recovery actions to take after peeling off the commands to send to libata. Reported-by: Andrzej Jakowski <andrzej.jakowski@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
8abda4d28a
commit
d230ce691c
@ -699,10 +699,9 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
|
|||||||
sas_enable_revalidation(sas_ha);
|
sas_enable_revalidation(sas_ha);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
||||||
struct list_head *done_q)
|
struct list_head *done_q)
|
||||||
{
|
{
|
||||||
int rtn = 0;
|
|
||||||
struct scsi_cmnd *cmd, *n;
|
struct scsi_cmnd *cmd, *n;
|
||||||
struct ata_port *ap;
|
struct ata_port *ap;
|
||||||
|
|
||||||
@ -719,7 +718,6 @@ int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
|||||||
if (ap && ap != ddev->sata_dev.ap)
|
if (ap && ap != ddev->sata_dev.ap)
|
||||||
continue;
|
continue;
|
||||||
ap = ddev->sata_dev.ap;
|
ap = ddev->sata_dev.ap;
|
||||||
rtn = 1;
|
|
||||||
list_move(&cmd->eh_entry, &sata_q);
|
list_move(&cmd->eh_entry, &sata_q);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,8 +739,6 @@ int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
|||||||
list_del_init(sata_q.next);
|
list_del_init(sata_q.next);
|
||||||
}
|
}
|
||||||
} while (ap);
|
} while (ap);
|
||||||
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sas_ata_schedule_reset(struct domain_device *dev)
|
void sas_ata_schedule_reset(struct domain_device *dev)
|
||||||
|
@ -678,7 +678,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
|
|||||||
shost->host_eh_scheduled = 0;
|
shost->host_eh_scheduled = 0;
|
||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||||
|
|
||||||
SAS_DPRINTK("Enter %s\n", __func__);
|
SAS_DPRINTK("Enter %s busy: %d failed: %d\n",
|
||||||
|
__func__, shost->host_busy, shost->host_failed);
|
||||||
/*
|
/*
|
||||||
* Deal with commands that still have SAS tasks (i.e. they didn't
|
* Deal with commands that still have SAS tasks (i.e. they didn't
|
||||||
* complete via the normal sas_task completion mechanism)
|
* complete via the normal sas_task completion mechanism)
|
||||||
@ -693,9 +694,9 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
|
|||||||
* scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
|
* scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
|
||||||
* command we see here has no sas_task and is thus unknown to the HA.
|
* command we see here has no sas_task and is thus unknown to the HA.
|
||||||
*/
|
*/
|
||||||
if (!sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q))
|
sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q);
|
||||||
if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
|
if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
|
||||||
scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
|
scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
clear_bit(SAS_HA_FROZEN, &ha->state);
|
clear_bit(SAS_HA_FROZEN, &ha->state);
|
||||||
@ -707,8 +708,8 @@ out:
|
|||||||
|
|
||||||
scsi_eh_flush_done_q(&ha->eh_done_q);
|
scsi_eh_flush_done_q(&ha->eh_done_q);
|
||||||
|
|
||||||
SAS_DPRINTK("--- Exit %s\n", __func__);
|
SAS_DPRINTK("--- Exit %s: busy: %d failed: %d\n",
|
||||||
return;
|
__func__, shost->host_busy, shost->host_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
|
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
|
||||||
|
@ -41,8 +41,8 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
|
|||||||
|
|
||||||
void sas_ata_task_abort(struct sas_task *task);
|
void sas_ata_task_abort(struct sas_task *task);
|
||||||
void sas_ata_strategy_handler(struct Scsi_Host *shost);
|
void sas_ata_strategy_handler(struct Scsi_Host *shost);
|
||||||
int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
||||||
struct list_head *done_q);
|
struct list_head *done_q);
|
||||||
void sas_probe_sata(struct work_struct *work);
|
void sas_probe_sata(struct work_struct *work);
|
||||||
void sas_ata_schedule_reset(struct domain_device *dev);
|
void sas_ata_schedule_reset(struct domain_device *dev);
|
||||||
void sas_ata_wait_eh(struct domain_device *dev);
|
void sas_ata_wait_eh(struct domain_device *dev);
|
||||||
@ -66,10 +66,9 @@ static inline void sas_ata_strategy_handler(struct Scsi_Host *shost)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
static inline void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
||||||
struct list_head *done_q)
|
struct list_head *done_q)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sas_probe_sata(struct work_struct *work)
|
static inline void sas_probe_sata(struct work_struct *work)
|
||||||
|
Loading…
Reference in New Issue
Block a user