xref: /openbmc/linux/drivers/ata/libata-pmp.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
155716d26SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23af9a77aSTejun Heo /*
33af9a77aSTejun Heo  * libata-pmp.c - libata port multiplier support
43af9a77aSTejun Heo  *
53af9a77aSTejun Heo  * Copyright (c) 2007  SUSE Linux Products GmbH
63af9a77aSTejun Heo  * Copyright (c) 2007  Tejun Heo <teheo@suse.de>
73af9a77aSTejun Heo  */
83af9a77aSTejun Heo 
93af9a77aSTejun Heo #include <linux/kernel.h>
1038789fdaSPaul Gortmaker #include <linux/export.h>
113af9a77aSTejun Heo #include <linux/libata.h>
125a0e3ad6STejun Heo #include <linux/slab.h>
133af9a77aSTejun Heo #include "libata.h"
14d9027470SGwendal Grignou #include "libata-transport.h"
153af9a77aSTejun Heo 
1648515f6cSTejun Heo const struct ata_port_operations sata_pmp_port_ops = {
1748515f6cSTejun Heo 	.inherits		= &sata_port_ops,
1848515f6cSTejun Heo 	.pmp_prereset		= ata_std_prereset,
1948515f6cSTejun Heo 	.pmp_hardreset		= sata_std_hardreset,
2048515f6cSTejun Heo 	.pmp_postreset		= ata_std_postreset,
2148515f6cSTejun Heo 	.error_handler		= sata_pmp_error_handler,
2248515f6cSTejun Heo };
2348515f6cSTejun Heo 
243af9a77aSTejun Heo /**
253af9a77aSTejun Heo  *	sata_pmp_read - read PMP register
263af9a77aSTejun Heo  *	@link: link to read PMP register for
273af9a77aSTejun Heo  *	@reg: register to read
283af9a77aSTejun Heo  *	@r_val: resulting value
293af9a77aSTejun Heo  *
30b06ce3e5STejun Heo  *	Read PMP register.
313af9a77aSTejun Heo  *
323af9a77aSTejun Heo  *	LOCKING:
333af9a77aSTejun Heo  *	Kernel thread context (may sleep).
343af9a77aSTejun Heo  *
353af9a77aSTejun Heo  *	RETURNS:
36b06ce3e5STejun Heo  *	0 on success, AC_ERR_* mask on failure.
373af9a77aSTejun Heo  */
sata_pmp_read(struct ata_link * link,int reg,u32 * r_val)38b06ce3e5STejun Heo static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val)
393af9a77aSTejun Heo {
403af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
413af9a77aSTejun Heo 	struct ata_device *pmp_dev = ap->link.device;
42b06ce3e5STejun Heo 	struct ata_taskfile tf;
43b06ce3e5STejun Heo 	unsigned int err_mask;
443af9a77aSTejun Heo 
45b06ce3e5STejun Heo 	ata_tf_init(pmp_dev, &tf);
46b06ce3e5STejun Heo 	tf.command = ATA_CMD_PMP_READ;
47b06ce3e5STejun Heo 	tf.protocol = ATA_PROT_NODATA;
4839f25e70SMark Lord 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
49b06ce3e5STejun Heo 	tf.feature = reg;
50b06ce3e5STejun Heo 	tf.device = link->pmp;
513af9a77aSTejun Heo 
52b06ce3e5STejun Heo 	err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
53bf1bff6fSTejun Heo 				     SATA_PMP_RW_TIMEOUT);
54b06ce3e5STejun Heo 	if (err_mask)
55b06ce3e5STejun Heo 		return err_mask;
56b06ce3e5STejun Heo 
57b06ce3e5STejun Heo 	*r_val = tf.nsect | tf.lbal << 8 | tf.lbam << 16 | tf.lbah << 24;
58b06ce3e5STejun Heo 	return 0;
593af9a77aSTejun Heo }
603af9a77aSTejun Heo 
613af9a77aSTejun Heo /**
623af9a77aSTejun Heo  *	sata_pmp_write - write PMP register
633af9a77aSTejun Heo  *	@link: link to write PMP register for
643af9a77aSTejun Heo  *	@reg: register to write
65*32db9fadSLee Jones  *	@val: value to write
663af9a77aSTejun Heo  *
67b06ce3e5STejun Heo  *	Write PMP register.
683af9a77aSTejun Heo  *
693af9a77aSTejun Heo  *	LOCKING:
703af9a77aSTejun Heo  *	Kernel thread context (may sleep).
713af9a77aSTejun Heo  *
723af9a77aSTejun Heo  *	RETURNS:
73b06ce3e5STejun Heo  *	0 on success, AC_ERR_* mask on failure.
743af9a77aSTejun Heo  */
sata_pmp_write(struct ata_link * link,int reg,u32 val)75b06ce3e5STejun Heo static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val)
763af9a77aSTejun Heo {
773af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
783af9a77aSTejun Heo 	struct ata_device *pmp_dev = ap->link.device;
79b06ce3e5STejun Heo 	struct ata_taskfile tf;
803af9a77aSTejun Heo 
81b06ce3e5STejun Heo 	ata_tf_init(pmp_dev, &tf);
82b06ce3e5STejun Heo 	tf.command = ATA_CMD_PMP_WRITE;
83b06ce3e5STejun Heo 	tf.protocol = ATA_PROT_NODATA;
8439f25e70SMark Lord 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
85b06ce3e5STejun Heo 	tf.feature = reg;
86b06ce3e5STejun Heo 	tf.device = link->pmp;
87b06ce3e5STejun Heo 	tf.nsect = val & 0xff;
88b06ce3e5STejun Heo 	tf.lbal = (val >> 8) & 0xff;
89b06ce3e5STejun Heo 	tf.lbam = (val >> 16) & 0xff;
90b06ce3e5STejun Heo 	tf.lbah = (val >> 24) & 0xff;
913af9a77aSTejun Heo 
92b06ce3e5STejun Heo 	return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
93bf1bff6fSTejun Heo 				 SATA_PMP_RW_TIMEOUT);
943af9a77aSTejun Heo }
953af9a77aSTejun Heo 
963af9a77aSTejun Heo /**
9731f88384STejun Heo  *	sata_pmp_qc_defer_cmd_switch - qc_defer for command switching PMP
9831f88384STejun Heo  *	@qc: ATA command in question
9931f88384STejun Heo  *
10031f88384STejun Heo  *	A host which has command switching PMP support cannot issue
10131f88384STejun Heo  *	commands to multiple links simultaneously.
10231f88384STejun Heo  *
10331f88384STejun Heo  *	LOCKING:
10431f88384STejun Heo  *	spin_lock_irqsave(host lock)
10531f88384STejun Heo  *
10631f88384STejun Heo  *	RETURNS:
10731f88384STejun Heo  *	ATA_DEFER_* if deferring is needed, 0 otherwise.
10831f88384STejun Heo  */
sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd * qc)10931f88384STejun Heo int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc)
11031f88384STejun Heo {
11131f88384STejun Heo 	struct ata_link *link = qc->dev->link;
11231f88384STejun Heo 	struct ata_port *ap = link->ap;
11331f88384STejun Heo 
11431f88384STejun Heo 	if (ap->excl_link == NULL || ap->excl_link == link) {
11531f88384STejun Heo 		if (ap->nr_active_links == 0 || ata_link_active(link)) {
11631f88384STejun Heo 			qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
11731f88384STejun Heo 			return ata_std_qc_defer(qc);
11831f88384STejun Heo 		}
11931f88384STejun Heo 
12031f88384STejun Heo 		ap->excl_link = link;
12131f88384STejun Heo 	}
12231f88384STejun Heo 
12331f88384STejun Heo 	return ATA_DEFER_PORT;
12431f88384STejun Heo }
12531f88384STejun Heo 
12631f88384STejun Heo /**
1273af9a77aSTejun Heo  *	sata_pmp_scr_read - read PSCR
1283af9a77aSTejun Heo  *	@link: ATA link to read PSCR for
1293af9a77aSTejun Heo  *	@reg: PSCR to read
1303af9a77aSTejun Heo  *	@r_val: resulting value
1313af9a77aSTejun Heo  *
1323af9a77aSTejun Heo  *	Read PSCR @reg into @r_val for @link, to be called from
1333af9a77aSTejun Heo  *	ata_scr_read().
1343af9a77aSTejun Heo  *
1353af9a77aSTejun Heo  *	LOCKING:
1363af9a77aSTejun Heo  *	Kernel thread context (may sleep).
1373af9a77aSTejun Heo  *
1383af9a77aSTejun Heo  *	RETURNS:
1393af9a77aSTejun Heo  *	0 on success, -errno on failure.
1403af9a77aSTejun Heo  */
sata_pmp_scr_read(struct ata_link * link,int reg,u32 * r_val)1413af9a77aSTejun Heo int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)
1423af9a77aSTejun Heo {
143b06ce3e5STejun Heo 	unsigned int err_mask;
144b06ce3e5STejun Heo 
1453af9a77aSTejun Heo 	if (reg > SATA_PMP_PSCR_CONTROL)
1463af9a77aSTejun Heo 		return -EINVAL;
1473af9a77aSTejun Heo 
148b06ce3e5STejun Heo 	err_mask = sata_pmp_read(link, reg, r_val);
149b06ce3e5STejun Heo 	if (err_mask) {
150a9a79dfeSJoe Perches 		ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n",
151a9a79dfeSJoe Perches 			      reg, err_mask);
152b06ce3e5STejun Heo 		return -EIO;
153b06ce3e5STejun Heo 	}
154b06ce3e5STejun Heo 	return 0;
1553af9a77aSTejun Heo }
1563af9a77aSTejun Heo 
1573af9a77aSTejun Heo /**
1583af9a77aSTejun Heo  *	sata_pmp_scr_write - write PSCR
1593af9a77aSTejun Heo  *	@link: ATA link to write PSCR for
1603af9a77aSTejun Heo  *	@reg: PSCR to write
1613af9a77aSTejun Heo  *	@val: value to be written
1623af9a77aSTejun Heo  *
1633af9a77aSTejun Heo  *	Write @val to PSCR @reg for @link, to be called from
1643af9a77aSTejun Heo  *	ata_scr_write() and ata_scr_write_flush().
1653af9a77aSTejun Heo  *
1663af9a77aSTejun Heo  *	LOCKING:
1673af9a77aSTejun Heo  *	Kernel thread context (may sleep).
1683af9a77aSTejun Heo  *
1693af9a77aSTejun Heo  *	RETURNS:
1703af9a77aSTejun Heo  *	0 on success, -errno on failure.
1713af9a77aSTejun Heo  */
sata_pmp_scr_write(struct ata_link * link,int reg,u32 val)1723af9a77aSTejun Heo int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
1733af9a77aSTejun Heo {
174b06ce3e5STejun Heo 	unsigned int err_mask;
175b06ce3e5STejun Heo 
1763af9a77aSTejun Heo 	if (reg > SATA_PMP_PSCR_CONTROL)
1773af9a77aSTejun Heo 		return -EINVAL;
1783af9a77aSTejun Heo 
179b06ce3e5STejun Heo 	err_mask = sata_pmp_write(link, reg, val);
180b06ce3e5STejun Heo 	if (err_mask) {
181a9a79dfeSJoe Perches 		ata_link_warn(link, "failed to write SCR %d (Emask=0x%x)\n",
182a9a79dfeSJoe Perches 			      reg, err_mask);
183b06ce3e5STejun Heo 		return -EIO;
184b06ce3e5STejun Heo 	}
185b06ce3e5STejun Heo 	return 0;
1863af9a77aSTejun Heo }
1873af9a77aSTejun Heo 
1883af9a77aSTejun Heo /**
1896c8ea89cSTejun Heo  *	sata_pmp_set_lpm - configure LPM for a PMP link
1906c8ea89cSTejun Heo  *	@link: PMP link to configure LPM for
1916c8ea89cSTejun Heo  *	@policy: target LPM policy
1926c8ea89cSTejun Heo  *	@hints: LPM hints
1936c8ea89cSTejun Heo  *
1946c8ea89cSTejun Heo  *	Configure LPM for @link.  This function will contain any PMP
1956c8ea89cSTejun Heo  *	specific workarounds if necessary.
1966c8ea89cSTejun Heo  *
1976c8ea89cSTejun Heo  *	LOCKING:
1986c8ea89cSTejun Heo  *	EH context.
1996c8ea89cSTejun Heo  *
2006c8ea89cSTejun Heo  *	RETURNS:
2016c8ea89cSTejun Heo  *	0 on success, -errno on failure.
2026c8ea89cSTejun Heo  */
sata_pmp_set_lpm(struct ata_link * link,enum ata_lpm_policy policy,unsigned hints)2036c8ea89cSTejun Heo int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
2046c8ea89cSTejun Heo 		     unsigned hints)
2056c8ea89cSTejun Heo {
2066c8ea89cSTejun Heo 	return sata_link_scr_lpm(link, policy, true);
2076c8ea89cSTejun Heo }
2086c8ea89cSTejun Heo 
2096c8ea89cSTejun Heo /**
2103af9a77aSTejun Heo  *	sata_pmp_read_gscr - read GSCR block of SATA PMP
2113af9a77aSTejun Heo  *	@dev: PMP device
2123af9a77aSTejun Heo  *	@gscr: buffer to read GSCR block into
2133af9a77aSTejun Heo  *
2143af9a77aSTejun Heo  *	Read selected PMP GSCRs from the PMP at @dev.  This will serve
2153af9a77aSTejun Heo  *	as configuration and identification info for the PMP.
2163af9a77aSTejun Heo  *
2173af9a77aSTejun Heo  *	LOCKING:
2183af9a77aSTejun Heo  *	Kernel thread context (may sleep).
2193af9a77aSTejun Heo  *
2203af9a77aSTejun Heo  *	RETURNS:
2213af9a77aSTejun Heo  *	0 on success, -errno on failure.
2223af9a77aSTejun Heo  */
sata_pmp_read_gscr(struct ata_device * dev,u32 * gscr)2233af9a77aSTejun Heo static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr)
2243af9a77aSTejun Heo {
2253af9a77aSTejun Heo 	static const int gscr_to_read[] = { 0, 1, 2, 32, 33, 64, 96 };
226b06ce3e5STejun Heo 	int i;
2273af9a77aSTejun Heo 
2283af9a77aSTejun Heo 	for (i = 0; i < ARRAY_SIZE(gscr_to_read); i++) {
2293af9a77aSTejun Heo 		int reg = gscr_to_read[i];
230b06ce3e5STejun Heo 		unsigned int err_mask;
2313af9a77aSTejun Heo 
232b06ce3e5STejun Heo 		err_mask = sata_pmp_read(dev->link, reg, &gscr[reg]);
233b06ce3e5STejun Heo 		if (err_mask) {
234a9a79dfeSJoe Perches 			ata_dev_err(dev, "failed to read PMP GSCR[%d] (Emask=0x%x)\n",
235a9a79dfeSJoe Perches 				    reg, err_mask);
236b06ce3e5STejun Heo 			return -EIO;
2373af9a77aSTejun Heo 		}
2383af9a77aSTejun Heo 	}
2393af9a77aSTejun Heo 
2403af9a77aSTejun Heo 	return 0;
2413af9a77aSTejun Heo }
2423af9a77aSTejun Heo 
sata_pmp_spec_rev_str(const u32 * gscr)2433af9a77aSTejun Heo static const char *sata_pmp_spec_rev_str(const u32 *gscr)
2443af9a77aSTejun Heo {
2453af9a77aSTejun Heo 	u32 rev = gscr[SATA_PMP_GSCR_REV];
2463af9a77aSTejun Heo 
247deeb003eSShane Huang 	if (rev & (1 << 3))
248deeb003eSShane Huang 		return "1.2";
2493af9a77aSTejun Heo 	if (rev & (1 << 2))
2503af9a77aSTejun Heo 		return "1.1";
2513af9a77aSTejun Heo 	if (rev & (1 << 1))
2523af9a77aSTejun Heo 		return "1.0";
2533af9a77aSTejun Heo 	return "<unknown>";
2543af9a77aSTejun Heo }
2553af9a77aSTejun Heo 
2564f2c7748SGrant Grundler #define PMP_GSCR_SII_POL 129
2574f2c7748SGrant Grundler 
sata_pmp_configure(struct ata_device * dev,int print_info)2583af9a77aSTejun Heo static int sata_pmp_configure(struct ata_device *dev, int print_info)
2593af9a77aSTejun Heo {
2603af9a77aSTejun Heo 	struct ata_port *ap = dev->link->ap;
2613af9a77aSTejun Heo 	u32 *gscr = dev->gscr;
2624f2c7748SGrant Grundler 	u16 vendor = sata_pmp_gscr_vendor(gscr);
2634f2c7748SGrant Grundler 	u16 devid = sata_pmp_gscr_devid(gscr);
264b06ce3e5STejun Heo 	unsigned int err_mask = 0;
2653af9a77aSTejun Heo 	const char *reason;
2663af9a77aSTejun Heo 	int nr_ports, rc;
2673af9a77aSTejun Heo 
2683af9a77aSTejun Heo 	nr_ports = sata_pmp_gscr_ports(gscr);
2693af9a77aSTejun Heo 
2703af9a77aSTejun Heo 	if (nr_ports <= 0 || nr_ports > SATA_PMP_MAX_PORTS) {
2713af9a77aSTejun Heo 		rc = -EINVAL;
2723af9a77aSTejun Heo 		reason = "invalid nr_ports";
2733af9a77aSTejun Heo 		goto fail;
2743af9a77aSTejun Heo 	}
2753af9a77aSTejun Heo 
2763af9a77aSTejun Heo 	if ((ap->flags & ATA_FLAG_AN) &&
2773af9a77aSTejun Heo 	    (gscr[SATA_PMP_GSCR_FEAT] & SATA_PMP_FEAT_NOTIFY))
2783af9a77aSTejun Heo 		dev->flags |= ATA_DFLAG_AN;
2793af9a77aSTejun Heo 
2803af9a77aSTejun Heo 	/* monitor SERR_PHYRDY_CHG on fan-out ports */
281b06ce3e5STejun Heo 	err_mask = sata_pmp_write(dev->link, SATA_PMP_GSCR_ERROR_EN,
282b06ce3e5STejun Heo 				  SERR_PHYRDY_CHG);
283b06ce3e5STejun Heo 	if (err_mask) {
284b06ce3e5STejun Heo 		rc = -EIO;
2853af9a77aSTejun Heo 		reason = "failed to write GSCR_ERROR_EN";
2863af9a77aSTejun Heo 		goto fail;
2873af9a77aSTejun Heo 	}
2883af9a77aSTejun Heo 
2894f2c7748SGrant Grundler 	/* Disable sending Early R_OK.
2904f2c7748SGrant Grundler 	 * With "cached read" HDD testing and multiple ports busy on a SATA
2918ffff94dSTerry Suereth 	 * host controller, 3x26 PMP will very rarely drop a deferred
2924f2c7748SGrant Grundler 	 * R_OK that was intended for the host. Symptom will be all
2934f2c7748SGrant Grundler 	 * 5 drives under test will timeout, get reset, and recover.
2944f2c7748SGrant Grundler 	 */
2958ffff94dSTerry Suereth 	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
2964f2c7748SGrant Grundler 		u32 reg;
2974f2c7748SGrant Grundler 
2984f2c7748SGrant Grundler 		err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
2994f2c7748SGrant Grundler 		if (err_mask) {
3004f2c7748SGrant Grundler 			rc = -EIO;
3018ffff94dSTerry Suereth 			reason = "failed to read Sil3x26 Private Register";
3024f2c7748SGrant Grundler 			goto fail;
3034f2c7748SGrant Grundler 		}
3044f2c7748SGrant Grundler 		reg &= ~0x1;
3054f2c7748SGrant Grundler 		err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
3064f2c7748SGrant Grundler 		if (err_mask) {
3074f2c7748SGrant Grundler 			rc = -EIO;
3088ffff94dSTerry Suereth 			reason = "failed to write Sil3x26 Private Register";
3094f2c7748SGrant Grundler 			goto fail;
3104f2c7748SGrant Grundler 		}
3114f2c7748SGrant Grundler 	}
3124f2c7748SGrant Grundler 
3133af9a77aSTejun Heo 	if (print_info) {
314a9a79dfeSJoe Perches 		ata_dev_info(dev, "Port Multiplier %s, "
3153af9a77aSTejun Heo 			     "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
3164f2c7748SGrant Grundler 			     sata_pmp_spec_rev_str(gscr), vendor, devid,
3173af9a77aSTejun Heo 			     sata_pmp_gscr_rev(gscr),
3183af9a77aSTejun Heo 			     nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
3193af9a77aSTejun Heo 			     gscr[SATA_PMP_GSCR_FEAT]);
3203af9a77aSTejun Heo 
3213af9a77aSTejun Heo 		if (!(dev->flags & ATA_DFLAG_AN))
322a9a79dfeSJoe Perches 			ata_dev_info(dev,
3233af9a77aSTejun Heo 				"Asynchronous notification not supported, "
324a9a79dfeSJoe Perches 				"hotplug won't work on fan-out ports. Use warm-plug instead.\n");
3253af9a77aSTejun Heo 	}
3263af9a77aSTejun Heo 
3273af9a77aSTejun Heo 	return 0;
3283af9a77aSTejun Heo 
3293af9a77aSTejun Heo  fail:
330a9a79dfeSJoe Perches 	ata_dev_err(dev,
331b06ce3e5STejun Heo 		    "failed to configure Port Multiplier (%s, Emask=0x%x)\n",
332b06ce3e5STejun Heo 		    reason, err_mask);
3333af9a77aSTejun Heo 	return rc;
3343af9a77aSTejun Heo }
3353af9a77aSTejun Heo 
sata_pmp_init_links(struct ata_port * ap,int nr_ports)3363af9a77aSTejun Heo static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
3373af9a77aSTejun Heo {
3383af9a77aSTejun Heo 	struct ata_link *pmp_link = ap->pmp_link;
339d9027470SGwendal Grignou 	int i, err;
3403af9a77aSTejun Heo 
3413af9a77aSTejun Heo 	if (!pmp_link) {
3426396bb22SKees Cook 		pmp_link = kcalloc(SATA_PMP_MAX_PORTS, sizeof(pmp_link[0]),
3433af9a77aSTejun Heo 				   GFP_NOIO);
3443af9a77aSTejun Heo 		if (!pmp_link)
3453af9a77aSTejun Heo 			return -ENOMEM;
3463af9a77aSTejun Heo 
3473af9a77aSTejun Heo 		for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
3483af9a77aSTejun Heo 			ata_link_init(ap, &pmp_link[i], i);
3493af9a77aSTejun Heo 
3503af9a77aSTejun Heo 		ap->pmp_link = pmp_link;
351d9027470SGwendal Grignou 
352d9027470SGwendal Grignou 		for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
353d9027470SGwendal Grignou 			err = ata_tlink_add(&pmp_link[i]);
354d9027470SGwendal Grignou 			if (err) {
355d9027470SGwendal Grignou 				goto err_tlink;
356d9027470SGwendal Grignou 			}
357d9027470SGwendal Grignou 		}
3583af9a77aSTejun Heo 	}
3593af9a77aSTejun Heo 
3603af9a77aSTejun Heo 	for (i = 0; i < nr_ports; i++) {
3613af9a77aSTejun Heo 		struct ata_link *link = &pmp_link[i];
3623af9a77aSTejun Heo 		struct ata_eh_context *ehc = &link->eh_context;
3633af9a77aSTejun Heo 
3643af9a77aSTejun Heo 		link->flags = 0;
365b558edddSTejun Heo 		ehc->i.probe_mask |= ATA_ALL_DEVICES;
366cf480626STejun Heo 		ehc->i.action |= ATA_EH_RESET;
3673af9a77aSTejun Heo 	}
3683af9a77aSTejun Heo 
3693af9a77aSTejun Heo 	return 0;
370d9027470SGwendal Grignou   err_tlink:
371d9027470SGwendal Grignou 	while (--i >= 0)
372d9027470SGwendal Grignou 		ata_tlink_delete(&pmp_link[i]);
373d9027470SGwendal Grignou 	kfree(pmp_link);
374d9027470SGwendal Grignou 	ap->pmp_link = NULL;
375d9027470SGwendal Grignou 	return err;
3763af9a77aSTejun Heo }
3773af9a77aSTejun Heo 
sata_pmp_quirks(struct ata_port * ap)3783af9a77aSTejun Heo static void sata_pmp_quirks(struct ata_port *ap)
3793af9a77aSTejun Heo {
3803af9a77aSTejun Heo 	u32 *gscr = ap->link.device->gscr;
3813af9a77aSTejun Heo 	u16 vendor = sata_pmp_gscr_vendor(gscr);
3823af9a77aSTejun Heo 	u16 devid = sata_pmp_gscr_devid(gscr);
3833af9a77aSTejun Heo 	struct ata_link *link;
3843af9a77aSTejun Heo 
3858ffff94dSTerry Suereth 	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
3868ffff94dSTerry Suereth 		/* sil3x26 quirks */
3871eca4365STejun Heo 		ata_for_each_link(link, ap, EDGE) {
3886c8ea89cSTejun Heo 			/* link reports offline after LPM */
3896c8ea89cSTejun Heo 			link->flags |= ATA_LFLAG_NO_LPM;
3906c8ea89cSTejun Heo 
3917a87718dSTejun Heo 			/*
3927a87718dSTejun Heo 			 * Class code report is unreliable and SRST times
3937a87718dSTejun Heo 			 * out under certain configurations.
3947a87718dSTejun Heo 			 */
3953af9a77aSTejun Heo 			if (link->pmp < 5)
3967a87718dSTejun Heo 				link->flags |= ATA_LFLAG_NO_SRST |
3977a87718dSTejun Heo 					       ATA_LFLAG_ASSUME_ATA;
3983af9a77aSTejun Heo 
3993af9a77aSTejun Heo 			/* port 5 is for SEMB device and it doesn't like SRST */
4003af9a77aSTejun Heo 			if (link->pmp == 5)
4013af9a77aSTejun Heo 				link->flags |= ATA_LFLAG_NO_SRST |
4023af9a77aSTejun Heo 					       ATA_LFLAG_ASSUME_SEMB;
4033af9a77aSTejun Heo 		}
4043af9a77aSTejun Heo 	} else if (vendor == 0x1095 && devid == 0x4723) {
4057a87718dSTejun Heo 		/*
4067a87718dSTejun Heo 		 * sil4723 quirks
4077a87718dSTejun Heo 		 *
4087a87718dSTejun Heo 		 * Link reports offline after LPM.  Class code report is
4097a87718dSTejun Heo 		 * unreliable.  SIMG PMPs never got SRST reliable and the
4107a87718dSTejun Heo 		 * config device at port 2 locks up on SRST.
4117a87718dSTejun Heo 		 */
4127a87718dSTejun Heo 		ata_for_each_link(link, ap, EDGE)
4137a87718dSTejun Heo 			link->flags |= ATA_LFLAG_NO_LPM |
4147a87718dSTejun Heo 				       ATA_LFLAG_NO_SRST |
4153af9a77aSTejun Heo 				       ATA_LFLAG_ASSUME_ATA;
4163af9a77aSTejun Heo 	} else if (vendor == 0x1095 && devid == 0x4726) {
4173af9a77aSTejun Heo 		/* sil4726 quirks */
4181eca4365STejun Heo 		ata_for_each_link(link, ap, EDGE) {
4196c8ea89cSTejun Heo 			/* link reports offline after LPM */
4206c8ea89cSTejun Heo 			link->flags |= ATA_LFLAG_NO_LPM;
4216c8ea89cSTejun Heo 
4228048307dSTejun Heo 			/* Class code report is unreliable and SRST
4238048307dSTejun Heo 			 * times out under certain configurations.
4248048307dSTejun Heo 			 * Config device can be at port 0 or 5 and
4258048307dSTejun Heo 			 * locks up on SRST.
4263af9a77aSTejun Heo 			 */
4278048307dSTejun Heo 			if (link->pmp <= 5)
4283af9a77aSTejun Heo 				link->flags |= ATA_LFLAG_NO_SRST |
4293af9a77aSTejun Heo 					       ATA_LFLAG_ASSUME_ATA;
4303af9a77aSTejun Heo 
4313af9a77aSTejun Heo 			/* Port 6 is for SEMB device which doesn't
4323af9a77aSTejun Heo 			 * like SRST either.
4333af9a77aSTejun Heo 			 */
4343af9a77aSTejun Heo 			if (link->pmp == 6)
4353af9a77aSTejun Heo 				link->flags |= ATA_LFLAG_NO_SRST |
4363af9a77aSTejun Heo 					       ATA_LFLAG_ASSUME_SEMB;
4373af9a77aSTejun Heo 		}
4383af9a77aSTejun Heo 	} else if (vendor == 0x1095 && (devid == 0x5723 || devid == 0x5733 ||
4393af9a77aSTejun Heo 					devid == 0x5734 || devid == 0x5744)) {
4403af9a77aSTejun Heo 		/* sil5723/5744 quirks */
4413af9a77aSTejun Heo 
4423af9a77aSTejun Heo 		/* sil5723/5744 has either two or three downstream
4433af9a77aSTejun Heo 		 * ports depending on operation mode.  The last port
4443af9a77aSTejun Heo 		 * is empty if any actual IO device is available or
4453af9a77aSTejun Heo 		 * occupied by a pseudo configuration device
4463af9a77aSTejun Heo 		 * otherwise.  Don't try hard to recover it.
4473af9a77aSTejun Heo 		 */
4483af9a77aSTejun Heo 		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
449efb9e0f4SDenis V. Lunev 	} else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
450efb9e0f4SDenis V. Lunev 		/*
451efb9e0f4SDenis V. Lunev 		 * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
452efb9e0f4SDenis V. Lunev 		 * 0x0325: jmicron JMB394.
453efb9e0f4SDenis V. Lunev 		 */
4540afc6f5bSPavel Herrmann 		ata_for_each_link(link, ap, EDGE) {
4550afc6f5bSPavel Herrmann 			/* SRST breaks detection and disks get misclassified
4560afc6f5bSPavel Herrmann 			 * LPM disabled to avoid potential problems
4570afc6f5bSPavel Herrmann 			 */
4580afc6f5bSPavel Herrmann 			link->flags |= ATA_LFLAG_NO_LPM |
4590afc6f5bSPavel Herrmann 				       ATA_LFLAG_NO_SRST |
4600afc6f5bSPavel Herrmann 				       ATA_LFLAG_ASSUME_ATA;
4610afc6f5bSPavel Herrmann 		}
462945b4744SLior Amsalem 	} else if (vendor == 0x11ab && devid == 0x4140) {
463945b4744SLior Amsalem 		/* Marvell 4140 quirks */
464945b4744SLior Amsalem 		ata_for_each_link(link, ap, EDGE) {
465945b4744SLior Amsalem 			/* port 4 is for SEMB device and it doesn't like SRST */
466945b4744SLior Amsalem 			if (link->pmp == 4)
467945b4744SLior Amsalem 				link->flags |= ATA_LFLAG_DISABLED;
468945b4744SLior Amsalem 		}
4693af9a77aSTejun Heo 	}
4703af9a77aSTejun Heo }
4713af9a77aSTejun Heo 
4723af9a77aSTejun Heo /**
4733af9a77aSTejun Heo  *	sata_pmp_attach - attach a SATA PMP device
4743af9a77aSTejun Heo  *	@dev: SATA PMP device to attach
4753af9a77aSTejun Heo  *
4763af9a77aSTejun Heo  *	Configure and attach SATA PMP device @dev.  This function is
4773af9a77aSTejun Heo  *	also responsible for allocating and initializing PMP links.
4783af9a77aSTejun Heo  *
4793af9a77aSTejun Heo  *	LOCKING:
4803af9a77aSTejun Heo  *	Kernel thread context (may sleep).
4813af9a77aSTejun Heo  *
4823af9a77aSTejun Heo  *	RETURNS:
4833af9a77aSTejun Heo  *	0 on success, -errno on failure.
4843af9a77aSTejun Heo  */
sata_pmp_attach(struct ata_device * dev)4853af9a77aSTejun Heo int sata_pmp_attach(struct ata_device *dev)
4863af9a77aSTejun Heo {
4873af9a77aSTejun Heo 	struct ata_link *link = dev->link;
4883af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
4893af9a77aSTejun Heo 	unsigned long flags;
4903af9a77aSTejun Heo 	struct ata_link *tlink;
4913af9a77aSTejun Heo 	int rc;
4923af9a77aSTejun Heo 
4933af9a77aSTejun Heo 	/* is it hanging off the right place? */
494071f44b1STejun Heo 	if (!sata_pmp_supported(ap)) {
495a9a79dfeSJoe Perches 		ata_dev_err(dev, "host does not support Port Multiplier\n");
4963af9a77aSTejun Heo 		return -EINVAL;
4973af9a77aSTejun Heo 	}
4983af9a77aSTejun Heo 
4993af9a77aSTejun Heo 	if (!ata_is_host_link(link)) {
500a9a79dfeSJoe Perches 		ata_dev_err(dev, "Port Multipliers cannot be nested\n");
5013af9a77aSTejun Heo 		return -EINVAL;
5023af9a77aSTejun Heo 	}
5033af9a77aSTejun Heo 
5043af9a77aSTejun Heo 	if (dev->devno) {
505a9a79dfeSJoe Perches 		ata_dev_err(dev, "Port Multiplier must be the first device\n");
5063af9a77aSTejun Heo 		return -EINVAL;
5073af9a77aSTejun Heo 	}
5083af9a77aSTejun Heo 
5093af9a77aSTejun Heo 	WARN_ON(link->pmp != 0);
5103af9a77aSTejun Heo 	link->pmp = SATA_PMP_CTRL_PORT;
5113af9a77aSTejun Heo 
5123af9a77aSTejun Heo 	/* read GSCR block */
5133af9a77aSTejun Heo 	rc = sata_pmp_read_gscr(dev, dev->gscr);
5143af9a77aSTejun Heo 	if (rc)
5153af9a77aSTejun Heo 		goto fail;
5163af9a77aSTejun Heo 
5173af9a77aSTejun Heo 	/* config PMP */
5183af9a77aSTejun Heo 	rc = sata_pmp_configure(dev, 1);
5193af9a77aSTejun Heo 	if (rc)
5203af9a77aSTejun Heo 		goto fail;
5213af9a77aSTejun Heo 
5223af9a77aSTejun Heo 	rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr));
5233af9a77aSTejun Heo 	if (rc) {
524a9a79dfeSJoe Perches 		ata_dev_info(dev, "failed to initialize PMP links\n");
5253af9a77aSTejun Heo 		goto fail;
5263af9a77aSTejun Heo 	}
5273af9a77aSTejun Heo 
5283af9a77aSTejun Heo 	/* attach it */
5293af9a77aSTejun Heo 	spin_lock_irqsave(ap->lock, flags);
5303af9a77aSTejun Heo 	WARN_ON(ap->nr_pmp_links);
5313af9a77aSTejun Heo 	ap->nr_pmp_links = sata_pmp_gscr_ports(dev->gscr);
5323af9a77aSTejun Heo 	spin_unlock_irqrestore(ap->lock, flags);
5333af9a77aSTejun Heo 
5343af9a77aSTejun Heo 	sata_pmp_quirks(ap);
5353af9a77aSTejun Heo 
5363af9a77aSTejun Heo 	if (ap->ops->pmp_attach)
5373af9a77aSTejun Heo 		ap->ops->pmp_attach(ap);
5383af9a77aSTejun Heo 
5391eca4365STejun Heo 	ata_for_each_link(tlink, ap, EDGE)
5403af9a77aSTejun Heo 		sata_link_init_spd(tlink);
5413af9a77aSTejun Heo 
5423af9a77aSTejun Heo 	return 0;
5433af9a77aSTejun Heo 
5443af9a77aSTejun Heo  fail:
5453af9a77aSTejun Heo 	link->pmp = 0;
5463af9a77aSTejun Heo 	return rc;
5473af9a77aSTejun Heo }
5483af9a77aSTejun Heo 
5493af9a77aSTejun Heo /**
5503af9a77aSTejun Heo  *	sata_pmp_detach - detach a SATA PMP device
5513af9a77aSTejun Heo  *	@dev: SATA PMP device to detach
5523af9a77aSTejun Heo  *
5533af9a77aSTejun Heo  *	Detach SATA PMP device @dev.  This function is also
5543af9a77aSTejun Heo  *	responsible for deconfiguring PMP links.
5553af9a77aSTejun Heo  *
5563af9a77aSTejun Heo  *	LOCKING:
5573af9a77aSTejun Heo  *	Kernel thread context (may sleep).
5583af9a77aSTejun Heo  */
sata_pmp_detach(struct ata_device * dev)5593af9a77aSTejun Heo static void sata_pmp_detach(struct ata_device *dev)
5603af9a77aSTejun Heo {
5613af9a77aSTejun Heo 	struct ata_link *link = dev->link;
5623af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
5633af9a77aSTejun Heo 	struct ata_link *tlink;
5643af9a77aSTejun Heo 	unsigned long flags;
5653af9a77aSTejun Heo 
566a9a79dfeSJoe Perches 	ata_dev_info(dev, "Port Multiplier detaching\n");
5673af9a77aSTejun Heo 
5683af9a77aSTejun Heo 	WARN_ON(!ata_is_host_link(link) || dev->devno ||
5693af9a77aSTejun Heo 		link->pmp != SATA_PMP_CTRL_PORT);
5703af9a77aSTejun Heo 
5713af9a77aSTejun Heo 	if (ap->ops->pmp_detach)
5723af9a77aSTejun Heo 		ap->ops->pmp_detach(ap);
5733af9a77aSTejun Heo 
5741eca4365STejun Heo 	ata_for_each_link(tlink, ap, EDGE)
5753af9a77aSTejun Heo 		ata_eh_detach_dev(tlink->device);
5763af9a77aSTejun Heo 
5773af9a77aSTejun Heo 	spin_lock_irqsave(ap->lock, flags);
5783af9a77aSTejun Heo 	ap->nr_pmp_links = 0;
5793af9a77aSTejun Heo 	link->pmp = 0;
5803af9a77aSTejun Heo 	spin_unlock_irqrestore(ap->lock, flags);
5813af9a77aSTejun Heo }
5823af9a77aSTejun Heo 
5833af9a77aSTejun Heo /**
5843af9a77aSTejun Heo  *	sata_pmp_same_pmp - does new GSCR matches the configured PMP?
5853af9a77aSTejun Heo  *	@dev: PMP device to compare against
5863af9a77aSTejun Heo  *	@new_gscr: GSCR block of the new device
5873af9a77aSTejun Heo  *
5883af9a77aSTejun Heo  *	Compare @new_gscr against @dev and determine whether @dev is
5893af9a77aSTejun Heo  *	the PMP described by @new_gscr.
5903af9a77aSTejun Heo  *
5913af9a77aSTejun Heo  *	LOCKING:
5923af9a77aSTejun Heo  *	None.
5933af9a77aSTejun Heo  *
5943af9a77aSTejun Heo  *	RETURNS:
5953af9a77aSTejun Heo  *	1 if @dev matches @new_gscr, 0 otherwise.
5963af9a77aSTejun Heo  */
sata_pmp_same_pmp(struct ata_device * dev,const u32 * new_gscr)5973af9a77aSTejun Heo static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr)
5983af9a77aSTejun Heo {
5993af9a77aSTejun Heo 	const u32 *old_gscr = dev->gscr;
6003af9a77aSTejun Heo 	u16 old_vendor, new_vendor, old_devid, new_devid;
6013af9a77aSTejun Heo 	int old_nr_ports, new_nr_ports;
6023af9a77aSTejun Heo 
6033af9a77aSTejun Heo 	old_vendor = sata_pmp_gscr_vendor(old_gscr);
6043af9a77aSTejun Heo 	new_vendor = sata_pmp_gscr_vendor(new_gscr);
6053af9a77aSTejun Heo 	old_devid = sata_pmp_gscr_devid(old_gscr);
6063af9a77aSTejun Heo 	new_devid = sata_pmp_gscr_devid(new_gscr);
6073af9a77aSTejun Heo 	old_nr_ports = sata_pmp_gscr_ports(old_gscr);
6083af9a77aSTejun Heo 	new_nr_ports = sata_pmp_gscr_ports(new_gscr);
6093af9a77aSTejun Heo 
6103af9a77aSTejun Heo 	if (old_vendor != new_vendor) {
611a9a79dfeSJoe Perches 		ata_dev_info(dev,
612a9a79dfeSJoe Perches 			     "Port Multiplier vendor mismatch '0x%x' != '0x%x'\n",
6133af9a77aSTejun Heo 			     old_vendor, new_vendor);
6143af9a77aSTejun Heo 		return 0;
6153af9a77aSTejun Heo 	}
6163af9a77aSTejun Heo 
6173af9a77aSTejun Heo 	if (old_devid != new_devid) {
618a9a79dfeSJoe Perches 		ata_dev_info(dev,
619a9a79dfeSJoe Perches 			     "Port Multiplier device ID mismatch '0x%x' != '0x%x'\n",
6203af9a77aSTejun Heo 			     old_devid, new_devid);
6213af9a77aSTejun Heo 		return 0;
6223af9a77aSTejun Heo 	}
6233af9a77aSTejun Heo 
6243af9a77aSTejun Heo 	if (old_nr_ports != new_nr_ports) {
625a9a79dfeSJoe Perches 		ata_dev_info(dev,
626a9a79dfeSJoe Perches 			     "Port Multiplier nr_ports mismatch '0x%x' != '0x%x'\n",
6273af9a77aSTejun Heo 			     old_nr_ports, new_nr_ports);
6283af9a77aSTejun Heo 		return 0;
6293af9a77aSTejun Heo 	}
6303af9a77aSTejun Heo 
6313af9a77aSTejun Heo 	return 1;
6323af9a77aSTejun Heo }
6333af9a77aSTejun Heo 
6343af9a77aSTejun Heo /**
6353af9a77aSTejun Heo  *	sata_pmp_revalidate - revalidate SATA PMP
6363af9a77aSTejun Heo  *	@dev: PMP device to revalidate
6373af9a77aSTejun Heo  *	@new_class: new class code
6383af9a77aSTejun Heo  *
6393af9a77aSTejun Heo  *	Re-read GSCR block and make sure @dev is still attached to the
6403af9a77aSTejun Heo  *	port and properly configured.
6413af9a77aSTejun Heo  *
6423af9a77aSTejun Heo  *	LOCKING:
6433af9a77aSTejun Heo  *	Kernel thread context (may sleep).
6443af9a77aSTejun Heo  *
6453af9a77aSTejun Heo  *	RETURNS:
6463af9a77aSTejun Heo  *	0 on success, -errno otherwise.
6473af9a77aSTejun Heo  */
sata_pmp_revalidate(struct ata_device * dev,unsigned int new_class)6483af9a77aSTejun Heo static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class)
6493af9a77aSTejun Heo {
6503af9a77aSTejun Heo 	struct ata_link *link = dev->link;
6513af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
6523af9a77aSTejun Heo 	u32 *gscr = (void *)ap->sector_buf;
6533af9a77aSTejun Heo 	int rc;
6543af9a77aSTejun Heo 
6553af9a77aSTejun Heo 	ata_eh_about_to_do(link, NULL, ATA_EH_REVALIDATE);
6563af9a77aSTejun Heo 
6573af9a77aSTejun Heo 	if (!ata_dev_enabled(dev)) {
6583af9a77aSTejun Heo 		rc = -ENODEV;
6593af9a77aSTejun Heo 		goto fail;
6603af9a77aSTejun Heo 	}
6613af9a77aSTejun Heo 
6623af9a77aSTejun Heo 	/* wrong class? */
6633af9a77aSTejun Heo 	if (ata_class_enabled(new_class) && new_class != ATA_DEV_PMP) {
6643af9a77aSTejun Heo 		rc = -ENODEV;
6653af9a77aSTejun Heo 		goto fail;
6663af9a77aSTejun Heo 	}
6673af9a77aSTejun Heo 
6683af9a77aSTejun Heo 	/* read GSCR */
6693af9a77aSTejun Heo 	rc = sata_pmp_read_gscr(dev, gscr);
6703af9a77aSTejun Heo 	if (rc)
6713af9a77aSTejun Heo 		goto fail;
6723af9a77aSTejun Heo 
6733af9a77aSTejun Heo 	/* is the pmp still there? */
6743af9a77aSTejun Heo 	if (!sata_pmp_same_pmp(dev, gscr)) {
6753af9a77aSTejun Heo 		rc = -ENODEV;
6763af9a77aSTejun Heo 		goto fail;
6773af9a77aSTejun Heo 	}
6783af9a77aSTejun Heo 
6793af9a77aSTejun Heo 	memcpy(dev->gscr, gscr, sizeof(gscr[0]) * SATA_PMP_GSCR_DWORDS);
6803af9a77aSTejun Heo 
6813af9a77aSTejun Heo 	rc = sata_pmp_configure(dev, 0);
6823af9a77aSTejun Heo 	if (rc)
6833af9a77aSTejun Heo 		goto fail;
6843af9a77aSTejun Heo 
6853af9a77aSTejun Heo 	ata_eh_done(link, NULL, ATA_EH_REVALIDATE);
6863af9a77aSTejun Heo 
6873af9a77aSTejun Heo 	return 0;
6883af9a77aSTejun Heo 
6893af9a77aSTejun Heo  fail:
690a9a79dfeSJoe Perches 	ata_dev_err(dev, "PMP revalidation failed (errno=%d)\n", rc);
6913af9a77aSTejun Heo 	return rc;
6923af9a77aSTejun Heo }
6933af9a77aSTejun Heo 
6943af9a77aSTejun Heo /**
6953af9a77aSTejun Heo  *	sata_pmp_revalidate_quick - revalidate SATA PMP quickly
6963af9a77aSTejun Heo  *	@dev: PMP device to revalidate
6973af9a77aSTejun Heo  *
6983af9a77aSTejun Heo  *	Make sure the attached PMP is accessible.
6993af9a77aSTejun Heo  *
7003af9a77aSTejun Heo  *	LOCKING:
7013af9a77aSTejun Heo  *	Kernel thread context (may sleep).
7023af9a77aSTejun Heo  *
7033af9a77aSTejun Heo  *	RETURNS:
7043af9a77aSTejun Heo  *	0 on success, -errno otherwise.
7053af9a77aSTejun Heo  */
sata_pmp_revalidate_quick(struct ata_device * dev)7063af9a77aSTejun Heo static int sata_pmp_revalidate_quick(struct ata_device *dev)
7073af9a77aSTejun Heo {
708b06ce3e5STejun Heo 	unsigned int err_mask;
7093af9a77aSTejun Heo 	u32 prod_id;
7103af9a77aSTejun Heo 
711b06ce3e5STejun Heo 	err_mask = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id);
712b06ce3e5STejun Heo 	if (err_mask) {
713a9a79dfeSJoe Perches 		ata_dev_err(dev,
714a9a79dfeSJoe Perches 			    "failed to read PMP product ID (Emask=0x%x)\n",
715a9a79dfeSJoe Perches 			    err_mask);
716b06ce3e5STejun Heo 		return -EIO;
7173af9a77aSTejun Heo 	}
7183af9a77aSTejun Heo 
7193af9a77aSTejun Heo 	if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) {
720a9a79dfeSJoe Perches 		ata_dev_err(dev, "PMP product ID mismatch\n");
7213af9a77aSTejun Heo 		/* something weird is going on, request full PMP recovery */
7223af9a77aSTejun Heo 		return -EIO;
7233af9a77aSTejun Heo 	}
7243af9a77aSTejun Heo 
7253af9a77aSTejun Heo 	return 0;
7263af9a77aSTejun Heo }
7273af9a77aSTejun Heo 
7283af9a77aSTejun Heo /**
7293af9a77aSTejun Heo  *	sata_pmp_eh_recover_pmp - recover PMP
7303af9a77aSTejun Heo  *	@ap: ATA port PMP is attached to
7313af9a77aSTejun Heo  *	@prereset: prereset method (can be NULL)
7323af9a77aSTejun Heo  *	@softreset: softreset method
7333af9a77aSTejun Heo  *	@hardreset: hardreset method
7343af9a77aSTejun Heo  *	@postreset: postreset method (can be NULL)
7353af9a77aSTejun Heo  *
7363af9a77aSTejun Heo  *	Recover PMP attached to @ap.  Recovery procedure is somewhat
7373af9a77aSTejun Heo  *	similar to that of ata_eh_recover() except that reset should
7383af9a77aSTejun Heo  *	always be performed in hard->soft sequence and recovery
7393af9a77aSTejun Heo  *	failure results in PMP detachment.
7403af9a77aSTejun Heo  *
7413af9a77aSTejun Heo  *	LOCKING:
7423af9a77aSTejun Heo  *	Kernel thread context (may sleep).
7433af9a77aSTejun Heo  *
7443af9a77aSTejun Heo  *	RETURNS:
7453af9a77aSTejun Heo  *	0 on success, -errno on failure.
7463af9a77aSTejun Heo  */
sata_pmp_eh_recover_pmp(struct ata_port * ap,ata_prereset_fn_t prereset,ata_reset_fn_t softreset,ata_reset_fn_t hardreset,ata_postreset_fn_t postreset)7473af9a77aSTejun Heo static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
7483af9a77aSTejun Heo 		ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
7493af9a77aSTejun Heo 		ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
7503af9a77aSTejun Heo {
7513af9a77aSTejun Heo 	struct ata_link *link = &ap->link;
7523af9a77aSTejun Heo 	struct ata_eh_context *ehc = &link->eh_context;
7533af9a77aSTejun Heo 	struct ata_device *dev = link->device;
7543af9a77aSTejun Heo 	int tries = ATA_EH_PMP_TRIES;
7553af9a77aSTejun Heo 	int detach = 0, rc = 0;
7563af9a77aSTejun Heo 	int reval_failed = 0;
7573af9a77aSTejun Heo 
7583af9a77aSTejun Heo 	if (dev->flags & ATA_DFLAG_DETACH) {
7593af9a77aSTejun Heo 		detach = 1;
7608305f72fSKai-Heng Feng 		rc = -ENODEV;
7613af9a77aSTejun Heo 		goto fail;
7623af9a77aSTejun Heo 	}
7633af9a77aSTejun Heo 
7643af9a77aSTejun Heo  retry:
7653af9a77aSTejun Heo 	ehc->classes[0] = ATA_DEV_UNKNOWN;
7663af9a77aSTejun Heo 
767cf480626STejun Heo 	if (ehc->i.action & ATA_EH_RESET) {
7683af9a77aSTejun Heo 		struct ata_link *tlink;
7693af9a77aSTejun Heo 
7703af9a77aSTejun Heo 		/* reset */
7713af9a77aSTejun Heo 		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
7723af9a77aSTejun Heo 				  postreset);
7733af9a77aSTejun Heo 		if (rc) {
774a9a79dfeSJoe Perches 			ata_link_err(link, "failed to reset PMP, giving up\n");
7753af9a77aSTejun Heo 			goto fail;
7763af9a77aSTejun Heo 		}
7773af9a77aSTejun Heo 
7783af9a77aSTejun Heo 		/* PMP is reset, SErrors cannot be trusted, scan all */
7791eca4365STejun Heo 		ata_for_each_link(tlink, ap, EDGE) {
780b558edddSTejun Heo 			struct ata_eh_context *ehc = &tlink->eh_context;
781b558edddSTejun Heo 
782b558edddSTejun Heo 			ehc->i.probe_mask |= ATA_ALL_DEVICES;
783b558edddSTejun Heo 			ehc->i.action |= ATA_EH_RESET;
784b558edddSTejun Heo 		}
7853af9a77aSTejun Heo 	}
7863af9a77aSTejun Heo 
7873af9a77aSTejun Heo 	/* If revalidation is requested, revalidate and reconfigure;
7883af9a77aSTejun Heo 	 * otherwise, do quick revalidation.
7893af9a77aSTejun Heo 	 */
7903af9a77aSTejun Heo 	if (ehc->i.action & ATA_EH_REVALIDATE)
7913af9a77aSTejun Heo 		rc = sata_pmp_revalidate(dev, ehc->classes[0]);
7923af9a77aSTejun Heo 	else
7933af9a77aSTejun Heo 		rc = sata_pmp_revalidate_quick(dev);
7943af9a77aSTejun Heo 
7953af9a77aSTejun Heo 	if (rc) {
7963af9a77aSTejun Heo 		tries--;
7973af9a77aSTejun Heo 
7983af9a77aSTejun Heo 		if (rc == -ENODEV) {
799b558edddSTejun Heo 			ehc->i.probe_mask |= ATA_ALL_DEVICES;
8003af9a77aSTejun Heo 			detach = 1;
8013af9a77aSTejun Heo 			/* give it just two more chances */
8023af9a77aSTejun Heo 			tries = min(tries, 2);
8033af9a77aSTejun Heo 		}
8043af9a77aSTejun Heo 
8053af9a77aSTejun Heo 		if (tries) {
8063af9a77aSTejun Heo 			/* consecutive revalidation failures? speed down */
8073af9a77aSTejun Heo 			if (reval_failed)
808a07d499bSTejun Heo 				sata_down_spd_limit(link, 0);
8093af9a77aSTejun Heo 			else
8103af9a77aSTejun Heo 				reval_failed = 1;
8113af9a77aSTejun Heo 
812cf480626STejun Heo 			ehc->i.action |= ATA_EH_RESET;
8133af9a77aSTejun Heo 			goto retry;
8143af9a77aSTejun Heo 		} else {
815a9a79dfeSJoe Perches 			ata_dev_err(dev,
816a9a79dfeSJoe Perches 				    "failed to recover PMP after %d tries, giving up\n",
8173af9a77aSTejun Heo 				    ATA_EH_PMP_TRIES);
8183af9a77aSTejun Heo 			goto fail;
8193af9a77aSTejun Heo 		}
8203af9a77aSTejun Heo 	}
8213af9a77aSTejun Heo 
8223af9a77aSTejun Heo 	/* okay, PMP resurrected */
8233af9a77aSTejun Heo 	ehc->i.flags = 0;
8243af9a77aSTejun Heo 
8253af9a77aSTejun Heo 	return 0;
8263af9a77aSTejun Heo 
8273af9a77aSTejun Heo  fail:
8283af9a77aSTejun Heo 	sata_pmp_detach(dev);
8293af9a77aSTejun Heo 	if (detach)
8303af9a77aSTejun Heo 		ata_eh_detach_dev(dev);
8313af9a77aSTejun Heo 	else
8323af9a77aSTejun Heo 		ata_dev_disable(dev);
8333af9a77aSTejun Heo 
8343af9a77aSTejun Heo 	return rc;
8353af9a77aSTejun Heo }
8363af9a77aSTejun Heo 
sata_pmp_eh_handle_disabled_links(struct ata_port * ap)8373af9a77aSTejun Heo static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
8383af9a77aSTejun Heo {
8393af9a77aSTejun Heo 	struct ata_link *link;
8403af9a77aSTejun Heo 	unsigned long flags;
8413af9a77aSTejun Heo 	int rc;
8423af9a77aSTejun Heo 
8433af9a77aSTejun Heo 	spin_lock_irqsave(ap->lock, flags);
8443af9a77aSTejun Heo 
8451eca4365STejun Heo 	ata_for_each_link(link, ap, EDGE) {
8463af9a77aSTejun Heo 		if (!(link->flags & ATA_LFLAG_DISABLED))
8473af9a77aSTejun Heo 			continue;
8483af9a77aSTejun Heo 
8493af9a77aSTejun Heo 		spin_unlock_irqrestore(ap->lock, flags);
8503af9a77aSTejun Heo 
8513af9a77aSTejun Heo 		/* Some PMPs require hardreset sequence to get
8523af9a77aSTejun Heo 		 * SError.N working.
8533af9a77aSTejun Heo 		 */
8543af9a77aSTejun Heo 		sata_link_hardreset(link, sata_deb_timing_normal,
855341c2c95STejun Heo 				ata_deadline(jiffies, ATA_TMOUT_INTERNAL_QUICK),
856341c2c95STejun Heo 				NULL, NULL);
8573af9a77aSTejun Heo 
8583af9a77aSTejun Heo 		/* unconditionally clear SError.N */
8593af9a77aSTejun Heo 		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
8603af9a77aSTejun Heo 		if (rc) {
861a9a79dfeSJoe Perches 			ata_link_err(link,
862a9a79dfeSJoe Perches 				     "failed to clear SError.N (errno=%d)\n",
863a9a79dfeSJoe Perches 				     rc);
8643af9a77aSTejun Heo 			return rc;
8653af9a77aSTejun Heo 		}
8663af9a77aSTejun Heo 
8673af9a77aSTejun Heo 		spin_lock_irqsave(ap->lock, flags);
8683af9a77aSTejun Heo 	}
8693af9a77aSTejun Heo 
8703af9a77aSTejun Heo 	spin_unlock_irqrestore(ap->lock, flags);
8713af9a77aSTejun Heo 
8723af9a77aSTejun Heo 	return 0;
8733af9a77aSTejun Heo }
8743af9a77aSTejun Heo 
sata_pmp_handle_link_fail(struct ata_link * link,int * link_tries)8753af9a77aSTejun Heo static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
8763af9a77aSTejun Heo {
8773af9a77aSTejun Heo 	struct ata_port *ap = link->ap;
8783af9a77aSTejun Heo 	unsigned long flags;
8793af9a77aSTejun Heo 
8803af9a77aSTejun Heo 	if (link_tries[link->pmp] && --link_tries[link->pmp])
8813af9a77aSTejun Heo 		return 1;
8823af9a77aSTejun Heo 
8833af9a77aSTejun Heo 	/* disable this link */
8843af9a77aSTejun Heo 	if (!(link->flags & ATA_LFLAG_DISABLED)) {
885a9a79dfeSJoe Perches 		ata_link_warn(link,
8863af9a77aSTejun Heo 			"failed to recover link after %d tries, disabling\n",
8873af9a77aSTejun Heo 			ATA_EH_PMP_LINK_TRIES);
8883af9a77aSTejun Heo 
8893af9a77aSTejun Heo 		spin_lock_irqsave(ap->lock, flags);
8903af9a77aSTejun Heo 		link->flags |= ATA_LFLAG_DISABLED;
8913af9a77aSTejun Heo 		spin_unlock_irqrestore(ap->lock, flags);
8923af9a77aSTejun Heo 	}
8933af9a77aSTejun Heo 
8943af9a77aSTejun Heo 	ata_dev_disable(link->device);
8953af9a77aSTejun Heo 	link->eh_context.i.action = 0;
8963af9a77aSTejun Heo 
8973af9a77aSTejun Heo 	return 0;
8983af9a77aSTejun Heo }
8993af9a77aSTejun Heo 
9003af9a77aSTejun Heo /**
9013af9a77aSTejun Heo  *	sata_pmp_eh_recover - recover PMP-enabled port
9023af9a77aSTejun Heo  *	@ap: ATA port to recover
9033af9a77aSTejun Heo  *
9043af9a77aSTejun Heo  *	Drive EH recovery operation for PMP enabled port @ap.  This
9053af9a77aSTejun Heo  *	function recovers host and PMP ports with proper retrials and
9063af9a77aSTejun Heo  *	fallbacks.  Actual recovery operations are performed using
9073af9a77aSTejun Heo  *	ata_eh_recover() and sata_pmp_eh_recover_pmp().
9083af9a77aSTejun Heo  *
9093af9a77aSTejun Heo  *	LOCKING:
9103af9a77aSTejun Heo  *	Kernel thread context (may sleep).
9113af9a77aSTejun Heo  *
9123af9a77aSTejun Heo  *	RETURNS:
9133af9a77aSTejun Heo  *	0 on success, -errno on failure.
9143af9a77aSTejun Heo  */
sata_pmp_eh_recover(struct ata_port * ap)915a1efdabaSTejun Heo static int sata_pmp_eh_recover(struct ata_port *ap)
9163af9a77aSTejun Heo {
917a1efdabaSTejun Heo 	struct ata_port_operations *ops = ap->ops;
9183af9a77aSTejun Heo 	int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
9193af9a77aSTejun Heo 	struct ata_link *pmp_link = &ap->link;
9203af9a77aSTejun Heo 	struct ata_device *pmp_dev = pmp_link->device;
9213af9a77aSTejun Heo 	struct ata_eh_context *pmp_ehc = &pmp_link->eh_context;
922f1bbfb90STejun Heo 	u32 *gscr = pmp_dev->gscr;
9233af9a77aSTejun Heo 	struct ata_link *link;
9243af9a77aSTejun Heo 	struct ata_device *dev;
925b06ce3e5STejun Heo 	unsigned int err_mask;
9263af9a77aSTejun Heo 	u32 gscr_error, sntf;
9273af9a77aSTejun Heo 	int cnt, rc;
9283af9a77aSTejun Heo 
9293af9a77aSTejun Heo 	pmp_tries = ATA_EH_PMP_TRIES;
9301eca4365STejun Heo 	ata_for_each_link(link, ap, EDGE)
9313af9a77aSTejun Heo 		link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES;
9323af9a77aSTejun Heo 
9333af9a77aSTejun Heo  retry:
9343af9a77aSTejun Heo 	/* PMP attached? */
935071f44b1STejun Heo 	if (!sata_pmp_attached(ap)) {
936a1efdabaSTejun Heo 		rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
937a1efdabaSTejun Heo 				    ops->hardreset, ops->postreset, NULL);
9383af9a77aSTejun Heo 		if (rc) {
9391eca4365STejun Heo 			ata_for_each_dev(dev, &ap->link, ALL)
9403af9a77aSTejun Heo 				ata_dev_disable(dev);
9413af9a77aSTejun Heo 			return rc;
9423af9a77aSTejun Heo 		}
9433af9a77aSTejun Heo 
9443af9a77aSTejun Heo 		if (pmp_dev->class != ATA_DEV_PMP)
9453af9a77aSTejun Heo 			return 0;
9463af9a77aSTejun Heo 
9473af9a77aSTejun Heo 		/* new PMP online */
9481eca4365STejun Heo 		ata_for_each_link(link, ap, EDGE)
9493af9a77aSTejun Heo 			link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES;
9503af9a77aSTejun Heo 
9513af9a77aSTejun Heo 		/* fall through */
9523af9a77aSTejun Heo 	}
9533af9a77aSTejun Heo 
9543af9a77aSTejun Heo 	/* recover pmp */
955a1efdabaSTejun Heo 	rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
956a1efdabaSTejun Heo 				     ops->hardreset, ops->postreset);
9573af9a77aSTejun Heo 	if (rc)
9583af9a77aSTejun Heo 		goto pmp_fail;
9593af9a77aSTejun Heo 
960f1bbfb90STejun Heo 	/* PHY event notification can disturb reset and other recovery
961f1bbfb90STejun Heo 	 * operations.  Turn it off.
962f1bbfb90STejun Heo 	 */
963f1bbfb90STejun Heo 	if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) {
964f1bbfb90STejun Heo 		gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY;
965f1bbfb90STejun Heo 
966f1bbfb90STejun Heo 		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
967f1bbfb90STejun Heo 					  gscr[SATA_PMP_GSCR_FEAT_EN]);
968f1bbfb90STejun Heo 		if (err_mask) {
969a9a79dfeSJoe Perches 			ata_link_warn(pmp_link,
970f1bbfb90STejun Heo 				"failed to disable NOTIFY (err_mask=0x%x)\n",
971f1bbfb90STejun Heo 				err_mask);
972f1bbfb90STejun Heo 			goto pmp_fail;
973f1bbfb90STejun Heo 		}
974f1bbfb90STejun Heo 	}
975f1bbfb90STejun Heo 
9763af9a77aSTejun Heo 	/* handle disabled links */
9773af9a77aSTejun Heo 	rc = sata_pmp_eh_handle_disabled_links(ap);
9783af9a77aSTejun Heo 	if (rc)
9793af9a77aSTejun Heo 		goto pmp_fail;
9803af9a77aSTejun Heo 
9813af9a77aSTejun Heo 	/* recover links */
982a1efdabaSTejun Heo 	rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
983a1efdabaSTejun Heo 			    ops->pmp_hardreset, ops->pmp_postreset, &link);
9843af9a77aSTejun Heo 	if (rc)
9853af9a77aSTejun Heo 		goto link_fail;
9863af9a77aSTejun Heo 
9873af9a77aSTejun Heo 	/* clear SNotification */
9883af9a77aSTejun Heo 	rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
9893af9a77aSTejun Heo 	if (rc == 0)
9903af9a77aSTejun Heo 		sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
9913af9a77aSTejun Heo 
9926c8ea89cSTejun Heo 	/*
9936c8ea89cSTejun Heo 	 * If LPM is active on any fan-out port, hotplug wouldn't
9946c8ea89cSTejun Heo 	 * work.  Return w/ PHY event notification disabled.
9956c8ea89cSTejun Heo 	 */
9966c8ea89cSTejun Heo 	ata_for_each_link(link, ap, EDGE)
9976c8ea89cSTejun Heo 		if (link->lpm_policy > ATA_LPM_MAX_POWER)
9986c8ea89cSTejun Heo 			return 0;
9996c8ea89cSTejun Heo 
10006c8ea89cSTejun Heo 	/*
10016c8ea89cSTejun Heo 	 * Connection status might have changed while resetting other
10026c8ea89cSTejun Heo 	 * links, enable notification and check SATA_PMP_GSCR_ERROR
10036c8ea89cSTejun Heo 	 * before returning.
10046c8ea89cSTejun Heo 	 */
10056c8ea89cSTejun Heo 
10063af9a77aSTejun Heo 	/* enable notification */
10073af9a77aSTejun Heo 	if (pmp_dev->flags & ATA_DFLAG_AN) {
1008f1bbfb90STejun Heo 		gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
10093af9a77aSTejun Heo 
1010f1bbfb90STejun Heo 		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
1011f1bbfb90STejun Heo 					  gscr[SATA_PMP_GSCR_FEAT_EN]);
1012b06ce3e5STejun Heo 		if (err_mask) {
1013a9a79dfeSJoe Perches 			ata_dev_err(pmp_dev,
1014a9a79dfeSJoe Perches 				    "failed to write PMP_FEAT_EN (Emask=0x%x)\n",
1015a9a79dfeSJoe Perches 				    err_mask);
1016b06ce3e5STejun Heo 			rc = -EIO;
10173af9a77aSTejun Heo 			goto pmp_fail;
10183af9a77aSTejun Heo 		}
10193af9a77aSTejun Heo 	}
10203af9a77aSTejun Heo 
10213af9a77aSTejun Heo 	/* check GSCR_ERROR */
1022b06ce3e5STejun Heo 	err_mask = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error);
1023b06ce3e5STejun Heo 	if (err_mask) {
1024a9a79dfeSJoe Perches 		ata_dev_err(pmp_dev,
1025a9a79dfeSJoe Perches 			    "failed to read PMP_GSCR_ERROR (Emask=0x%x)\n",
1026a9a79dfeSJoe Perches 			    err_mask);
1027b06ce3e5STejun Heo 		rc = -EIO;
10283af9a77aSTejun Heo 		goto pmp_fail;
10293af9a77aSTejun Heo 	}
10303af9a77aSTejun Heo 
10313af9a77aSTejun Heo 	cnt = 0;
10321eca4365STejun Heo 	ata_for_each_link(link, ap, EDGE) {
10333af9a77aSTejun Heo 		if (!(gscr_error & (1 << link->pmp)))
10343af9a77aSTejun Heo 			continue;
10353af9a77aSTejun Heo 
10363af9a77aSTejun Heo 		if (sata_pmp_handle_link_fail(link, link_tries)) {
10373af9a77aSTejun Heo 			ata_ehi_hotplugged(&link->eh_context.i);
10383af9a77aSTejun Heo 			cnt++;
10393af9a77aSTejun Heo 		} else {
1040a9a79dfeSJoe Perches 			ata_link_warn(link,
1041a9a79dfeSJoe Perches 				"PHY status changed but maxed out on retries, giving up\n");
1042a9a79dfeSJoe Perches 			ata_link_warn(link,
1043a9a79dfeSJoe Perches 				"Manually issue scan to resume this link\n");
10443af9a77aSTejun Heo 		}
10453af9a77aSTejun Heo 	}
10463af9a77aSTejun Heo 
10473af9a77aSTejun Heo 	if (cnt) {
1048a9a79dfeSJoe Perches 		ata_port_info(ap,
1049a9a79dfeSJoe Perches 			"PMP SError.N set for some ports, repeating recovery\n");
10503af9a77aSTejun Heo 		goto retry;
10513af9a77aSTejun Heo 	}
10523af9a77aSTejun Heo 
10533af9a77aSTejun Heo 	return 0;
10543af9a77aSTejun Heo 
10553af9a77aSTejun Heo  link_fail:
10563af9a77aSTejun Heo 	if (sata_pmp_handle_link_fail(link, link_tries)) {
1057cf480626STejun Heo 		pmp_ehc->i.action |= ATA_EH_RESET;
10583af9a77aSTejun Heo 		goto retry;
10593af9a77aSTejun Heo 	}
10603af9a77aSTejun Heo 
10613af9a77aSTejun Heo 	/* fall through */
10623af9a77aSTejun Heo  pmp_fail:
10633af9a77aSTejun Heo 	/* Control always ends up here after detaching PMP.  Shut up
10643af9a77aSTejun Heo 	 * and return if we're unloading.
10653af9a77aSTejun Heo 	 */
10663af9a77aSTejun Heo 	if (ap->pflags & ATA_PFLAG_UNLOADING)
10673af9a77aSTejun Heo 		return rc;
10683af9a77aSTejun Heo 
1069071f44b1STejun Heo 	if (!sata_pmp_attached(ap))
10703af9a77aSTejun Heo 		goto retry;
10713af9a77aSTejun Heo 
10723af9a77aSTejun Heo 	if (--pmp_tries) {
1073cf480626STejun Heo 		pmp_ehc->i.action |= ATA_EH_RESET;
10743af9a77aSTejun Heo 		goto retry;
10753af9a77aSTejun Heo 	}
10763af9a77aSTejun Heo 
1077a9a79dfeSJoe Perches 	ata_port_err(ap, "failed to recover PMP after %d tries, giving up\n",
10783af9a77aSTejun Heo 		     ATA_EH_PMP_TRIES);
10793af9a77aSTejun Heo 	sata_pmp_detach(pmp_dev);
10803af9a77aSTejun Heo 	ata_dev_disable(pmp_dev);
10813af9a77aSTejun Heo 
10823af9a77aSTejun Heo 	return rc;
10833af9a77aSTejun Heo }
10843af9a77aSTejun Heo 
10853af9a77aSTejun Heo /**
1086a1efdabaSTejun Heo  *	sata_pmp_error_handler - do standard error handling for PMP-enabled host
10873af9a77aSTejun Heo  *	@ap: host port to handle error for
10883af9a77aSTejun Heo  *
10893af9a77aSTejun Heo  *	Perform standard error handling sequence for PMP-enabled host
10903af9a77aSTejun Heo  *	@ap.
10913af9a77aSTejun Heo  *
10923af9a77aSTejun Heo  *	LOCKING:
10933af9a77aSTejun Heo  *	Kernel thread context (may sleep).
10943af9a77aSTejun Heo  */
sata_pmp_error_handler(struct ata_port * ap)1095a1efdabaSTejun Heo void sata_pmp_error_handler(struct ata_port *ap)
10963af9a77aSTejun Heo {
10973af9a77aSTejun Heo 	ata_eh_autopsy(ap);
10983af9a77aSTejun Heo 	ata_eh_report(ap);
1099a1efdabaSTejun Heo 	sata_pmp_eh_recover(ap);
11003af9a77aSTejun Heo 	ata_eh_finish(ap);
11013af9a77aSTejun Heo }
110248515f6cSTejun Heo 
110348515f6cSTejun Heo EXPORT_SYMBOL_GPL(sata_pmp_port_ops);
110448515f6cSTejun Heo EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
110548515f6cSTejun Heo EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
1106