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

Commit 071f44b1 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

libata: implement PMP helpers



Implement helpers to test whether PMP is supported, attached and
determine pmp number to use when issuing SRST to a link.  While at it,
move ata_is_host_link() so that it's together with the two new PMP
helpers.

This change simplifies LLDs and helps making PMP support optional.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
parent 48515f6c
Loading
Loading
Loading
Loading
+6 −24
Original line number Diff line number Diff line
@@ -260,8 +260,6 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
				unsigned long deadline);
static void ahci_postreset(struct ata_link *link, unsigned int *class);
static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
			      unsigned long deadline);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static int ahci_port_resume(struct ata_port *ap);
@@ -301,7 +299,7 @@ static struct ata_port_operations ahci_ops = {
	.softreset		= ahci_softreset,
	.hardreset		= ahci_hardreset,
	.postreset		= ahci_postreset,
	.pmp_softreset		= ahci_pmp_softreset,
	.pmp_softreset		= ahci_softreset,
	.error_handler		= ahci_error_handler,
	.post_internal_cmd	= ahci_post_internal_cmd,
	.dev_config		= ahci_dev_config,
@@ -1263,10 +1261,11 @@ static int ahci_check_ready(struct ata_link *link)
	return 0;
}

static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
			     int pmp, unsigned long deadline)
static int ahci_softreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
{
	struct ata_port *ap = link->ap;
	int pmp = sata_srst_pmp(link);
	const char *reason = NULL;
	unsigned long now, msecs;
	struct ata_taskfile tf;
@@ -1326,17 +1325,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
	return rc;
}

static int ahci_softreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
{
	int pmp = 0;

	if (link->ap->flags & ATA_FLAG_PMP)
		pmp = SATA_PMP_CTRL_PORT;

	return ahci_do_softreset(link, class, pmp, deadline);
}

static int ahci_hardreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
{
@@ -1457,12 +1445,6 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class)
	}
}

static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
			      unsigned long deadline)
{
	return ahci_do_softreset(link, class, link->pmp, deadline);
}

static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
{
	struct scatterlist *sg;
@@ -1581,7 +1563,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
				  unk[0], unk[1], unk[2], unk[3]);
	}

	if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
	if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
		active_ehi->err_mask |= AC_ERR_HSM;
		active_ehi->action |= ATA_EH_RESET;
		ata_ehi_push_desc(active_ehi, "incorrect PMP");
@@ -1847,7 +1829,7 @@ static int ahci_port_resume(struct ata_port *ap)
	ahci_power_up(ap);
	ahci_start_port(ap);

	if (ap->nr_pmp_links)
	if (sata_pmp_attached(ap))
		ahci_pmp_attach(ap);
	else
		ahci_pmp_detach(ap);
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap)
{
	WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));

	if (!ap->nr_pmp_links) {
	if (!sata_pmp_attached(ap)) {
		acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);

		ap->link.device->acpi_handle =
+2 −2
Original line number Diff line number Diff line
@@ -2278,7 +2278,7 @@ int ata_dev_configure(struct ata_device *dev)
		 * changed notifications and ATAPI ANs.
		 */
		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
		    (!ap->nr_pmp_links ||
		    (!sata_pmp_attached(ap) ||
		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
			unsigned int err_mask;

@@ -3623,7 +3623,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
	if (online)
		*online = true;

	if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link)) {
	if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) {
		/* If PMP is supported, we have to do follow-up SRST.
		 * Some PMPs don't send D2H Reg FIS after hardreset if
		 * the first port is empty.  Wait only for
+7 −7
Original line number Diff line number Diff line
@@ -873,9 +873,9 @@ int sata_async_notification(struct ata_port *ap)
	if (rc == 0)
		sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);

	if (!ap->nr_pmp_links || rc) {
	if (!sata_pmp_attached(ap) || rc) {
		/* PMP is not attached or SNTF is not available */
		if (!ap->nr_pmp_links) {
		if (!sata_pmp_attached(ap)) {
			/* PMP is not attached.  Check whether ATAPI
			 * AN is configured.  If so, notify media
			 * change.
@@ -1853,7 +1853,7 @@ void ata_eh_autopsy(struct ata_port *ap)
	/* Autopsy of fanout ports can affect host link autopsy.
	 * Perform host link autopsy last.
	 */
	if (ap->nr_pmp_links)
	if (sata_pmp_attached(ap))
		ata_eh_link_autopsy(&ap->link);
}

@@ -2076,7 +2076,7 @@ static int ata_eh_followup_srst_needed(struct ata_link *link,
	}
	if (rc != 0)
		return 0;
	if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link))
	if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
		return 1;
	return 0;
}
@@ -2668,7 +2668,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
		/* if PMP is attached, this function only deals with
		 * downstream links, port should stay thawed.
		 */
		if (!ap->nr_pmp_links)
		if (!sata_pmp_attached(ap))
			ata_eh_freeze_port(ap);

		ata_port_for_each_link(link, ap) {
@@ -2687,7 +2687,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
			}
		}

		if (!ap->nr_pmp_links)
		if (!sata_pmp_attached(ap))
			ata_eh_thaw_port(ap);
	}

@@ -2731,7 +2731,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
			/* PMP reset requires working host port.
			 * Can't retry if it's frozen.
			 */
			if (ap->nr_pmp_links)
			if (sata_pmp_attached(ap))
				goto out;
			break;
		}
+3 −3
Original line number Diff line number Diff line
@@ -411,7 +411,7 @@ int sata_pmp_attach(struct ata_device *dev)
	int rc;

	/* is it hanging off the right place? */
	if (!(ap->flags & ATA_FLAG_PMP)) {
	if (!sata_pmp_supported(ap)) {
		ata_dev_printk(dev, KERN_ERR,
			       "host does not support Port Multiplier\n");
		return -EINVAL;
@@ -876,7 +876,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)

 retry:
	/* PMP attached? */
	if (!ap->nr_pmp_links) {
	if (!sata_pmp_attached(ap)) {
		rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
				    ops->hardreset, ops->postreset, NULL);
		if (rc) {
@@ -983,7 +983,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
	if (ap->pflags & ATA_PFLAG_UNLOADING)
		return rc;

	if (!ap->nr_pmp_links)
	if (!sata_pmp_attached(ap))
		goto retry;

	if (--pmp_tries) {
Loading