Skip to contentSkip to conversation

block/libata: update and use block layer padding and draining, take 3

PATCH In review Tejun Heo 2 participants 11 messages Mar 11, 2008 – Mar 17, 2008

Subsystems (2)
lore
Share & tools
lore

Tejun Heo

author
#0 lore raw

PATCH 1/1 block/libata: update and use block layer padding and draining, take 3

Hello,

After posting the previous patchset, I realized #upstream is proper subset of #upstream-fixes, so here's the updated version against #upstream-fixes. It still needs Mikael's ack regarding behavior change on sata_promise.

Changes from the last take[L] are...

* Updated against the current #upstream-fixes.

This patchset is against the current #upstream-fixes (3db691da).

 drivers/ata/ahci.c        |   17 ++----
 drivers/ata/libata-core.c |   28 ++---------
 drivers/ata/libata-eh.c   |  114 ++++++++++++++++------------------------------
 drivers/ata/libata-pmp.c  |   57 ++++++-----------------
 drivers/ata/libata-scsi.c |    7 +-
 drivers/ata/sata_fsl.c    |    4 -
 drivers/ata/sata_mv.c     |   31 +++---------
 drivers/ata/sata_nv.c     |   17 ++----
 drivers/ata/sata_sil.c    |    5 --
 drivers/ata/sata_sil24.c  |   58 ++++++++++-------------
 drivers/ata/sata_via.c    |    2
 include/linux/libata.h    |   24 ++-------
 12 files changed, 121 insertions(+), 243 deletions(-)

[L] http://thread.gmane.org/gmane.linux.ide/29637

--
tejun

author
#1 lore raw

PATCH 1/5 libata: prefer hardreset

When both soft and hard resets are available, libata preferred softreset till now. The logic behind it was to be softer to devices; however, this doesn't really help much. Rationales for the change:

* BIOS may freeze lock certain things during boot and softreset can't unlock those. This by itself is okay but during operation PHY event or other error conditions can trigger hardreset and the device may end up with different configuration.

For example, after a hardreset, previously unlockable HPA can be unlocked resulting in different device size and thus revalidation failure. Similar condition can occur during or after resume.

* Certain ATAPI devices require hardreset to recover after certain error conditions. On PATA, this is done by issuing the DEVICE RESET command. On SATA, COMRESET has equivalent effect. The problem is that DEVICE RESET needs its own execution protocol.

For SFF controllers with bare TF access, it can be easily implemented but more advanced controllers (e.g. ahci and sata_sil24) require specialized implementations. Simply using hardreset solves the problem nicely.

* COMRESET initialization sequence is the norm in SATA land and many SATA devices don't work properly if only SRST is used. For example, some PMPs behave this way and libata works around by always issuing hardreset if the host supports PMP.

Like the above example, libata has developed a number of mechanisms aiming to promote softreset to hardreset if softreset is not going to work. This approach is time consuming and error prone.

Also, note that, dependingon how you read the specs, it could be argued that PMP fan-out ports require COMRESET to start operation. In fact, all the PMPs on the market except one don't work properly if COMRESET is not issued to fan-out ports after PMP reset.

* COMRESET is an integral part of SATA connection and any working device should be able to handle COMRESET properly. After all, it's the way to signal hardreset during reboot. This is the most used and recommended (at least by the ahci spec) method of resetting devices.

So, this patch makes libata prefer hardreset over softreset by making the following changes.

* Rename ATA_EH_RESET_MASK to ATA_EH_RESET and use it whereever ATA_EH_{SOFT|HARD}RESET used to be used. ATA_EH_{SOFT|HARD}RESET is now only used to tell prereset whether soft or hard reset will be issued.

* Strip out now unneeded promote-to-hardreset logics from ata_eh_reset(), ata_std_prereset(), sata_pmp_std_prereset() and other places.

---
 drivers/ata/ahci.c        |   10 ++--
 drivers/ata/libata-core.c |   19 ++-------
 drivers/ata/libata-eh.c   |   99 ++++++++++++++++-----------------------------
 drivers/ata/libata-pmp.c  |   28 ++++---------
 drivers/ata/libata-scsi.c |    4 +-
 drivers/ata/sata_fsl.c    |    2 +-
 drivers/ata/sata_mv.c     |   31 ++++----------
 drivers/ata/sata_nv.c     |   12 +++---
 drivers/ata/sata_sil24.c  |   54 ++++++++++++------------
 drivers/ata/sata_via.c    |    2 +-
 include/linux/libata.h    |    8 ++--
 11 files changed, 101 insertions(+), 168 deletions(-)
drivers/ata/ahci.c +5 -5
index 6978469..b88b38a 100644
@@ -1638,7 +1638,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
 
 		active_ehi->err_mask |= AC_ERR_HSM;
-		active_ehi->action |= ATA_EH_SOFTRESET;
+		active_ehi->action |= ATA_EH_RESET;
 		ata_ehi_push_desc(active_ehi,
 				  "unknown FIS %08x %08x %08x %08x" ,
 				  unk[0], unk[1], unk[2], unk[3]);
@@ -1646,19 +1646,19 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 
 	if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
 		active_ehi->err_mask |= AC_ERR_HSM;
-		active_ehi->action |= ATA_EH_SOFTRESET;
+		active_ehi->action |= ATA_EH_RESET;
 		ata_ehi_push_desc(active_ehi, "incorrect PMP");
 	}
 
 	if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
 		host_ehi->err_mask |= AC_ERR_HOST_BUS;
-		host_ehi->action |= ATA_EH_SOFTRESET;
+		host_ehi->action |= ATA_EH_RESET;
 		ata_ehi_push_desc(host_ehi, "host bus error");
 	}
 
 	if (irq_stat & PORT_IRQ_IF_ERR) {
 		host_ehi->err_mask |= AC_ERR_ATA_BUS;
-		host_ehi->action |= ATA_EH_SOFTRESET;
+		host_ehi->action |= ATA_EH_RESET;
 		ata_ehi_push_desc(host_ehi, "interface fatal error");
 	}
 
@@ -1746,7 +1746,7 @@ static void ahci_port_intr(struct ata_port *ap)
 	/* while resetting, invalid completions are expected */
 	if (unlikely(rc < 0 && !resetting)) {
 		ehi->err_mask |= AC_ERR_HSM;
-		ehi->action |= ATA_EH_SOFTRESET;
+		ehi->action |= ATA_EH_RESET;
 		ata_port_freeze(ap);
 	}
 }
drivers/ata/libata-core.c +4 -15
index 4bbe31f..b3ebc3e 100644
@@ -3901,17 +3901,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
 	const unsigned long *timing = sata_ehc_deb_timing(ehc);
 	int rc;
 
-	/* handle link resume */
-	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
-	    (link->flags & ATA_LFLAG_HRST_TO_RESUME))
-		ehc->i.action |= ATA_EH_HARDRESET;
-
-	/* Some PMPs don't work with only SRST, force hardreset if PMP
-	 * is supported.
-	 */
-	if (ap->flags & ATA_FLAG_PMP)
-		ehc->i.action |= ATA_EH_HARDRESET;
-
 	/* if we're about to do hardreset, nothing more to do */
 	if (ehc->i.action & ATA_EH_HARDRESET)
 		return 0;
@@ -6007,9 +5996,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
 		if (ata_sg_setup(qc))
 			goto sg_err;
 
-	/* if device is sleeping, schedule softreset and abort the link */
+	/* if device is sleeping, schedule reset and abort the link */
 	if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
-		link->eh_info.action |= ATA_EH_SOFTRESET;
+		link->eh_info.action |= ATA_EH_RESET;
 		ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
 		ata_link_abort(link);
 		return;
@@ -6586,7 +6575,7 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
  */
 void ata_host_resume(struct ata_host *host)
 {
-	ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
+	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;
 
@@ -7123,7 +7112,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 
 			ehi->probe_mask =
 				(1 << ata_link_max_devices(&ap->link)) - 1;
-			ehi->action |= ATA_EH_SOFTRESET;
+			ehi->action |= ATA_EH_RESET;
 			ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
 			ap->pflags &= ~ATA_PFLAG_INITIALIZING;
drivers/ata/libata-eh.c +35 -64

244 lines not on this page · raw message

drivers/ata/libata-pmp.c +8 -20
index d91f509..8439fc8 100644
@@ -194,15 +194,6 @@ int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
 	const unsigned long *timing = sata_ehc_deb_timing(ehc);
 	int rc;
 
-	/* force HRST? */
-	if (link->flags & ATA_LFLAG_NO_SRST)
-		ehc->i.action |= ATA_EH_HARDRESET;
-
-	/* handle link resume */
-	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
-	    (link->flags & ATA_LFLAG_HRST_TO_RESUME))
-		ehc->i.action |= ATA_EH_HARDRESET;
-
 	/* if we're about to do hardreset, nothing more to do */
 	if (ehc->i.action & ATA_EH_HARDRESET)
 		return 0;
@@ -445,7 +436,7 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
 
 		link->flags = 0;
 		ehc->i.probe_mask |= 1;
-		ehc->i.action |= ATA_EH_SOFTRESET;
+		ehc->i.action |= ATA_EH_RESET;
 		ehc->i.flags |= ATA_EHI_RESUME_LINK;
 	}
 
@@ -840,13 +831,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
  retry:
 	ehc->classes[0] = ATA_DEV_UNKNOWN;
 
-	if (ehc->i.action & ATA_EH_RESET_MASK) {
+	if (ehc->i.action & ATA_EH_RESET) {
 		struct ata_link *tlink;
 
 		ata_eh_freeze_port(ap);
 
 		/* reset */
-		ehc->i.action = ATA_EH_HARDRESET;
 		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
 				  postreset);
 		if (rc) {
@@ -890,11 +880,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 				reval_failed = 1;
 
 			ata_dev_printk(dev, KERN_WARNING,
-				       "retrying hardreset%s\n",
+				       "retrying reset%s\n",
 				       sleep ? " in 5 secs" : "");
 			if (sleep)
 				ssleep(5);
-			ehc->i.action |= ATA_EH_HARDRESET;
+			ehc->i.action |= ATA_EH_RESET;
 			goto retry;
 		} else {
 			ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
@@ -938,10 +928,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
 		/* Some PMPs require hardreset sequence to get
 		 * SError.N working.
 		 */
-		if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) &&
-		    (link->eh_context.i.flags & ATA_EHI_RESUME_LINK))
-			sata_link_hardreset(link, sata_deb_timing_normal,
-					    jiffies + ATA_TMOUT_INTERNAL_QUICK);
+		sata_link_hardreset(link, sata_deb_timing_normal,
+				    jiffies + ATA_TMOUT_INTERNAL_QUICK);
 
 		/* unconditionally clear SError.N */
 		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
@@ -1124,7 +1112,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
 
  link_fail:
 	if (sata_pmp_handle_link_fail(link, link_tries)) {
-		pmp_ehc->i.action |= ATA_EH_HARDRESET;
+		pmp_ehc->i.action |= ATA_EH_RESET;
 		goto retry;
 	}
 
@@ -1142,7 +1130,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
 	if (--pmp_tries) {
 		ata_port_printk(ap, KERN_WARNING,
 				"failed to recover PMP, retrying in 5 secs\n");
-		pmp_ehc->i.action |= ATA_EH_HARDRESET;
+		pmp_ehc->i.action |= ATA_EH_RESET;
 		ssleep(5);
 		goto retry;
 	}
drivers/ata/libata-scsi.c +2 -2
index 8f0e8f2..3270d21 100644
@@ -3500,7 +3500,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 		ata_port_for_each_link(link, ap) {
 			struct ata_eh_info *ehi = &link->eh_info;
 			ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
-			ehi->action |= ATA_EH_SOFTRESET;
+			ehi->action |= ATA_EH_RESET;
 		}
 	} else {
 		struct ata_device *dev = ata_find_dev(ap, devno);
@@ -3508,7 +3508,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 		if (dev) {
 			struct ata_eh_info *ehi = &dev->link->eh_info;
 			ehi->probe_mask |= 1 << dev->devno;
-			ehi->action |= ATA_EH_SOFTRESET;
+			ehi->action |= ATA_EH_RESET;
 			ehi->flags |= ATA_EHI_RESUME_LINK;
 		} else
 			rc = -EINVAL;
drivers/ata/sata_fsl.c +1 -1
index 07791a7..7749e04 100644
@@ -996,7 +996,7 @@ static void sata_fsl_error_intr(struct ata_port *ap)
 	/* handle fatal errors */
 	if (hstatus & FATAL_ERROR_DECODE) {
 		err_mask |= AC_ERR_ATA_BUS;
-		action |= ATA_EH_SOFTRESET;
+		action |= ATA_EH_RESET;
 		/* how will fatal error interrupts be completed ?? */
 		freeze = 1;
 	}
drivers/ata/sata_mv.c +8 -23
index 6ebebde..a4944c8 100644
@@ -1524,14 +1524,14 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
 			EDMA_ERR_INTRL_PAR)) {
 		err_mask |= AC_ERR_ATA_BUS;
-		action |= ATA_EH_HARDRESET;
+		action |= ATA_EH_RESET;
 		ata_ehi_push_desc(ehi, "parity error");
 	}
 	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
 		ata_ehi_hotplugged(ehi);
 		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
 			"dev disconnect" : "dev connect");
-		action |= ATA_EH_HARDRESET;
+		action |= ATA_EH_RESET;
 	}
 
 	if (IS_GEN_I(hpriv)) {
@@ -1555,7 +1555,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 			sata_scr_read(&ap->link, SCR_ERROR, &serr);
 			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
 			err_mask = AC_ERR_ATA_BUS;
-			action |= ATA_EH_HARDRESET;
+			action |= ATA_EH_RESET;
 		}
 	}
 
@@ -1564,7 +1564,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 
 	if (!err_mask) {
 		err_mask = AC_ERR_OTHER;
-		action |= ATA_EH_HARDRESET;
+		action |= ATA_EH_RESET;
 	}
 
 	ehi->serror |= serr;
@@ -1780,7 +1780,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
 				ata_ehi_push_desc(ehi,
 					"PCI err cause 0x%08x", err_cause);
 			err_mask = AC_ERR_HOST_BUS;
-			ehi->action = ATA_EH_HARDRESET;
+			ehi->action = ATA_EH_RESET;
 			qc = ata_qc_from_tag(ap, ap->link.active_tag);
 			if (qc)
 				qc->err_mask |= err_mask;
@@ -2449,28 +2449,13 @@ static int mv_prereset(struct ata_link *link, unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
 	struct mv_port_priv *pp	= ap->private_data;
-	struct ata_eh_context *ehc = &link->eh_context;
-	int rc;
 
-	rc = mv_stop_dma(ap);
-	if (rc)
-		ehc->i.action |= ATA_EH_HARDRESET;
+	mv_stop_dma(ap);
 
-	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET))
 		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
-		ehc->i.action |= ATA_EH_HARDRESET;
-	}
-
-	/* if we're about to do hardreset, nothing more to do */
-	if (ehc->i.action & ATA_EH_HARDRESET)
-		return 0;
-
-	if (ata_link_online(link))
-		rc = ata_wait_ready(ap, deadline);
-	else
-		rc = -ENODEV;
 
-	return rc;
+	return 0;
 }
 
 static int mv_hardreset(struct ata_link *link, unsigned int *class,
drivers/ata/sata_nv.c +6 -6
index ed5473b..ce02e15 100644
@@ -929,7 +929,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
 					"notifier for tag %d with no cmd?\n",
 					cpb_num);
 			ehi->err_mask |= AC_ERR_HSM;
-			ehi->action |= ATA_EH_SOFTRESET;
+			ehi->action |= ATA_EH_RESET;
 			ata_port_freeze(ap);
 			return 1;
 		}
@@ -1892,7 +1892,7 @@ static void nv_swncq_error_handler(struct ata_port *ap)
 
 	if (ap->link.sactive) {
 		nv_swncq_ncq_stop(ap);
-		ehc->i.action |= ATA_EH_HARDRESET;
+		ehc->i.action |= ATA_EH_RESET;
 	}
 
 	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
@@ -2173,7 +2173,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
 		ata_ehi_clear_desc(ehi);
 		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
 		ehi->err_mask |= AC_ERR_HOST_BUS;
-		ehi->action |= ATA_EH_SOFTRESET;
+		ehi->action |= ATA_EH_RESET;
 		return -EINVAL;
 	}
 
@@ -2188,7 +2188,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
 		ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
 				  "(%08x->%08x)", pp->qc_active, sactive);
 		ehi->err_mask |= AC_ERR_HSM;
-		ehi->action |= ATA_EH_HARDRESET;
+		ehi->action |= ATA_EH_RESET;
 		return -EINVAL;
 	}
 	for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -2324,7 +2324,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
 		ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
 		ehi->err_mask |= AC_ERR_DEV;
 		ehi->serror |= serror;
-		ehi->action |= ATA_EH_SOFTRESET;
+		ehi->action |= ATA_EH_RESET;
 		ata_port_freeze(ap);
 		return;
 	}
@@ -2356,7 +2356,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
 		if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
 			ata_ehi_push_desc(ehi, "illegal fis transaction");
 			ehi->err_mask |= AC_ERR_HSM;
-			ehi->action |= ATA_EH_HARDRESET;
+			ehi->action |= ATA_EH_RESET;
 			goto irq_error;
 		}
 
drivers/ata/sata_sil24.c +27 -27

119 lines not on this page · raw message

drivers/ata/sata_via.c +1 -1
index 0d03f44..c0e0f1d 100644
@@ -320,7 +320,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
 
 	if (!online) {
 		/* tell EH to bail */
-		ehc->i.action &= ~ATA_EH_RESET_MASK;
+		ehc->i.action &= ~ATA_EH_RESET;
 		return 0;
 	}
 
include/linux/libata.h +4 -4
index a05f600..618fbf2 100644
@@ -292,11 +292,11 @@ enum {
 
 	/* reset / recovery action types */
 	ATA_EH_REVALIDATE	= (1 << 0),
-	ATA_EH_SOFTRESET	= (1 << 1),
-	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_SOFTRESET	= (1 << 1), /* meaningful only in ->prereset */
+	ATA_EH_HARDRESET	= (1 << 2), /* meaningful only in ->prereset */
+	ATA_EH_RESET		= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
 	ATA_EH_ENABLE_LINK	= (1 << 3),
 
-	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
 	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
 
 	/* ata_eh_info->flags */
@@ -1094,7 +1094,7 @@ extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
 static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
 {
 	ehi->flags |= ATA_EHI_RESUME_LINK;
-	ehi->action |= ATA_EH_SOFTRESET;
+	ehi->action |= ATA_EH_RESET;
 	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
 }
 
Signature · 1 line
1.5.2.4
author
#2 lore raw

PATCH 2/5 libata: kill ATA_LFLAG_HRST_TO_RESUME

In reply to Tejun Heo

Now that hardreset is the preferred method of resetting, there's no need for ATA_LFLAG_HRST_TO_RESUME flag. Kill it.

---
 drivers/ata/ahci.c       |    2 +-
 drivers/ata/libata-pmp.c |   16 ----------------
 drivers/ata/sata_nv.c    |    5 -----
 drivers/ata/sata_sil.c   |    5 -----
 include/linux/libata.h   |    1 -
 5 files changed, 1 insertions(+), 28 deletions(-)
drivers/ata/ahci.c +1 -1
index b88b38a..826a996 100644
@@ -412,7 +412,7 @@ static const struct ata_port_info ahci_port_info[] = {
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON | ATA_LFLAG_HRST_TO_RESUME,
+		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
drivers/ata/libata-pmp.c +0 -16
index 8439fc8..7f8bcff 100644
@@ -453,9 +453,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
 	if (vendor == 0x1095 && devid == 0x3726) {
 		/* sil3726 quirks */
 		ata_port_for_each_link(link, ap) {
-			/* SError.N need a kick in the ass to get working */
-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
-
 			/* class code report is unreliable */
 			if (link->pmp < 5)
 				link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -468,9 +465,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
 	} else if (vendor == 0x1095 && devid == 0x4723) {
 		/* sil4723 quirks */
 		ata_port_for_each_link(link, ap) {
-			/* SError.N need a kick in the ass to get working */
-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
-
 			/* class code report is unreliable */
 			if (link->pmp < 2)
 				link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -483,9 +477,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
 	} else if (vendor == 0x1095 && devid == 0x4726) {
 		/* sil4726 quirks */
 		ata_port_for_each_link(link, ap) {
-			/* SError.N need a kick in the ass to get working */
-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
-
 			/* Class code report is unreliable and SRST
 			 * times out under certain configurations.
 			 * Config device can be at port 0 or 5 and
@@ -513,13 +504,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
 		 * otherwise.  Don't try hard to recover it.
 		 */
 		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
-	} else if (vendor == 0x11ab && devid == 0x4140) {
-		/* Marvell 88SM4140 quirks.  Fan-out ports require PHY
-		 * reset to work; other than that, it behaves very
-		 * nicely.
-		 */
-		ata_port_for_each_link(link, ap)
-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
 	}
 }
 
drivers/ata/sata_nv.c +0 -5
index ce02e15..75b7653 100644
@@ -579,7 +579,6 @@ static const struct ata_port_info nv_port_info[] = {
 	{
 		.sht		= &nv_sht,
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -590,7 +589,6 @@ static const struct ata_port_info nv_port_info[] = {
 	{
 		.sht		= &nv_sht,
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -601,7 +599,6 @@ static const struct ata_port_info nv_port_info[] = {
 	{
 		.sht		= &nv_sht,
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -613,7 +610,6 @@ static const struct ata_port_info nv_port_info[] = {
 		.sht		= &nv_adma_sht,
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -625,7 +621,6 @@ static const struct ata_port_info nv_port_info[] = {
 		.sht		= &nv_swncq_sht,
 		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_NCQ,
-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
drivers/ata/sata_sil.c +0 -5
index 0b8191b..7052915 100644
@@ -60,7 +60,6 @@ enum {
 
 	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO,
-	SIL_DFL_LINK_FLAGS	= ATA_LFLAG_HRST_TO_RESUME,
 
 	/*
 	 * Controller IDs
@@ -215,7 +214,6 @@ static const struct ata_port_info sil_port_info[] = {
 	/* sil_3112 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
-		.link_flags	= SIL_DFL_LINK_FLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,
@@ -225,7 +223,6 @@ static const struct ata_port_info sil_port_info[] = {
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
 				  SIL_FLAG_NO_SATA_IRQ,
-		.link_flags	= SIL_DFL_LINK_FLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,
@@ -234,7 +231,6 @@ static const struct ata_port_info sil_port_info[] = {
 	/* sil_3512 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-		.link_flags	= SIL_DFL_LINK_FLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,
@@ -243,7 +239,6 @@ static const struct ata_port_info sil_port_info[] = {
 	/* sil_3114 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-		.link_flags	= SIL_DFL_LINK_FLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,
include/linux/libata.h +0 -1
index 618fbf2..8921c1c 100644
@@ -163,7 +163,6 @@ enum {
 	ATA_DEV_NONE		= 9,	/* no device */
 
 	/* struct ata_link flags */
-	ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
 	ATA_LFLAG_SKIP_D2H_BSY	= (1 << 1), /* can't wait for the first D2H
 					     * Register FIS clearing BSY */
 	ATA_LFLAG_NO_SRST	= (1 << 2), /* avoid softreset */
Signature · 1 line
1.5.2.4
author
#3 lore raw

PATCH 3/5 libata: kill ATA_EHI_RESUME_LINK

In reply to Tejun Heo

ATA_EHI_RESUME_LINK has two functions - promote reset to hardreset if ATA_LFLAG_HRST_TO_RESUME is set and preventing EH from shortcutting reset action when probing is requested. The former is gone now and the latter can easily be achieved by making EH to perform at least one reset if reset is requested, which also makes more sense than depending on RESUME_LINK flag.

As ATA_EHI_RESUME_LINK was the only EHI reset modifier, this also kills reset modifier handling.

---
 drivers/ata/libata-eh.c   |   21 ++++++++-------------
 drivers/ata/libata-pmp.c  |    1 -
 drivers/ata/libata-scsi.c |    1 -
 include/linux/libata.h    |    3 ---
 4 files changed, 8 insertions(+), 18 deletions(-)
drivers/ata/libata-eh.c +8 -13
index 2dd0a2b..5969471 100644
@@ -1079,12 +1079,6 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
 
 	spin_lock_irqsave(ap->lock, flags);
 
-	/* suck in and clear reset modifier */
-	if (action & ATA_EH_RESET) {
-		ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
-		ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
-	}
-
 	ata_eh_clear_action(link, dev, ehi, action);
 
 	if (!(ehc->i.flags & ATA_EHI_QUIET))
@@ -1110,10 +1104,6 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
 {
 	struct ata_eh_context *ehc = &link->eh_context;
 
-	/* if reset is complete, clear reset modifier */
-	if (action & ATA_EH_RESET)
-		ehc->i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
-
 	ata_eh_clear_action(link, dev, &ehc->i, action);
 }
 
@@ -2491,6 +2481,7 @@ static int ata_link_nr_vacant(struct ata_link *link)
 
 static int ata_eh_skip_recovery(struct ata_link *link)
 {
+	struct ata_port *ap = link->ap;
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_device *dev;
 
@@ -2498,9 +2489,13 @@ static int ata_eh_skip_recovery(struct ata_link *link)
 	if (link->flags & ATA_LFLAG_DISABLED)
 		return 1;
 
-	/* thaw frozen port, resume link and recover failed devices */
-	if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
-	    (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
+	/* thaw frozen port and recover failed devices */
+	if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
+		return 0;
+
+	/* reset at least once if reset is requested */
+	if ((ehc->i.action & ATA_EH_RESET) &&
+	    !(ehc->i.flags & ATA_EHI_DID_RESET))
 		return 0;
 
 	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
drivers/ata/libata-pmp.c +0 -1
index 7f8bcff..df1d325 100644
@@ -437,7 +437,6 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
 		link->flags = 0;
 		ehc->i.probe_mask |= 1;
 		ehc->i.action |= ATA_EH_RESET;
-		ehc->i.flags |= ATA_EHI_RESUME_LINK;
 	}
 
 	return 0;
drivers/ata/libata-scsi.c +0 -1
index 3270d21..d3b8291 100644
@@ -3509,7 +3509,6 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 			struct ata_eh_info *ehi = &dev->link->eh_info;
 			ehi->probe_mask |= 1 << dev->devno;
 			ehi->action |= ATA_EH_RESET;
-			ehi->flags |= ATA_EHI_RESUME_LINK;
 		} else
 			rc = -EINVAL;
 	}
include/linux/libata.h +0 -3
index 8921c1c..2df65b7 100644
@@ -300,7 +300,6 @@ enum {
 
 	/* ata_eh_info->flags */
 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
-	ATA_EHI_RESUME_LINK	= (1 << 1),  /* resume link (reset modifier) */
 	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
 	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
 	ATA_EHI_LPM		= (1 << 4),  /* link power management action */
@@ -312,7 +311,6 @@ enum {
 	ATA_EHI_POST_SETMODE	= (1 << 20), /* revaildating after setmode */
 
 	ATA_EHI_DID_RESET	= ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
-	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
 
 	/* max tries if error condition is still set after ->error_handler */
 	ATA_EH_MAX_TRIES	= 5,
@@ -1092,7 +1090,6 @@ extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
 
 static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
 {
-	ehi->flags |= ATA_EHI_RESUME_LINK;
 	ehi->action |= ATA_EH_RESET;
 	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
 }
Signature · 1 line
1.5.2.4
author
#4 lore raw

PATCH 4/5 libata: kill ATA_LFLAG_SKIP_D2H_BSY

In reply to Tejun Heo

Some controllers can't reliably record the initial D2H FIS after SATA link is brought online for whatever reason. Advanced controllers which don't have traditional TF register based interface often have this problem as they don't really have the TF registers to update while the controller and link are being initialized.

SKIP_D2H_BSY works around the problem by skipping the wait for device readiness before issuing SRST, so for such controllers libata issues SRST blindly and hopes for the best.

Now that libata defaults to hardreset, this workaround is no longer necessary. For controllers which have support for hardreset, SRST is never issued by itself. It is only issued as follow-up SRST for device classification and PMP initialization, so there's no need to wait for it from prereset.

Kill ATA_LFLAG_SKIP_D2H_BSY.

---
 drivers/ata/ahci.c        |    7 -------
 drivers/ata/libata-core.c |    6 ++----
 drivers/ata/sata_fsl.c    |    2 --
 drivers/ata/sata_sil24.c  |    4 ----
 include/linux/libata.h    |    2 --
 5 files changed, 2 insertions(+), 19 deletions(-)
drivers/ata/ahci.c +0 -7
index 826a996..546907a 100644
@@ -194,7 +194,6 @@ enum {
 					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
 					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
 					  ATA_FLAG_IPM,
-	AHCI_LFLAG_COMMON		= ATA_LFLAG_SKIP_D2H_BSY,
 
 	ICH_MAP				= 0x90, /* ICH MAP register */
 };
@@ -403,7 +402,6 @@ static const struct ata_port_info ahci_port_info[] = {
 	/* board_ahci */
 	{
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -412,7 +410,6 @@ static const struct ata_port_info ahci_port_info[] = {
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
@@ -421,7 +418,6 @@ static const struct ata_port_info ahci_port_info[] = {
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -431,7 +427,6 @@ static const struct ata_port_info ahci_port_info[] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
 				 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -442,7 +437,6 @@ static const struct ata_port_info ahci_port_info[] = {
 				 AHCI_HFLAG_MV_PATA),
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -452,7 +446,6 @@ static const struct ata_port_info ahci_port_info[] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
 				 AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.link_flags	= AHCI_LFLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
drivers/ata/libata-core.c +2 -4
index b3ebc3e..18925ed 100644
@@ -3914,10 +3914,8 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
 					"link for reset (errno=%d)\n", rc);
 	}
 
-	/* Wait for !BSY if the controller can wait for the first D2H
-	 * Reg FIS and we don't know that no device is attached.
-	 */
-	if (!(link->flags & ATA_LFLAG_SKIP_D2H_BSY) && !ata_link_offline(link)) {
+	/* wait for !BSY if we don't know that no device is attached */
+	if (!ata_link_offline(link)) {
 		rc = ata_wait_ready(ap, deadline);
 		if (rc && rc != -ENODEV) {
 			ata_link_printk(link, KERN_WARNING, "device not ready "
drivers/ata/sata_fsl.c +0 -2
index 7749e04..ec96bae 100644
@@ -35,7 +35,6 @@ enum {
 	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
 				ATA_FLAG_NCQ),
-	SATA_FSL_HOST_LFLAGS	= ATA_LFLAG_SKIP_D2H_BSY,
 
 	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH,
 	SATA_FSL_CMD_HDR_SIZE	= 16,	/* 4 DWORDS */
@@ -1241,7 +1240,6 @@ static const struct ata_port_operations sata_fsl_ops = {
 static const struct ata_port_info sata_fsl_port_info[] = {
 	{
 	 .flags = SATA_FSL_HOST_FLAGS,
-	 .link_flags = SATA_FSL_HOST_LFLAGS,
 	 .pio_mask = 0x1f,	/* pio 0-4 */
 	 .udma_mask = 0x7f,	/* udma 0-6 */
 	 .port_ops = &sata_fsl_ops,
drivers/ata/sata_sil24.c +0 -4
index aa8d032..ba0c00e 100644
@@ -254,7 +254,6 @@ enum {
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
 				  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
 				  ATA_FLAG_AN | ATA_FLAG_PMP,
-	SIL24_COMMON_LFLAGS	= ATA_LFLAG_SKIP_D2H_BSY,
 	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */
 
 	IRQ_STAT_4PORTS		= 0xf,
@@ -449,7 +448,6 @@ static const struct ata_port_info sil24_port_info[] = {
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
 				  SIL24_FLAG_PCIX_IRQ_WOC,
-		.link_flags	= SIL24_COMMON_LFLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
@@ -458,7 +456,6 @@ static const struct ata_port_info sil24_port_info[] = {
 	/* sil_3132 */
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
-		.link_flags	= SIL24_COMMON_LFLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
@@ -467,7 +464,6 @@ static const struct ata_port_info sil24_port_info[] = {
 	/* sil_3131/sil_3531 */
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
-		.link_flags	= SIL24_COMMON_LFLAGS,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
include/linux/libata.h +0 -2
index 2df65b7..95a1a86 100644
@@ -163,8 +163,6 @@ enum {
 	ATA_DEV_NONE		= 9,	/* no device */
 
 	/* struct ata_link flags */
-	ATA_LFLAG_SKIP_D2H_BSY	= (1 << 1), /* can't wait for the first D2H
-					     * Register FIS clearing BSY */
 	ATA_LFLAG_NO_SRST	= (1 << 2), /* avoid softreset */
 	ATA_LFLAG_ASSUME_ATA	= (1 << 3), /* assume ATA class */
 	ATA_LFLAG_ASSUME_SEMB	= (1 << 4), /* assume SEMB class */
Signature · 1 line
1.5.2.4
author
#5 lore raw

PATCH 5/5 libata: kill ata_ehi_schedule_probe()

In reply to Tejun Heo

ata_ehi_schedule_probe() was created to hide details of link-resuming reset magic. Now that all the softreset workarounds are gone, scheduling probe is very simple - set probe_mask and request RESET. Kill ata_ehi_schedule_probe() and open code it. This also increases consistency as ata_ehi_schedule_probe() couldn't cover individual device probings so they were open-coded even when the helper existed.

While at it, define ATA_ALL_DEVICES as mask of all possible devices on a link and always use it when requesting probe on link level for simplicity and consistency. Setting extra bits in the probe_mask doesn't hurt anybody.

---
 drivers/ata/libata-core.c |    3 +--
 drivers/ata/libata-eh.c   |    2 +-
 drivers/ata/libata-pmp.c  |   12 ++++++++----
 drivers/ata/libata-scsi.c |    2 +-
 include/linux/libata.h    |   12 ++++--------
 5 files changed, 15 insertions(+), 16 deletions(-)
drivers/ata/libata-core.c +1 -2
index 18925ed..4b64edd 100644
@@ -7108,8 +7108,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 			/* kick EH for boot probing */
 			spin_lock_irqsave(ap->lock, flags);
 
-			ehi->probe_mask =
-				(1 << ata_link_max_devices(&ap->link)) - 1;
+			ehi->probe_mask |= ATA_ALL_DEVICES;
 			ehi->action |= ATA_EH_RESET;
 			ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
drivers/ata/libata-eh.c +1 -1
index 5969471..611ecb1 100644
@@ -1746,7 +1746,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
 		ata_eh_analyze_serror(link);
 	} else if (rc != -EOPNOTSUPP) {
 		/* SError read failed, force reset and probing */
-		ata_ehi_schedule_probe(&ehc->i);
+		ehc->i.probe_mask |= ATA_ALL_DEVICES;
 		ehc->i.action |= ATA_EH_RESET;
 		ehc->i.err_mask |= AC_ERR_OTHER;
 	}
drivers/ata/libata-pmp.c +8 -4
index df1d325..39e036c 100644
@@ -435,7 +435,7 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
 		struct ata_eh_context *ehc = &link->eh_context;
 
 		link->flags = 0;
-		ehc->i.probe_mask |= 1;
+		ehc->i.probe_mask |= ATA_ALL_DEVICES;
 		ehc->i.action |= ATA_EH_RESET;
 	}
 
@@ -831,8 +831,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 		ata_eh_thaw_port(ap);
 
 		/* PMP is reset, SErrors cannot be trusted, scan all */
-		ata_port_for_each_link(tlink, ap)
-			ata_ehi_schedule_probe(&tlink->eh_context.i);
+		ata_port_for_each_link(tlink, ap) {
+			struct ata_eh_context *ehc = &tlink->eh_context;
+
+			ehc->i.probe_mask |= ATA_ALL_DEVICES;
+			ehc->i.action |= ATA_EH_RESET;
+		}
 	}
 
 	/* If revalidation is requested, revalidate and reconfigure;
@@ -847,7 +851,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 		tries--;
 
 		if (rc == -ENODEV) {
-			ehc->i.probe_mask |= 1;
+			ehc->i.probe_mask |= ATA_ALL_DEVICES;
 			detach = 1;
 			/* give it just two more chances */
 			tries = min(tries, 2);
drivers/ata/libata-scsi.c +1 -1
index d3b8291..5dd3877 100644
@@ -3499,7 +3499,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 
 		ata_port_for_each_link(link, ap) {
 			struct ata_eh_info *ehi = &link->eh_info;
-			ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
+			ehi->probe_mask |= ATA_ALL_DEVICES;
 			ehi->action |= ATA_EH_RESET;
 		}
 	} else {
include/linux/libata.h +4 -8
index 95a1a86..0fef10e 100644
@@ -122,6 +122,8 @@ enum {
 
 	ATAPI_MAX_DRAIN		= 16 << 10,
 
+	ATA_ALL_DEVICES		= (1 << ATA_MAX_DEVICES) - 1,
+
 	ATA_SHT_EMULATED	= 1,
 	ATA_SHT_CMD_PER_LUN	= 1,
 	ATA_SHT_THIS_ID		= -1,
@@ -1086,17 +1088,11 @@ extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
 	__attribute__ ((format (printf, 2, 3)));
 extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
 
-static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
-{
-	ehi->action |= ATA_EH_RESET;
-	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
-}
-
 static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
 {
-	ata_ehi_schedule_probe(ehi);
+	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
 	ehi->flags |= ATA_EHI_HOTPLUGGED;
-	ehi->action |= ATA_EH_ENABLE_LINK;
+	ehi->action |= ATA_EH_RESET | ATA_EH_ENABLE_LINK;
 	ehi->err_mask |= AC_ERR_ATA_BUS;
 }
 
Signature · 1 line
1.5.2.4
author
#6 lore raw

Subject should be [PATCHSET libata-dev#upstream-fixes] libata: prefer hardreset, take #3

In reply to Tejun Heo

Patchset subject was wrong. Sorry about the confusion.

Signature · 1 line
tejun
#7 lore raw

Re: Subject should be [PATCHSET libata-dev#upstream-fixes] libata: prefer hardreset, take #3

Tejun Heo wrote (in first mail with wrong Subject):

Quoted 2 lines

It still needs Mikael's ack regarding behavior
change on sata_promise.

Unfortunately it breaks sata_promise:

ata5: SATA link up 3.0 Gbps (SStatus 123 SControl 300) ata5.00: ATA-7: ST3120813AS, 3.AAD, max UDMA/133 ata5.00: 234441648 sectors, multi 0: LBA48 NCQ (depth 0/32) ata5.00: configured for UDMA/133
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t4
ata5: hotplug_status 0x10
ata5: hard resetting link
ata5: SATA link up 3.0 Gbps (SStatus 123 SControl 300) ata5.00: configured for UDMA/133
ata5: limiting SATA link speed to 1.5 Gbps
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t3
ata5: hotplug_status 0x10
ata5: hard resetting link
ata5: SATA link up 1.5 Gbps (SStatus 113 SControl 310) ata5.00: configured for UDMA/133
ata5.00: limiting speed to UDMA/100:PIO4
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t2
ata5: hotplug_status 0x10
ata5: hard resetting link
ata5: SATA link up 1.5 Gbps (SStatus 113 SControl 310) ata5.00: configured for UDMA/100
ata5.00: limiting speed to UDMA/33:PIO4
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t1
ata5: hotplug_status 0x10
ata5: hard resetting link
ata5: SATA link up 1.5 Gbps (SStatus 113 SControl 310) ata5.00: configured for UDMA/33
ata5: EH pending after 5 tries, giving up
ata5: EH complete

What happens is that a hard reset triggers cable sensing and reporting, so we get stray hotplug events which confuses things.

One solution is to mask/unmask a port's hotplug events around calls to sata_std_hardreset(). (This also matches what Promise's reference driver does, except their hard reset fiddles with Promise specific registers.) The patch below is a draft which implements that solution.

A problem is that Promise SATA chips implement per-port hotplug control using port-specific bits in a single global register. So I have to map the link to the corresponding ata engine number:
this mapping doesn't seem to be present anywhere, so in this draft patch I'm resorting to searching the host's ports[] array.

Also, since the ports share a global register it's important that at most one port goes through a hard reset sequence at a time. Can I assume that libata EH guarantees mutual exclusion?

With this patch in place the hard reset conversion does seem to work Ok on a SATA300 TX4 card.

/Mikael

drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +57 -14
@@ -673,9 +673,65 @@ static void pdc_pata_error_handler(struc
 	pdc_common_error_handler(ap, NULL);
 }
 
+static int pdc_is_sataii_tx4(unsigned long flags)
+{
+	const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+	return (flags & mask) == mask;
+}
+
+static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
+					  int is_sataii_tx4)
+{
+	static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+	return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
+static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
+			      unsigned long deadline)
+{
+	struct ata_port *ap = link->ap;
+	struct ata_host *host = ap->host;
+	void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
+	unsigned int hotplug_offset, ata_no;
+	u32 hotplug_status;
+	int is_sataii_tx4, i, ret;
+
+	if (host->ports[0]->flags & PDC_FLAG_GEN_II)
+		hotplug_offset = PDC2_SATA_PLUG_CSR;
+	else
+		hotplug_offset = PDC_SATA_PLUG_CSR;
+	is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
+
+	/* XXX: this is gross and only works for 4-port SATA chips */
+	for(i = 0; i < 4/*XXX: how to detect # ports?*/ && host->ports[i] != ap; ++i)
+		;
+	if (i >= 4) {
+		printk(KERN_ERR "%s: unable to map ap to ata_no\n", __FUNCTION__);
+		return sata_std_hardreset(link, class, deadline);
+	}
+	ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+
+	hotplug_status = readl(mmio_base + hotplug_offset);
+
+	/* clear hotplug flags, mask hotplug ints */
+	hotplug_status |= (0x11 << ata_no);
+	hotplug_status |= (0x11 << ata_no) << 16;
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */
+
+	ret = sata_std_hardreset(link, class, deadline);
+
+	/* clear hotplug flags, unmask hotplug ints */
+	hotplug_status &= ~((0x11 << ata_no) << 16);
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */
+
+	return ret;
+}
+
 static void pdc_sata_error_handler(struct ata_port *ap)
 {
-	pdc_common_error_handler(ap, sata_std_hardreset);
+	pdc_common_error_handler(ap, pdc_sata_hardreset);
 }
 
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -765,19 +821,6 @@ static void pdc_irq_clear(struct ata_por
 	readl(mmio + PDC_INT_SEQMASK);
 }
 
-static int pdc_is_sataii_tx4(unsigned long flags)
-{
-	const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
-	return (flags & mask) == mask;
-}
-
-static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
-					  int is_sataii_tx4)
-{
-	static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
-	return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
-}
-
 static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
author
#8 lore raw

Re: Subject should be [PATCHSET libata-dev#upstream-fixes] libata: prefer hardreset, take #3

Hello, Mikael.

Thanks for testing.

Quoted 6 lines · Mikael Pettersson

Tejun Heo wrote (in first mail with wrong Subject):

Quoted 2 lines

It still needs Mikael's ack regarding behavior
change on sata_promise.

Unfortunately it breaks sata_promise:

Quoted 7 lines

ata5: SATA link up 3.0 Gbps (SStatus 123 SControl 300) ata5.00: ATA-7: ST3120813AS, 3.AAD, max UDMA/133 ata5.00: 234441648 sectors, multi 0: LBA48 NCQ (depth 0/32) ata5.00: configured for UDMA/133
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t4
ata5: hotplug_status 0x10
ata5: hard resetting link

Eeeek, this means that ->hardreset is already broken on sata_promise which gotta be fixed as it will lead to hardreset loops whenever softreset fails.

Quoted 8 lines

What happens is that a hard reset triggers cable sensing and reporting, so we get stray hotplug events which confuses things.

One solution is to mask/unmask a port's hotplug events around calls to sata_std_hardreset(). (This also matches what Promise's reference driver does, except their hard reset fiddles with Promise specific registers.) The patch below is a draft which implements that solution.

That can be done in either ->freeze/->thaw or ->postreset depending on symmetry of things. If ->freeze plugs hotplug interrupts too, it's probably best to clear hotplug events in ->thaw before unblocking hotplug events.

Quoted 5 lines

A problem is that Promise SATA chips implement per-port hotplug control using port-specific bits in a single global register. So I have to map the link to the corresponding ata engine number:
this mapping doesn't seem to be present anywhere, so in this draft patch I'm resorting to searching the host's ports[] array.

Hmmm....

Quoted 3 lines

Also, since the ports share a global register it's important that at most one port goes through a hard reset sequence at a time. Can I assume that libata EH guarantees mutual exclusion?

There currently is no cross-port synchronization but you can always grab host->lock for that.

Quoted 2 lines

With this patch in place the hard reset conversion does seem to work Ok on a SATA300 TX4 card.

[--snip--]

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 706

Quoted 1 line
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +1 -0
+	for(i = 0; i < 4/*XXX: how to detect # ports?*/ && host->ports[i] != ap; ++i)

host->n_ports?

Quoted 4 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +4 -0
+		;
+	if (i >= 4) {
+		printk(KERN_ERR "%s: unable to map ap to ata_no\n", __FUNCTION__);
+		return sata_std_hardreset(link, class, deadline);

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 720

Quoted 10 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +10 -0
+	}
+	ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+
+	hotplug_status = readl(mmio_base + hotplug_offset);
+
+	/* clear hotplug flags, mask hotplug ints */
+	hotplug_status |= (0x11 << ata_no);
+	hotplug_status |= (0x11 << ata_no) << 16;
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

I think this belongs to ->freeze().

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 727

Quoted 6 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +6 -0
+	ret = sata_std_hardreset(link, class, deadline);
+
+	/* clear hotplug flags, unmask hotplug ints */
+	hotplug_status &= ~((0x11 << ata_no) << 16);
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

And this to ->thaw().

Thanks.

Signature · 1 line
tejun
#9 lore raw

Re: Subject should be [PATCHSET libata-dev#upstream-fixes] libata: prefer hardreset, take #3

Quoted 19 lines · Tejun Heo

Hello, Mikael.

Thanks for testing.

Quoted 6 lines · Mikael Pettersson

Tejun Heo wrote (in first mail with wrong Subject):

Quoted 2 lines

It still needs Mikael's ack regarding behavior
change on sata_promise.

Unfortunately it breaks sata_promise:

Quoted 7 lines

ata5: SATA link up 3.0 Gbps (SStatus 123 SControl 300) ata5.00: ATA-7: ST3120813AS, 3.AAD, max UDMA/133 ata5.00: 234441648 sectors, multi 0: LBA48 NCQ (depth 0/32) ata5.00: configured for UDMA/133
ata5: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xf t4
ata5: hotplug_status 0x10
ata5: hard resetting link

Quoted 3 lines

Eeeek, this means that ->hardreset is already broken on sata_promise which gotta be fixed as it will lead to hardreset loops whenever softreset fails.

Yes. I even have a recent bug report where the symptom was stray hotplug interrupts. At the time nothing would explain why they occurred, but now it seems that it probably was hardreset.

Quoted 20 lines
Quoted 8 lines

What happens is that a hard reset triggers cable sensing and reporting, so we get stray hotplug events which confuses things.

One solution is to mask/unmask a port's hotplug events around calls to sata_std_hardreset(). (This also matches what Promise's reference driver does, except their hard reset fiddles with Promise specific registers.) The patch below is a draft which implements that solution.

That can be done in either ->freeze/->thaw or ->postreset depending on symmetry of things. If ->freeze plugs hotplug interrupts too, it's probably best to clear hotplug events in ->thaw before unblocking hotplug events.

Quoted 5 lines

A problem is that Promise SATA chips implement per-port hotplug control using port-specific bits in a single global register. So I have to map the link to the corresponding ata engine number:
this mapping doesn't seem to be present anywhere, so in this draft patch I'm resorting to searching the host's ports[] array.

Quoted 8 lines

Hmmm....

Quoted 3 lines

Also, since the ports share a global register it's important that at most one port goes through a hard reset sequence at a time. Can I assume that libata EH guarantees mutual exclusion?

There currently is no cross-port synchronization but you can always grab host->lock for that.

Ok.

Quoted 24 lines
Quoted 2 lines

With this patch in place the hard reset conversion does seem to work Ok on a SATA300 TX4 card.

[--snip--]

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 706

Quoted 1 line
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +1 -0
+	for(i = 0; i < 4/*XXX: how to detect # ports?*/ && host->ports[i] != ap; ++i)

host->n_ports?

Quoted 4 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +4 -0
+		;
+	if (i >= 4) {
+		printk(KERN_ERR "%s: unable to map ap to ata_no\n", __FUNCTION__);
+		return sata_std_hardreset(link, class, deadline);

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 720

Quoted 10 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +10 -0
+	}
+	ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+
+	hotplug_status = readl(mmio_base + hotplug_offset);
+
+	/* clear hotplug flags, mask hotplug ints */
+	hotplug_status |= (0x11 << ata_no);
+	hotplug_status |= (0x11 << ata_no) << 16;
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

I think this belongs to ->freeze().

Quoted 8 lines

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 727

Quoted 6 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +6 -0
+	ret = sata_std_hardreset(link, class, deadline);
+
+	/* clear hotplug flags, unmask hotplug ints */
+	hotplug_status &= ~((0x11 << ata_no) << 16);
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

And this to ->thaw().

Thanks, I'll try these suggestions. Expect a new patch in a couple of days.

/Mikael

author
#10 lore raw

Re: Subject should be [PATCHSET libata-dev#upstream-fixes] libata: prefer hardreset, take #3

Quoted 33 lines · Mikael Pettersson
Quoted 24 lines
Quoted 2 lines

With this patch in place the hard reset conversion does seem to work Ok on a SATA300 TX4 card.

[--snip--]

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 706

Quoted 1 line
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +1 -0
+	for(i = 0; i < 4/*XXX: how to detect # ports?*/ && host->ports[i] != ap; ++i)

host->n_ports?

Quoted 4 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +4 -0
+		;
+	if (i >= 4) {
+		printk(KERN_ERR "%s: unable to map ap to ata_no\n", __FUNCTION__);
+		return sata_std_hardreset(link, class, deadline);

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 720

Quoted 10 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +10 -0
+	}
+	ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+
+	hotplug_status = readl(mmio_base + hotplug_offset);
+
+	/* clear hotplug flags, mask hotplug ints */
+	hotplug_status |= (0x11 << ata_no);
+	hotplug_status |= (0x11 << ata_no) << 16;
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

I think this belongs to ->freeze().

Quoted 8 lines

drivers/ata/sata_promise.c static void pdc_pata_error_handler(struc · line 727

Quoted 6 lines
drivers/ata/sata_promise.c renamed from drivers/ata/sata_promise.c.~1~ +6 -0
+	ret = sata_std_hardreset(link, class, deadline);
+
+	/* clear hotplug flags, unmask hotplug ints */
+	hotplug_status &= ~((0x11 << ata_no) << 16);
+	writel(hotplug_status, mmio_base + hotplug_offset);
+	readl(mmio_base + hotplug_offset); /* flush */

And this to ->thaw().

Quoted 1 line

Thanks, I'll try these suggestions. Expect a new patch in a couple of days.

I'll update the patchset such that promise won't use hardreset by default so that cleanup-sht-ops patchset can go in. I'll merge your change when you're ready (shouldn't require too much massaging anyway).

Thanks.

Signature · 1 line
tejun