@@ -5058,6 +5058,16 @@ static int ata_port_pm_poweroff(struct device *dev)
return 0;
}
+static void ata_port_pm_complete(struct device *dev)
+{
+ struct ata_port *ap = to_ata_port(dev);
+
+ if (ap->pflags & ATA_PFLAG_DEFER_RESCAN)
+ schedule_work(&(ap->scsi_rescan_task));
+
+ ap->pflags &= ~ATA_PFLAG_DEFER_RESCAN;
+}
+
static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
| ATA_EHI_QUIET;
@@ -5123,6 +5133,7 @@ static const struct dev_pm_ops ata_port_pm_ops = {
.thaw = ata_port_pm_resume,
.poweroff = ata_port_pm_poweroff,
.restore = ata_port_pm_resume,
+ .complete = ata_port_pm_complete,
.runtime_suspend = ata_port_runtime_suspend,
.runtime_resume = ata_port_runtime_resume,
@@ -15,6 +15,7 @@
#include <linux/blkdev.h>
#include <linux/export.h>
#include <linux/pci.h>
+#include <linux/suspend.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_eh.h>
@@ -2972,8 +2973,14 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
*/
ehc->i.flags |= ATA_EHI_SETMODE;
- /* schedule the scsi_rescan_device() here */
- schedule_work(&(ap->scsi_rescan_task));
+ /* Schedule the scsi_rescan_device() here.
+ * Defer the rescan if it's in process of
+ * suspending or resuming.
+ */
+ if (pm_suspend_target_state != PM_SUSPEND_ON)
+ ap->pflags |= ATA_PFLAG_DEFER_RESCAN;
+ else
+ schedule_work(&(ap->scsi_rescan_task));
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
@@ -189,6 +189,7 @@ enum {
ATA_PFLAG_UNLOADING = (1 << 9), /* driver is being unloaded */
ATA_PFLAG_UNLOADED = (1 << 10), /* driver is unloaded */
+ ATA_PFLAG_DEFER_RESCAN = (1 << 16), /* peform deferred rescan on system resume */
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
ATA_PFLAG_INIT_GTM_VALID = (1 << 19), /* initial gtm data valid */