diff options
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_init.c | 37 | ||||
| -rw-r--r-- | include/scsi/libsas.h | 1 |
3 files changed, 19 insertions, 29 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 213d5b5dea94..8a2500993e19 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -5261,15 +5261,7 @@ static int _resume_v3_hw(struct device *device) return rc; } phys_init_v3_hw(hisi_hba); - - /* - * If a directly-attached disk is removed during suspend, a deadlock - * may occur, as the PHYE_RESUME_TIMEOUT processing will require the - * hisi_hba->device to be active, which can only happen when resume - * completes. So don't wait for the HA event workqueue to drain upon - * resume. - */ - sas_resume_ha_no_sync(sha); + sas_resume_ha(sha); clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); dev_warn(dev, "end of resuming controller\n"); diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 0bec236f0fb5..c3f3d05b46de 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -410,7 +410,7 @@ static void sas_resume_insert_broadcast_ha(struct sas_ha_struct *ha) } } -static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) +void sas_resume_ha(struct sas_ha_struct *ha) { const unsigned long tmo = msecs_to_jiffies(25000); int i; @@ -426,6 +426,23 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n", i, i > 1 ? "s" : ""); wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo); + + /* + * All phys are back up or timed out. Turn on I/O and drain + * pending work. + */ + scsi_unblock_requests(ha->shost); + sas_drain_work(ha); + + /* + * Send PHYE_RESUME_TIMEOUT after sas_drain_work(). The handler + * calls sas_deform_port() -> sas_destruct_devices(), which removes + * SCSI devices and, for LLDDs using device_link() PM sync, waits + * for the host to be runtime-active. Sending it before the drain + * would deadlock: the drain waits for the handler, the handler + * waits for host resume, and host resume waits for the drain to + * finish. + */ for (i = 0; i < ha->num_phys; i++) { struct asd_sas_phy *phy = ha->sas_phy[i]; @@ -436,12 +453,6 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) } } - /* all phys are back up or timed out, turn on i/o so we can - * flush out disks that did not return - */ - scsi_unblock_requests(ha->shost); - if (drain) - sas_drain_work(ha); clear_bit(SAS_HA_RESUMING, &ha->state); sas_queue_deferred_work(ha); @@ -450,20 +461,8 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) */ sas_resume_insert_broadcast_ha(ha); } - -void sas_resume_ha(struct sas_ha_struct *ha) -{ - _sas_resume_ha(ha, true); -} EXPORT_SYMBOL(sas_resume_ha); -/* A no-sync variant, which does not call sas_drain_ha(). */ -void sas_resume_ha_no_sync(struct sas_ha_struct *ha) -{ - _sas_resume_ha(ha, false); -} -EXPORT_SYMBOL(sas_resume_ha_no_sync); - void sas_suspend_ha(struct sas_ha_struct *ha) { int i; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 163f23c92b41..36d4cb567837 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -680,7 +680,6 @@ extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha); extern void sas_resume_ha(struct sas_ha_struct *sas_ha); -extern void sas_resume_ha_no_sync(struct sas_ha_struct *sas_ha); extern void sas_suspend_ha(struct sas_ha_struct *sas_ha); int sas_phy_reset(struct sas_phy *phy, int hard_reset); |
