Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ef41082 authored by Lin Ming's avatar Lin Ming Committed by Jeff Garzik
Browse files

ata: add ata port system PM callbacks



Change ata_host_request_pm to ata_port_request_pm which performs
port suspend/resume.

Add ata port type driver which implements port PM callbacks.

Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 54f57588
Loading
Loading
Loading
Loading
+74 −70
Original line number Diff line number Diff line
@@ -5234,16 +5234,13 @@ bool ata_link_offline(struct ata_link *link)
}

#ifdef CONFIG_PM
static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
			       unsigned int action, unsigned int ehi_flags,
			       int wait)
{
	unsigned long flags;
	int i, rc;

	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];
	struct ata_link *link;
	unsigned long flags;
	int rc;

	/* Previous resume operation might still be in
	 * progress.  Wait for PM_PENDING to clear.
@@ -5276,70 +5273,77 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
	if (wait) {
		ata_port_wait_eh(ap);
		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
			if (rc)
	}

	return rc;
}

#define to_ata_port(d) container_of(d, struct ata_port, tdev)

static int ata_port_suspend_common(struct device *dev)
{
	struct ata_port *ap = to_ata_port(dev);
	int rc;

	rc = ata_port_request_pm(ap, PMSG_SUSPEND, 0, ATA_EHI_QUIET, 1);
	return rc;
}

static int ata_port_suspend(struct device *dev)
{
	if (pm_runtime_suspended(dev))
		return 0;

	return ata_port_suspend_common(dev);
}

static int ata_port_resume(struct device *dev)
{
	struct ata_port *ap = to_ata_port(dev);
	int rc;

	rc = ata_port_request_pm(ap, PMSG_ON, ATA_EH_RESET,
		ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 1);
	return rc;
}

static const struct dev_pm_ops ata_port_pm_ops = {
	.suspend = ata_port_suspend,
	.resume = ata_port_resume,
};

/**
 *	ata_host_suspend - suspend host
 *	@host: host to suspend
 *	@mesg: PM message
 *
 *	Suspend @host.  Actual operation is performed by EH.  This
 *	function requests EH to perform PM operations and waits for EH
 *	to finish.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep).
 *
 *	RETURNS:
 *	0 on success, -errno on failure.
 *	Suspend @host.  Actual operation is performed by port suspend.
 */
int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
{
	unsigned int ehi_flags = ATA_EHI_QUIET;
	int rc;

	/*
	 * On some hardware, device fails to respond after spun down
	 * for suspend.  As the device won't be used before being
	 * resumed, we don't need to touch the device.  Ask EH to skip
	 * the usual stuff and proceed directly to suspend.
	 *
	 * http://thread.gmane.org/gmane.linux.ide/46764
	 */
	if (mesg.event == PM_EVENT_SUSPEND)
		ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;

	rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
	if (rc == 0)
	host->dev->power.power_state = mesg;
	return rc;
	return 0;
}

/**
 *	ata_host_resume - resume host
 *	@host: host to resume
 *
 *	Resume @host.  Actual operation is performed by EH.  This
 *	function requests EH to perform PM operations and returns.
 *	Note that all resume operations are performed parallelly.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep).
 *	Resume @host.  Actual operation is performed by port resume.
 */
void ata_host_resume(struct ata_host *host)
{
	ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
			    ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
	host->dev->power.power_state = PMSG_ON;
}
#endif

struct device_type ata_port_type = {
	.name = "ata_port",
#ifdef CONFIG_PM
	.pm = &ata_port_pm_ops,
#endif
};

/**
 *	ata_dev_init - Initialize an ata_device structure
 *	@dev: Device structure to initialize
+1 −0
Original line number Diff line number Diff line
@@ -279,6 +279,7 @@ int ata_tport_add(struct device *parent,
	struct device *dev = &ap->tdev;

	device_initialize(dev);
	dev->type = &ata_port_type;

	dev->parent = get_device(parent);
	dev->release = ata_tport_release;
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ extern int atapi_passthru16;
extern int libata_fua;
extern int libata_noacpi;
extern int libata_allow_tpm;
extern struct device_type ata_port_type;
extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
extern void ata_force_cbl(struct ata_port *ap);
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);