Linux kernel -stable discussions
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] ata: sata_inic162x: remove dangerous broken driver" failed to apply to 6.12-stable tree
@ 2026-11-07 10:17 Sasha Levin
  2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
  0 siblings, 1 reply; 6+ messages in thread
From: Sasha Levin @ 2026-11-07 10:17 UTC (permalink / raw)
  To: enelsonmoore, dlemoal, cassel; +Cc: stable

The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 96fdeb7e3fd8d937f8351ed90824c9d904e590a1
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107051701-failed-6.12-96fdeb7e3fd8@kernel.org' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'

Thanks,
Sasha

------------------ original commit in Linus's tree ------------------

From 96fdeb7e3fd8d937f8351ed90824c9d904e590a1 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 14 Sep 2026 18:47:09 -0700
Subject: [PATCH] ata: sata_inic162x: remove dangerous broken driver

The sata_inic162x driver was labeled as "very experimental" in
commit bb9696192826 ("libata: make it clear that sata_inic162x is
experimental") due to data corruption issues, but not marked as broken.
Since then, no changes have been made to it that could fix these
issues. Since the driver was not marked as broken, and the message
about potential data corruption is only visible in the code and dmesg,
it is possible that someone could enable the driver without realizing
its potential for data corruption. Remove the driver to protect users'
data.

Fixes: 1fd7a697a37b ("sata_inic162x: finally, driver for initio 162x SATA controllers, take #2")
Cc: stable@vger.kernel.org
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20260915014714.41274-1-enelsonmoore@gmail.com
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/Kconfig         |   7 -
 drivers/ata/Makefile        |   1 -
 drivers/ata/sata_inic162x.c | 903 ------------------------------------
 3 files changed, 911 deletions(-)
 delete mode 100644 drivers/ata/sata_inic162x.c

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 86af89a9bfce6..9704ed688775b 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -328,13 +328,6 @@ config SATA_AHCI_SEATTLE
 
 	 If unsure, say N
 
-config SATA_INIC162X
-	tristate "Initio 162x SATA support (Very Experimental)"
-	depends on PCI
-	select SATA_HOST
-	help
-	  This option enables support for Initio 162x Serial ATA.
-
 config SATA_ACARD_AHCI
 	tristate "ACard AHCI variant (ATP 8620)"
 	depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 647e3d4b6f758..20b400aea0c45 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_SATA_AHCI_SEATTLE)	+= ahci_seattle.o libahci.o libahci_platform.o
 obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
 obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
 obj-$(CONFIG_SATA_GEMINI)	+= sata_gemini.o
-obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
 obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
deleted file mode 100644
index 065408975f5b5..0000000000000
--- a/drivers/ata/sata_inic162x.c
+++ /dev/null
@@ -1,903 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * sata_inic162x.c - Driver for Initio 162x SATA controllers
- *
- * Copyright 2006  SUSE Linux Products GmbH
- * Copyright 2006  Tejun Heo <teheo@novell.com>
- *
- * **** WARNING ****
- *
- * This driver never worked properly and unfortunately data corruption is
- * relatively common.  There isn't anyone working on the driver and there's
- * no support from the vendor.  Do not use this driver in any production
- * environment.
- *
- * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491
- * https://bugzilla.kernel.org/show_bug.cgi?id=60565
- *
- * *****************
- *
- * This controller is eccentric and easily locks up if something isn't
- * right.  Documentation is available at initio's website but it only
- * documents registers (not programming model).
- *
- * This driver has interesting history.  The first version was written
- * from the documentation and a 2.4 IDE driver posted on a Taiwan
- * company, which didn't use any IDMA features and couldn't handle
- * LBA48.  The resulting driver couldn't handle LBA48 devices either
- * making it pretty useless.
- *
- * After a while, initio picked the driver up, renamed it to
- * sata_initio162x, updated it to use IDMA for ATA DMA commands and
- * posted it on their website.  It only used ATA_PROT_DMA for IDMA and
- * attaching both devices and issuing IDMA and !IDMA commands
- * simultaneously broke it due to PIRQ masking interaction but it did
- * show how to use the IDMA (ADMA + some initio specific twists)
- * engine.
- *
- * Then, I picked up their changes again and here's the usable driver
- * which uses IDMA for everything.  Everything works now including
- * LBA48, CD/DVD burning, suspend/resume and hotplug.  There are some
- * issues tho.  Result Tf is not resported properly, NCQ isn't
- * supported yet and CD/DVD writing works with DMA assisted PIO
- * protocol (which, for native SATA devices, shouldn't cause any
- * noticeable difference).
- *
- * Anyways, so, here's finally a working driver for inic162x.  Enjoy!
- *
- * initio: If you guys wanna improve the driver regarding result TF
- * access and other stuff, please feel free to contact me.  I'll be
- * happy to assist.
- */
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/blkdev.h>
-#include <scsi/scsi_device.h>
-
-#define DRV_NAME	"sata_inic162x"
-#define DRV_VERSION	"0.4"
-
-enum {
-	MMIO_BAR_PCI		= 5,
-	MMIO_BAR_CARDBUS	= 1,
-
-	NR_PORTS		= 2,
-
-	IDMA_CPB_TBL_SIZE	= 4 * 32,
-
-	INIC_DMA_BOUNDARY	= 0xffffff,
-
-	HOST_ACTRL		= 0x08,
-	HOST_CTL		= 0x7c,
-	HOST_STAT		= 0x7e,
-	HOST_IRQ_STAT		= 0xbc,
-	HOST_IRQ_MASK		= 0xbe,
-
-	PORT_SIZE		= 0x40,
-
-	/* registers for ATA TF operation */
-	PORT_TF_DATA		= 0x00,
-	PORT_TF_FEATURE		= 0x01,
-	PORT_TF_NSECT		= 0x02,
-	PORT_TF_LBAL		= 0x03,
-	PORT_TF_LBAM		= 0x04,
-	PORT_TF_LBAH		= 0x05,
-	PORT_TF_DEVICE		= 0x06,
-	PORT_TF_COMMAND		= 0x07,
-	PORT_TF_ALT_STAT	= 0x08,
-	PORT_IRQ_STAT		= 0x09,
-	PORT_IRQ_MASK		= 0x0a,
-	PORT_PRD_CTL		= 0x0b,
-	PORT_PRD_ADDR		= 0x0c,
-	PORT_PRD_XFERLEN	= 0x10,
-	PORT_CPB_CPBLAR		= 0x18,
-	PORT_CPB_PTQFIFO	= 0x1c,
-
-	/* IDMA register */
-	PORT_IDMA_CTL		= 0x14,
-	PORT_IDMA_STAT		= 0x16,
-
-	PORT_RPQ_FIFO		= 0x1e,
-	PORT_RPQ_CNT		= 0x1f,
-
-	PORT_SCR		= 0x20,
-
-	/* HOST_CTL bits */
-	HCTL_LEDEN		= (1 << 3),  /* enable LED operation */
-	HCTL_IRQOFF		= (1 << 8),  /* global IRQ off */
-	HCTL_FTHD0		= (1 << 10), /* fifo threshold 0 */
-	HCTL_FTHD1		= (1 << 11), /* fifo threshold 1*/
-	HCTL_PWRDWN		= (1 << 12), /* power down PHYs */
-	HCTL_SOFTRST		= (1 << 13), /* global reset (no phy reset) */
-	HCTL_RPGSEL		= (1 << 15), /* register page select */
-
-	HCTL_KNOWN_BITS		= HCTL_IRQOFF | HCTL_PWRDWN | HCTL_SOFTRST |
-				  HCTL_RPGSEL,
-
-	/* HOST_IRQ_(STAT|MASK) bits */
-	HIRQ_PORT0		= (1 << 0),
-	HIRQ_PORT1		= (1 << 1),
-	HIRQ_SOFT		= (1 << 14),
-	HIRQ_GLOBAL		= (1 << 15), /* STAT only */
-
-	/* PORT_IRQ_(STAT|MASK) bits */
-	PIRQ_OFFLINE		= (1 << 0),  /* device unplugged */
-	PIRQ_ONLINE		= (1 << 1),  /* device plugged */
-	PIRQ_COMPLETE		= (1 << 2),  /* completion interrupt */
-	PIRQ_FATAL		= (1 << 3),  /* fatal error */
-	PIRQ_ATA		= (1 << 4),  /* ATA interrupt */
-	PIRQ_REPLY		= (1 << 5),  /* reply FIFO not empty */
-	PIRQ_PENDING		= (1 << 7),  /* port IRQ pending (STAT only) */
-
-	PIRQ_ERR		= PIRQ_OFFLINE | PIRQ_ONLINE | PIRQ_FATAL,
-	PIRQ_MASK_DEFAULT	= PIRQ_REPLY | PIRQ_ATA,
-	PIRQ_MASK_FREEZE	= 0xff,
-
-	/* PORT_PRD_CTL bits */
-	PRD_CTL_START		= (1 << 0),
-	PRD_CTL_WR		= (1 << 3),
-	PRD_CTL_DMAEN		= (1 << 7),  /* DMA enable */
-
-	/* PORT_IDMA_CTL bits */
-	IDMA_CTL_RST_ATA	= (1 << 2),  /* hardreset ATA bus */
-	IDMA_CTL_RST_IDMA	= (1 << 5),  /* reset IDMA machinery */
-	IDMA_CTL_GO		= (1 << 7),  /* IDMA mode go */
-	IDMA_CTL_ATA_NIEN	= (1 << 8),  /* ATA IRQ disable */
-
-	/* PORT_IDMA_STAT bits */
-	IDMA_STAT_PERR		= (1 << 0),  /* PCI ERROR MODE */
-	IDMA_STAT_CPBERR	= (1 << 1),  /* ADMA CPB error */
-	IDMA_STAT_LGCY		= (1 << 3),  /* ADMA legacy */
-	IDMA_STAT_UIRQ		= (1 << 4),  /* ADMA unsolicited irq */
-	IDMA_STAT_STPD		= (1 << 5),  /* ADMA stopped */
-	IDMA_STAT_PSD		= (1 << 6),  /* ADMA pause */
-	IDMA_STAT_DONE		= (1 << 7),  /* ADMA done */
-
-	IDMA_STAT_ERR		= IDMA_STAT_PERR | IDMA_STAT_CPBERR,
-
-	/* CPB Control Flags*/
-	CPB_CTL_VALID		= (1 << 0),  /* CPB valid */
-	CPB_CTL_QUEUED		= (1 << 1),  /* queued command */
-	CPB_CTL_DATA		= (1 << 2),  /* data, rsvd in datasheet */
-	CPB_CTL_IEN		= (1 << 3),  /* PCI interrupt enable */
-	CPB_CTL_DEVDIR		= (1 << 4),  /* device direction control */
-
-	/* CPB Response Flags */
-	CPB_RESP_DONE		= (1 << 0),  /* ATA command complete */
-	CPB_RESP_REL		= (1 << 1),  /* ATA release */
-	CPB_RESP_IGNORED	= (1 << 2),  /* CPB ignored */
-	CPB_RESP_ATA_ERR	= (1 << 3),  /* ATA command error */
-	CPB_RESP_SPURIOUS	= (1 << 4),  /* ATA spurious interrupt error */
-	CPB_RESP_UNDERFLOW	= (1 << 5),  /* APRD deficiency length error */
-	CPB_RESP_OVERFLOW	= (1 << 6),  /* APRD exccess length error */
-	CPB_RESP_CPB_ERR	= (1 << 7),  /* CPB error flag */
-
-	/* PRD Control Flags */
-	PRD_DRAIN		= (1 << 1),  /* ignore data excess */
-	PRD_CDB			= (1 << 2),  /* atapi packet command pointer */
-	PRD_DIRECT_INTR		= (1 << 3),  /* direct interrupt */
-	PRD_DMA			= (1 << 4),  /* data transfer method */
-	PRD_WRITE		= (1 << 5),  /* data dir, rsvd in datasheet */
-	PRD_IOM			= (1 << 6),  /* io/memory transfer */
-	PRD_END			= (1 << 7),  /* APRD chain end */
-};
-
-/* Comman Parameter Block */
-struct inic_cpb {
-	u8		resp_flags;	/* Response Flags */
-	u8		error;		/* ATA Error */
-	u8		status;		/* ATA Status */
-	u8		ctl_flags;	/* Control Flags */
-	__le32		len;		/* Total Transfer Length */
-	__le32		prd;		/* First PRD pointer */
-	u8		rsvd[4];
-	/* 16 bytes */
-	u8		feature;	/* ATA Feature */
-	u8		hob_feature;	/* ATA Ex. Feature */
-	u8		device;		/* ATA Device/Head */
-	u8		mirctl;		/* Mirror Control */
-	u8		nsect;		/* ATA Sector Count */
-	u8		hob_nsect;	/* ATA Ex. Sector Count */
-	u8		lbal;		/* ATA Sector Number */
-	u8		hob_lbal;	/* ATA Ex. Sector Number */
-	u8		lbam;		/* ATA Cylinder Low */
-	u8		hob_lbam;	/* ATA Ex. Cylinder Low */
-	u8		lbah;		/* ATA Cylinder High */
-	u8		hob_lbah;	/* ATA Ex. Cylinder High */
-	u8		command;	/* ATA Command */
-	u8		ctl;		/* ATA Control */
-	u8		slave_error;	/* Slave ATA Error */
-	u8		slave_status;	/* Slave ATA Status */
-	/* 32 bytes */
-} __packed;
-
-/* Physical Region Descriptor */
-struct inic_prd {
-	__le32		mad;		/* Physical Memory Address */
-	__le16		len;		/* Transfer Length */
-	u8		rsvd;
-	u8		flags;		/* Control Flags */
-} __packed;
-
-struct inic_pkt {
-	struct inic_cpb	cpb;
-	struct inic_prd	prd[LIBATA_MAX_PRD + 1];	/* + 1 for cdb */
-	u8		cdb[ATAPI_CDB_LEN];
-} __packed;
-
-struct inic_host_priv {
-	void __iomem	*mmio_base;
-	u16		cached_hctl;
-};
-
-struct inic_port_priv {
-	struct inic_pkt	*pkt;
-	dma_addr_t	pkt_dma;
-	u32		*cpb_tbl;
-	dma_addr_t	cpb_tbl_dma;
-};
-
-static const struct scsi_host_template inic_sht = {
-	ATA_BASE_SHT(DRV_NAME),
-	.sg_tablesize		= LIBATA_MAX_PRD, /* maybe it can be larger? */
-
-	/*
-	 * This controller is braindamaged.  dma_boundary is 0xffff like others
-	 * but it will lock up the whole machine HARD if 65536 byte PRD entry
-	 * is fed.  Reduce maximum segment size.
-	 */
-	.dma_boundary		= INIC_DMA_BOUNDARY,
-	.max_segment_size	= 65536 - 512,
-};
-
-static const int scr_map[] = {
-	[SCR_STATUS]	= 0,
-	[SCR_ERROR]	= 1,
-	[SCR_CONTROL]	= 2,
-};
-
-static void __iomem *inic_port_base(struct ata_port *ap)
-{
-	struct inic_host_priv *hpriv = ap->host->private_data;
-
-	return hpriv->mmio_base + ap->port_no * PORT_SIZE;
-}
-
-static void inic_reset_port(void __iomem *port_base)
-{
-	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
-
-	/* stop IDMA engine */
-	readw(idma_ctl); /* flush */
-	msleep(1);
-
-	/* mask IRQ and assert reset */
-	writew(IDMA_CTL_RST_IDMA, idma_ctl);
-	readw(idma_ctl); /* flush */
-	msleep(1);
-
-	/* release reset */
-	writew(0, idma_ctl);
-
-	/* clear irq */
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-}
-
-static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
-{
-	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-
-	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
-		return -EINVAL;
-
-	*val = readl(scr_addr + scr_map[sc_reg] * 4);
-
-	/* this controller has stuck DIAG.N, ignore it */
-	if (sc_reg == SCR_ERROR)
-		*val &= ~SERR_PHYRDY_CHG;
-	return 0;
-}
-
-static int inic_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
-{
-	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-
-	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
-		return -EINVAL;
-
-	writel(val, scr_addr + scr_map[sc_reg] * 4);
-	return 0;
-}
-
-static void inic_stop_idma(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	readb(port_base + PORT_RPQ_FIFO);
-	readb(port_base + PORT_RPQ_CNT);
-	writew(0, port_base + PORT_IDMA_CTL);
-}
-
-static void inic_host_err_intr(struct ata_port *ap, u8 irq_stat, u16 idma_stat)
-{
-	struct ata_eh_info *ehi = &ap->link.eh_info;
-	struct inic_port_priv *pp = ap->private_data;
-	struct inic_cpb *cpb = &pp->pkt->cpb;
-	bool freeze = false;
-
-	ata_ehi_clear_desc(ehi);
-	ata_ehi_push_desc(ehi, "irq_stat=0x%x idma_stat=0x%x",
-			  irq_stat, idma_stat);
-
-	inic_stop_idma(ap);
-
-	if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
-		ata_ehi_push_desc(ehi, "hotplug");
-		ata_ehi_hotplugged(ehi);
-		freeze = true;
-	}
-
-	if (idma_stat & IDMA_STAT_PERR) {
-		ata_ehi_push_desc(ehi, "PCI error");
-		freeze = true;
-	}
-
-	if (idma_stat & IDMA_STAT_CPBERR) {
-		ata_ehi_push_desc(ehi, "CPB error");
-
-		if (cpb->resp_flags & CPB_RESP_IGNORED) {
-			__ata_ehi_push_desc(ehi, " ignored");
-			ehi->err_mask |= AC_ERR_INVALID;
-			freeze = true;
-		}
-
-		if (cpb->resp_flags & CPB_RESP_ATA_ERR)
-			ehi->err_mask |= AC_ERR_DEV;
-
-		if (cpb->resp_flags & CPB_RESP_SPURIOUS) {
-			__ata_ehi_push_desc(ehi, " spurious-intr");
-			ehi->err_mask |= AC_ERR_HSM;
-			freeze = true;
-		}
-
-		if (cpb->resp_flags &
-		    (CPB_RESP_UNDERFLOW | CPB_RESP_OVERFLOW)) {
-			__ata_ehi_push_desc(ehi, " data-over/underflow");
-			ehi->err_mask |= AC_ERR_HSM;
-			freeze = true;
-		}
-	}
-
-	if (freeze)
-		ata_port_freeze(ap);
-	else
-		ata_port_abort(ap);
-}
-
-static void inic_host_intr(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
-	u8 irq_stat;
-	u16 idma_stat;
-
-	/* read and clear IRQ status */
-	irq_stat = readb(port_base + PORT_IRQ_STAT);
-	writeb(irq_stat, port_base + PORT_IRQ_STAT);
-	idma_stat = readw(port_base + PORT_IDMA_STAT);
-
-	if (unlikely((irq_stat & PIRQ_ERR) || (idma_stat & IDMA_STAT_ERR)))
-		inic_host_err_intr(ap, irq_stat, idma_stat);
-
-	if (unlikely(!qc))
-		goto spurious;
-
-	if (likely(idma_stat & IDMA_STAT_DONE)) {
-		inic_stop_idma(ap);
-
-		/* Depending on circumstances, device error
-		 * isn't reported by IDMA, check it explicitly.
-		 */
-		if (unlikely(readb(port_base + PORT_TF_COMMAND) &
-			     (ATA_DF | ATA_ERR)))
-			qc->err_mask |= AC_ERR_DEV;
-
-		ata_qc_complete(qc);
-		return;
-	}
-
- spurious:
-	ata_port_warn(ap, "unhandled interrupt: cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
-		      qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
-}
-
-static irqreturn_t inic_interrupt(int irq, void *dev_instance)
-{
-	struct ata_host *host = dev_instance;
-	struct inic_host_priv *hpriv = host->private_data;
-	u16 host_irq_stat;
-	int i, handled = 0;
-
-	host_irq_stat = readw(hpriv->mmio_base + HOST_IRQ_STAT);
-
-	if (unlikely(!(host_irq_stat & HIRQ_GLOBAL)))
-		goto out;
-
-	spin_lock(&host->lock);
-
-	for (i = 0; i < NR_PORTS; i++)
-		if (host_irq_stat & (HIRQ_PORT0 << i)) {
-			inic_host_intr(host->ports[i]);
-			handled++;
-		}
-
-	spin_unlock(&host->lock);
-
- out:
-	return IRQ_RETVAL(handled);
-}
-
-static int inic_check_atapi_dma(struct ata_queued_cmd *qc)
-{
-	/* For some reason ATAPI_PROT_DMA doesn't work for some
-	 * commands including writes and other misc ops.  Use PIO
-	 * protocol instead, which BTW is driven by the DMA engine
-	 * anyway, so it shouldn't make much difference for native
-	 * SATA devices.
-	 */
-	if (atapi_cmd_type(qc->cdb[0]) == READ)
-		return 0;
-	return 1;
-}
-
-static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc)
-{
-	struct scatterlist *sg;
-	unsigned int si;
-	u8 flags = 0;
-
-	if (qc->tf.flags & ATA_TFLAG_WRITE)
-		flags |= PRD_WRITE;
-
-	if (ata_is_dma(qc->tf.protocol))
-		flags |= PRD_DMA;
-
-	for_each_sg(qc->sg, sg, qc->n_elem, si) {
-		prd->mad = cpu_to_le32(sg_dma_address(sg));
-		prd->len = cpu_to_le16(sg_dma_len(sg));
-		prd->flags = flags;
-		prd++;
-	}
-
-	WARN_ON(!si);
-	prd[-1].flags |= PRD_END;
-}
-
-static enum ata_completion_errors inic_qc_prep(struct ata_queued_cmd *qc)
-{
-	struct inic_port_priv *pp = qc->ap->private_data;
-	struct inic_pkt *pkt = pp->pkt;
-	struct inic_cpb *cpb = &pkt->cpb;
-	struct inic_prd *prd = pkt->prd;
-	bool is_atapi = ata_is_atapi(qc->tf.protocol);
-	bool is_data = ata_is_data(qc->tf.protocol);
-	unsigned int cdb_len = 0;
-
-	if (is_atapi)
-		cdb_len = qc->dev->cdb_len;
-
-	/* prepare packet, based on initio driver */
-	memset(pkt, 0, sizeof(struct inic_pkt));
-
-	cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN;
-	if (is_atapi || is_data)
-		cpb->ctl_flags |= CPB_CTL_DATA;
-
-	cpb->len = cpu_to_le32(qc->nbytes + cdb_len);
-	cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd));
-
-	cpb->device = qc->tf.device;
-	cpb->feature = qc->tf.feature;
-	cpb->nsect = qc->tf.nsect;
-	cpb->lbal = qc->tf.lbal;
-	cpb->lbam = qc->tf.lbam;
-	cpb->lbah = qc->tf.lbah;
-
-	if (qc->tf.flags & ATA_TFLAG_LBA48) {
-		cpb->hob_feature = qc->tf.hob_feature;
-		cpb->hob_nsect = qc->tf.hob_nsect;
-		cpb->hob_lbal = qc->tf.hob_lbal;
-		cpb->hob_lbam = qc->tf.hob_lbam;
-		cpb->hob_lbah = qc->tf.hob_lbah;
-	}
-
-	cpb->command = qc->tf.command;
-	/* don't load ctl - dunno why.  it's like that in the initio driver */
-
-	/* setup PRD for CDB */
-	if (is_atapi) {
-		memcpy(pkt->cdb, qc->cdb, ATAPI_CDB_LEN);
-		prd->mad = cpu_to_le32(pp->pkt_dma +
-				       offsetof(struct inic_pkt, cdb));
-		prd->len = cpu_to_le16(cdb_len);
-		prd->flags = PRD_CDB | PRD_WRITE;
-		if (!is_data)
-			prd->flags |= PRD_END;
-		prd++;
-	}
-
-	/* setup sg table */
-	if (is_data)
-		inic_fill_sg(prd, qc);
-
-	pp->cpb_tbl[0] = pp->pkt_dma;
-
-	return AC_ERR_OK;
-}
-
-static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	void __iomem *port_base = inic_port_base(ap);
-
-	/* fire up the ADMA engine */
-	writew(HCTL_FTHD0 | HCTL_LEDEN, port_base + HOST_CTL);
-	writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
-	writeb(0, port_base + PORT_CPB_PTQFIFO);
-
-	return 0;
-}
-
-static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	tf->error	= readb(port_base + PORT_TF_FEATURE);
-	tf->nsect	= readb(port_base + PORT_TF_NSECT);
-	tf->lbal	= readb(port_base + PORT_TF_LBAL);
-	tf->lbam	= readb(port_base + PORT_TF_LBAM);
-	tf->lbah	= readb(port_base + PORT_TF_LBAH);
-	tf->device	= readb(port_base + PORT_TF_DEVICE);
-	tf->status	= readb(port_base + PORT_TF_COMMAND);
-}
-
-static void inic_qc_fill_rtf(struct ata_queued_cmd *qc)
-{
-	struct ata_taskfile *rtf = &qc->result_tf;
-	struct ata_taskfile tf;
-
-	/* FIXME: Except for status and error, result TF access
-	 * doesn't work.  I tried reading from BAR0/2, CPB and BAR5.
-	 * None works regardless of which command interface is used.
-	 * For now return true iff status indicates device error.
-	 * This means that we're reporting bogus sector for RW
-	 * failures.  Eeekk....
-	 */
-	inic_tf_read(qc->ap, &tf);
-
-	if (tf.status & ATA_ERR) {
-		rtf->status = tf.status;
-		rtf->error = tf.error;
-	}
-}
-
-static void inic_freeze(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	writeb(PIRQ_MASK_FREEZE, port_base + PORT_IRQ_MASK);
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-}
-
-static void inic_thaw(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-	writeb(PIRQ_MASK_DEFAULT, port_base + PORT_IRQ_MASK);
-}
-
-static int inic_check_ready(struct ata_link *link)
-{
-	void __iomem *port_base = inic_port_base(link->ap);
-
-	return ata_check_ready(readb(port_base + PORT_TF_COMMAND));
-}
-
-/*
- * SRST and SControl hardreset don't give valid signature on this
- * controller.  Only controller specific hardreset mechanism works.
- */
-static int inic_hardreset(struct ata_link *link, unsigned int *class,
-			  unsigned long deadline)
-{
-	struct ata_port *ap = link->ap;
-	void __iomem *port_base = inic_port_base(ap);
-	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
-	const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context);
-	int rc;
-
-	/* hammer it into sane state */
-	inic_reset_port(port_base);
-
-	writew(IDMA_CTL_RST_ATA, idma_ctl);
-	readw(idma_ctl);	/* flush */
-	ata_msleep(ap, 1);
-	writew(0, idma_ctl);
-
-	rc = sata_link_resume(link, timing, deadline);
-	if (rc) {
-		ata_link_warn(link,
-			      "failed to resume link after reset (errno=%d)\n",
-			      rc);
-		return rc;
-	}
-
-	*class = ATA_DEV_NONE;
-	if (ata_link_online(link)) {
-		struct ata_taskfile tf;
-
-		/* wait for link to become ready */
-		rc = ata_wait_after_reset(link, deadline, inic_check_ready);
-		/* link occupied, -ENODEV too is an error */
-		if (rc) {
-			ata_link_warn(link,
-				      "device not ready after hardreset (errno=%d)\n",
-				      rc);
-			return rc;
-		}
-
-		inic_tf_read(ap, &tf);
-		*class = ata_port_classify(ap, &tf);
-	}
-
-	return 0;
-}
-
-static void inic_error_handler(struct ata_port *ap)
-	__must_hold(&ap->host->eh_mutex)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	inic_reset_port(port_base);
-	ata_std_error_handler(ap);
-}
-
-static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-	/* make DMA engine forget about the failed command */
-	if (qc->flags & ATA_QCFLAG_EH)
-		inic_reset_port(inic_port_base(qc->ap));
-}
-
-static void init_port(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-	struct inic_port_priv *pp = ap->private_data;
-
-	/* clear packet and CPB table */
-	memset(pp->pkt, 0, sizeof(struct inic_pkt));
-	memset(pp->cpb_tbl, 0, IDMA_CPB_TBL_SIZE);
-
-	/* setup CPB lookup table addresses */
-	writel(pp->cpb_tbl_dma, port_base + PORT_CPB_CPBLAR);
-}
-
-static int inic_port_resume(struct ata_port *ap)
-{
-	init_port(ap);
-	return 0;
-}
-
-static int inic_port_start(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct inic_port_priv *pp;
-
-	/* alloc and initialize private data */
-	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
-	if (!pp)
-		return -ENOMEM;
-	ap->private_data = pp;
-
-	/* Alloc resources */
-	pp->pkt = dmam_alloc_coherent(dev, sizeof(struct inic_pkt),
-				      &pp->pkt_dma, GFP_KERNEL);
-	if (!pp->pkt)
-		return -ENOMEM;
-
-	pp->cpb_tbl = dmam_alloc_coherent(dev, IDMA_CPB_TBL_SIZE,
-					  &pp->cpb_tbl_dma, GFP_KERNEL);
-	if (!pp->cpb_tbl)
-		return -ENOMEM;
-
-	init_port(ap);
-
-	return 0;
-}
-
-static struct ata_port_operations inic_port_ops = {
-	.inherits		= &sata_port_ops,
-
-	.check_atapi_dma	= inic_check_atapi_dma,
-	.qc_prep		= inic_qc_prep,
-	.qc_issue		= inic_qc_issue,
-	.qc_fill_rtf		= inic_qc_fill_rtf,
-
-	.freeze			= inic_freeze,
-	.thaw			= inic_thaw,
-	.reset.hardreset	= inic_hardreset,
-	.error_handler		= inic_error_handler,
-	.post_internal_cmd	= inic_post_internal_cmd,
-
-	.scr_read		= inic_scr_read,
-	.scr_write		= inic_scr_write,
-
-	.port_resume		= inic_port_resume,
-	.port_start		= inic_port_start,
-};
-
-static const struct ata_port_info inic_port_info = {
-	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
-	.pio_mask		= ATA_PIO4,
-	.mwdma_mask		= ATA_MWDMA2,
-	.udma_mask		= ATA_UDMA6,
-	.port_ops		= &inic_port_ops
-};
-
-static int init_controller(void __iomem *mmio_base, u16 hctl)
-{
-	int i;
-	u16 val;
-
-	hctl &= ~HCTL_KNOWN_BITS;
-
-	/* Soft reset whole controller.  Spec says reset duration is 3
-	 * PCI clocks, be generous and give it 10ms.
-	 */
-	writew(hctl | HCTL_SOFTRST, mmio_base + HOST_CTL);
-	readw(mmio_base + HOST_CTL); /* flush */
-
-	for (i = 0; i < 10; i++) {
-		msleep(1);
-		val = readw(mmio_base + HOST_CTL);
-		if (!(val & HCTL_SOFTRST))
-			break;
-	}
-
-	if (val & HCTL_SOFTRST)
-		return -EIO;
-
-	/* mask all interrupts and reset ports */
-	for (i = 0; i < NR_PORTS; i++) {
-		void __iomem *port_base = mmio_base + i * PORT_SIZE;
-
-		writeb(0xff, port_base + PORT_IRQ_MASK);
-		inic_reset_port(port_base);
-	}
-
-	/* port IRQ is masked now, unmask global IRQ */
-	writew(hctl & ~HCTL_IRQOFF, mmio_base + HOST_CTL);
-	val = readw(mmio_base + HOST_IRQ_MASK);
-	val &= ~(HIRQ_PORT0 | HIRQ_PORT1);
-	writew(val, mmio_base + HOST_IRQ_MASK);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int inic_pci_device_resume(struct pci_dev *pdev)
-{
-	struct ata_host *host = pci_get_drvdata(pdev);
-	struct inic_host_priv *hpriv = host->private_data;
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
-		if (rc)
-			return rc;
-	}
-
-	ata_host_resume(host);
-
-	return 0;
-}
-#endif
-
-static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	const struct ata_port_info *ppi[] = { &inic_port_info, NULL };
-	struct ata_host *host;
-	struct inic_host_priv *hpriv;
-	void __iomem * const *iomap;
-	int mmio_bar;
-	int i, rc;
-
-	ata_print_version_once(&pdev->dev, DRV_VERSION);
-
-	dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n");
-
-	/* alloc host */
-	host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
-	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
-	if (!host || !hpriv)
-		return -ENOMEM;
-
-	host->private_data = hpriv;
-
-	/* Acquire resources and fill host.  Note that PCI and cardbus
-	 * use different BARs.
-	 */
-	rc = pcim_enable_device(pdev);
-	if (rc)
-		return rc;
-
-	if (pci_resource_flags(pdev, MMIO_BAR_PCI) & IORESOURCE_MEM)
-		mmio_bar = MMIO_BAR_PCI;
-	else
-		mmio_bar = MMIO_BAR_CARDBUS;
-
-	rc = pcim_iomap_regions(pdev, 1 << mmio_bar, DRV_NAME);
-	if (rc)
-		return rc;
-	host->iomap = iomap = pcim_iomap_table(pdev);
-	hpriv->mmio_base = iomap[mmio_bar];
-	hpriv->cached_hctl = readw(hpriv->mmio_base + HOST_CTL);
-
-	for (i = 0; i < NR_PORTS; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		ata_port_pbar_desc(ap, mmio_bar, -1, "mmio");
-		ata_port_pbar_desc(ap, mmio_bar, i * PORT_SIZE, "port");
-	}
-
-	/* Set dma_mask.  This devices doesn't support 64bit addressing. */
-	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
-	if (rc) {
-		dev_err(&pdev->dev, "32-bit DMA enable failed\n");
-		return rc;
-	}
-
-	rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to initialize controller\n");
-		return rc;
-	}
-
-	pci_set_master(pdev);
-	return ata_host_activate(host, pdev->irq, inic_interrupt, IRQF_SHARED,
-				 &inic_sht);
-}
-
-static const struct pci_device_id inic_pci_tbl[] = {
-	{ PCI_VDEVICE(INIT, 0x1622), },
-	{ },
-};
-
-static struct pci_driver inic_pci_driver = {
-	.name 		= DRV_NAME,
-	.id_table	= inic_pci_tbl,
-#ifdef CONFIG_PM_SLEEP
-	.suspend	= ata_pci_device_suspend,
-	.resume		= inic_pci_device_resume,
-#endif
-	.probe 		= inic_init_one,
-	.remove		= ata_pci_remove_one,
-};
-
-module_pci_driver(inic_pci_driver);
-
-MODULE_AUTHOR("Tejun Heo");
-MODULE_DESCRIPTION("low-level driver for Initio 162x SATA");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(pci, inic_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-- 
2.53.0





^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static
  2026-11-07 10:17 FAILED: patch "[PATCH] ata: sata_inic162x: remove dangerous broken driver" failed to apply to 6.12-stable tree Sasha Levin
@ 2026-11-10 15:12 ` Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 2/5] ata: libata-eh: Remove ata_do_eh() Sasha Levin
                     ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Sasha Levin @ 2026-11-10 15:12 UTC (permalink / raw)
  To: stable; +Cc: Damien Le Moal, Niklas Cassel, Sasha Levin

From: Damien Le Moal <dlemoal@kernel.org>

[ Upstream commit 6ba4d05c1425fe220d95395b4485443ce895bb95 ]

The function ata_set_mode() is defined and used only in libata-eh.c.
Make this function static and rename it ata_eh_set_mode() to make it
clear where its definition is.

No functional changes.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Link: https://lore.kernel.org/r/20250703103622.291272-4-dlemoal@kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Stable-dep-of: 96fdeb7e3fd8 ("ata: sata_inic162x: remove dangerous broken driver")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/ata/libata-eh.c | 9 +++++----
 drivers/ata/libata.h    | 1 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 32ec1cfd648e3..1cf737f17d0a3 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3248,12 +3248,12 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
 }
 
 /**
- *	ata_set_mode - Program timings and issue SET FEATURES - XFER
+ *	ata_eh_set_mode - Program timings and issue SET FEATURES - XFER
  *	@link: link on which timings will be programmed
  *	@r_failed_dev: out parameter for failed device
  *
  *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
- *	ata_set_mode() fails, pointer to the failing device is
+ *	ata_eh_set_mode() fails, pointer to the failing device is
  *	returned in @r_failed_dev.
  *
  *	LOCKING:
@@ -3262,7 +3262,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
  *	RETURNS:
  *	0 on success, negative errno otherwise
  */
-int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+static int ata_eh_set_mode(struct ata_link *link,
+			   struct ata_device **r_failed_dev)
 {
 	struct ata_port *ap = link->ap;
 	struct ata_device *dev;
@@ -3900,7 +3901,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 
 		/* configure transfer mode if necessary */
 		if (ehc->i.flags & ATA_EHI_SETMODE) {
-			rc = ata_set_mode(link, &dev);
+			rc = ata_eh_set_mode(link, &dev);
 			if (rc)
 				goto rest_fail;
 			ehc->i.flags &= ~ATA_EHI_SETMODE;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 4b3e246227e68..898d5b368d82f 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -199,7 +199,6 @@ extern void ata_eh_report(struct ata_port *ap);
 extern int ata_eh_reset(struct ata_link *link, int classify,
 			ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
 			ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
-extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
 extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
 			  ata_postreset_fn_t postreset,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6.12.y 2/5] ata: libata-eh: Remove ata_do_eh()
  2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
@ 2026-11-10 15:12   ` Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 3/5] ata: libata-eh: Simplify reset operation management Sasha Levin
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-11-10 15:12 UTC (permalink / raw)
  To: stable
  Cc: Damien Le Moal, Niklas Cassel, Martin K. Petersen,
	Hannes Reinecke, Sasha Levin

From: Damien Le Moal <dlemoal@kernel.org>

[ Upstream commit df6f9a918ea856fc288b9001b0414c5be136d7d0 ]

The only reason for ata_do_eh() to exist is that the two caller sites,
ata_std_error_handler() and ata_sff_error_handler() may pass it a
NULL hardreset operation so that the built-in (generic) hardreset
operation for a driver is ignored if the adapter SCR access is not
available.

However, ata_std_error_handler() and ata_sff_error_handler()
modifications of the hardreset port operation can easily be combined as
they are mutually exclusive. That is, a driver using sata_std_hardreset()
as its hardreset operation cannot use sata_sff_hardreset() and
vice-versa.

With this observation, ata_do_eh() can be removed and its code moved to
ata_std_error_handler(). The condition used to ignore the built-in
hardreset port operation is modified to be the one that was used in
ata_sff_error_handler(). This requires defining a stub for the function
sata_sff_hardreset() to avoid compilation errors when CONFIG_ATA_SFF is
not enabled. Furthermore, instead of modifying the local hardreset
operation definition, set the ATA_LFLAG_NO_HRST link flag to prevent
the use of built-in hardreset methods for ports without a valid scr_read
function. This flag is checked in ata_eh_reset() and if set, the
hardreset method is ignored.

This change simplifies ata_sff_error_handler() as this function now only
needs to call ata_std_error_handler().

No functional changes.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://lore.kernel.org/r/20250716020315.235457-2-dlemoal@kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Stable-dep-of: 96fdeb7e3fd8 ("ata: sata_inic162x: remove dangerous broken driver")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/ata/libata-eh.c  | 48 ++++++++++++----------------------------
 drivers/ata/libata-sff.c | 10 +--------
 include/linux/libata.h   |  9 +++++---
 3 files changed, 21 insertions(+), 46 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 1cf737f17d0a3..a7525c8e97bf3 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -4040,59 +4040,39 @@ void ata_eh_finish(struct ata_port *ap)
 }
 
 /**
- *	ata_do_eh - do standard error handling
+ *	ata_std_error_handler - standard error handler
  *	@ap: host port to handle error for
  *
- *	@prereset: prereset method (can be NULL)
- *	@softreset: softreset method (can be NULL)
- *	@hardreset: hardreset method (can be NULL)
- *	@postreset: postreset method (can be NULL)
- *
  *	Perform standard error handling sequence.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep).
  */
-void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-	       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-	       ata_postreset_fn_t postreset)
+void ata_std_error_handler(struct ata_port *ap)
 {
-	struct ata_device *dev;
+	struct ata_port_operations *ops = ap->ops;
+	struct ata_link *link = &ap->link;
 	int rc;
 
+	/* Ignore built-in hardresets if SCR access is not available */
+	if ((ops->hardreset == sata_std_hardreset ||
+	     ops->hardreset == sata_sff_hardreset) && !sata_scr_valid(link))
+		link->flags |= ATA_LFLAG_NO_HRST;
+
 	ata_eh_autopsy(ap);
 	ata_eh_report(ap);
 
-	rc = ata_eh_recover(ap, prereset, softreset, hardreset, postreset,
-			    NULL);
+	rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
+			    ops->hardreset, ops->postreset, NULL);
 	if (rc) {
-		ata_for_each_dev(dev, &ap->link, ALL)
+		struct ata_device *dev;
+
+		ata_for_each_dev(dev, link, ALL)
 			ata_dev_disable(dev);
 	}
 
 	ata_eh_finish(ap);
 }
-
-/**
- *	ata_std_error_handler - standard error handler
- *	@ap: host port to handle error for
- *
- *	Standard error handler
- *
- *	LOCKING:
- *	Kernel thread context (may sleep).
- */
-void ata_std_error_handler(struct ata_port *ap)
-{
-	struct ata_port_operations *ops = ap->ops;
-	ata_reset_fn_t hardreset = ops->hardreset;
-
-	/* ignore built-in hardreset if SCR access is not available */
-	if (hardreset == sata_std_hardreset && !sata_scr_valid(&ap->link))
-		hardreset = NULL;
-
-	ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
-}
 EXPORT_SYMBOL_GPL(ata_std_error_handler);
 
 #ifdef CONFIG_PM
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 83cb44ca5a97e..13aec8ce4458f 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -2054,8 +2054,6 @@ EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
  */
 void ata_sff_error_handler(struct ata_port *ap)
 {
-	ata_reset_fn_t softreset = ap->ops->softreset;
-	ata_reset_fn_t hardreset = ap->ops->hardreset;
 	struct ata_queued_cmd *qc;
 	unsigned long flags;
 
@@ -2077,13 +2075,7 @@ void ata_sff_error_handler(struct ata_port *ap)
 
 	spin_unlock_irqrestore(ap->lock, flags);
 
-	/* ignore built-in hardresets if SCR access is not available */
-	if ((hardreset == sata_std_hardreset ||
-	     hardreset == sata_sff_hardreset) && !sata_scr_valid(&ap->link))
-		hardreset = NULL;
-
-	ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
-		  ap->ops->postreset);
+	ata_std_error_handler(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_error_handler);
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index e5e098279803b..511dad024708a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1418,9 +1418,6 @@ extern void ata_eh_thaw_port(struct ata_port *ap);
 extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 
-extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-		      ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-		      ata_postreset_fn_t postreset);
 extern void ata_std_error_handler(struct ata_port *ap);
 extern void ata_std_sched_eh(struct ata_port *ap);
 extern void ata_std_end_eh(struct ata_port *ap);
@@ -2153,6 +2150,12 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
 
 	return status;
 }
+#else /* CONFIG_ATA_SFF */
+static inline int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
+				     unsigned long deadline)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_ATA_SFF */
 
 #endif /* __LINUX_LIBATA_H__ */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6.12.y 3/5] ata: libata-eh: Simplify reset operation management
  2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 2/5] ata: libata-eh: Remove ata_do_eh() Sasha Levin
@ 2026-11-10 15:12   ` Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 4/5] ata: libata: Add an argument to ata_eh_reset() Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 5/5] ata: sata_inic162x: remove dangerous broken driver Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-11-10 15:12 UTC (permalink / raw)
  To: stable
  Cc: Damien Le Moal, Niklas Cassel, Martin K. Petersen,
	Hannes Reinecke, Sasha Levin

From: Damien Le Moal <dlemoal@kernel.org>

[ Upstream commit a4daf088a77323154514eb1f8626bbdf9329cfd4 ]

Introduce struct ata_reset_operations to aggregate in a single structure
the definitions of the 4 reset methods (prereset, softreset, hardreset
and postreset) for a port. This new structure is used in struct ata_port
to define the reset methods for a regular port (reset field) and for a
port-multiplier port (pmp_reset field). A pointer to either of these
fields replaces the 4 reset method arguments passed to ata_eh_recover()
and ata_eh_reset().

The definition of the reset methods for all drivers is changed to use
the reset and pmp_reset fields in struct ata_port_operations.

A large number of files is modifed, but no functional changes are
introduced.

Suggested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://lore.kernel.org/r/20250716020315.235457-3-dlemoal@kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Stable-dep-of: 96fdeb7e3fd8 ("ata: sata_inic162x: remove dangerous broken driver")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/ata/ahci.c                      |  6 ++---
 drivers/ata/ahci_da850.c                |  6 ++---
 drivers/ata/ahci_dm816.c                |  2 +-
 drivers/ata/ahci_imx.c                  | 13 ++++++-----
 drivers/ata/ahci_qoriq.c                |  4 ++--
 drivers/ata/ahci_xgene.c                |  8 +++----
 drivers/ata/ata_piix.c                  |  4 ++--
 drivers/ata/libahci.c                   | 10 ++++-----
 drivers/ata/libata-core.c               |  4 ++--
 drivers/ata/libata-eh.c                 | 29 +++++++++++--------------
 drivers/ata/libata-pmp.c                | 26 ++++++++--------------
 drivers/ata/libata-sata.c               |  2 +-
 drivers/ata/libata-sff.c                |  8 +++----
 drivers/ata/libata.h                    |  8 +++----
 drivers/ata/pata_acpi.c                 |  2 +-
 drivers/ata/pata_ali.c                  | 10 ++++-----
 drivers/ata/pata_amd.c                  |  4 ++--
 drivers/ata/pata_artop.c                |  4 ++--
 drivers/ata/pata_atiixp.c               |  2 +-
 drivers/ata/pata_efar.c                 |  2 +-
 drivers/ata/pata_ep93xx.c               |  4 ++--
 drivers/ata/pata_hpt366.c               |  2 +-
 drivers/ata/pata_hpt37x.c               |  4 ++--
 drivers/ata/pata_hpt3x2n.c              |  2 +-
 drivers/ata/pata_icside.c               |  2 +-
 drivers/ata/pata_it8213.c               |  2 +-
 drivers/ata/pata_jmicron.c              |  2 +-
 drivers/ata/pata_marvell.c              |  2 +-
 drivers/ata/pata_mpiix.c                |  2 +-
 drivers/ata/pata_ns87410.c              |  2 +-
 drivers/ata/pata_octeon_cf.c            |  2 +-
 drivers/ata/pata_oldpiix.c              |  2 +-
 drivers/ata/pata_opti.c                 |  2 +-
 drivers/ata/pata_optidma.c              |  2 +-
 drivers/ata/pata_parport/pata_parport.c |  4 ++--
 drivers/ata/pata_pdc2027x.c             |  2 +-
 drivers/ata/pata_rdc.c                  |  2 +-
 drivers/ata/pata_sis.c                  |  2 +-
 drivers/ata/pata_sl82c105.c             |  2 +-
 drivers/ata/pata_triflex.c              |  2 +-
 drivers/ata/pata_via.c                  |  2 +-
 drivers/ata/pdc_adma.c                  |  2 +-
 drivers/ata/sata_dwc_460ex.c            |  2 +-
 drivers/ata/sata_fsl.c                  |  6 ++---
 drivers/ata/sata_highbank.c             |  2 +-
 drivers/ata/sata_inic162x.c             |  2 +-
 drivers/ata/sata_mv.c                   | 10 ++++-----
 drivers/ata/sata_nv.c                   |  2 +-
 drivers/ata/sata_promise.c              |  4 ++--
 drivers/ata/sata_qstor.c                |  4 ++--
 drivers/ata/sata_rcar.c                 |  2 +-
 drivers/ata/sata_sil24.c                |  8 +++----
 drivers/ata/sata_svw.c                  |  4 ++--
 drivers/ata/sata_sx4.c                  |  2 +-
 drivers/ata/sata_uli.c                  |  2 +-
 drivers/ata/sata_via.c                  |  4 ++--
 drivers/scsi/libsas/sas_ata.c           |  4 ++--
 include/linux/libata.h                  | 17 ++++++++-------
 58 files changed, 134 insertions(+), 145 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 85b7bd605d7d8..bd543a5ee8c49 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -111,17 +111,17 @@ static const struct scsi_host_template ahci_sht = {
 
 static struct ata_port_operations ahci_vt8251_ops = {
 	.inherits		= &ahci_ops,
-	.hardreset		= ahci_vt8251_hardreset,
+	.reset.hardreset	= ahci_vt8251_hardreset,
 };
 
 static struct ata_port_operations ahci_p5wdh_ops = {
 	.inherits		= &ahci_ops,
-	.hardreset		= ahci_p5wdh_hardreset,
+	.reset.hardreset	= ahci_p5wdh_hardreset,
 };
 
 static struct ata_port_operations ahci_avn_ops = {
 	.inherits		= &ahci_ops,
-	.hardreset		= ahci_avn_hardreset,
+	.reset.hardreset	= ahci_avn_hardreset,
 };
 
 static const struct ata_port_info ahci_port_info[] = {
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 55a6627d5450e..2b331770ac528 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -137,13 +137,13 @@ static int ahci_da850_hardreset(struct ata_link *link,
 
 static struct ata_port_operations ahci_da850_port_ops = {
 	.inherits = &ahci_platform_ops,
-	.softreset = ahci_da850_softreset,
+	.reset.softreset = ahci_da850_softreset,
 	/*
 	 * No need to override .pmp_softreset - it's only used for actual
 	 * PMP-enabled ports.
 	 */
-	.hardreset = ahci_da850_hardreset,
-	.pmp_hardreset = ahci_da850_hardreset,
+	.reset.hardreset = ahci_da850_hardreset,
+	.pmp_reset.hardreset = ahci_da850_hardreset,
 };
 
 static const struct ata_port_info ahci_da850_port_info = {
diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c
index 4cb70064fb994..188d45716d3a1 100644
--- a/drivers/ata/ahci_dm816.c
+++ b/drivers/ata/ahci_dm816.c
@@ -124,7 +124,7 @@ static int ahci_dm816_softreset(struct ata_link *link,
 
 static struct ata_port_operations ahci_dm816_port_ops = {
 	.inherits = &ahci_platform_ops,
-	.softreset = ahci_dm816_softreset,
+	.reset.softreset = ahci_dm816_softreset,
 };
 
 static const struct ata_port_info ahci_dm816_port_info = {
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 6f955e9105e88..91c72a58f91c3 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -642,18 +642,19 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
 	int ret;
 
 	if (imxpriv->type == AHCI_IMX53)
-		ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
+		ret = ahci_pmp_retry_srst_ops.reset.softreset(link, class,
+							      deadline);
 	else
-		ret = ahci_ops.softreset(link, class, deadline);
+		ret = ahci_ops.reset.softreset(link, class, deadline);
 
 	return ret;
 }
 
 static struct ata_port_operations ahci_imx_ops = {
-	.inherits	= &ahci_ops,
-	.host_stop	= ahci_imx_host_stop,
-	.error_handler	= ahci_imx_error_handler,
-	.softreset	= ahci_imx_softreset,
+	.inherits		= &ahci_ops,
+	.host_stop		= ahci_imx_host_stop,
+	.error_handler		= ahci_imx_error_handler,
+	.reset.softreset	= ahci_imx_softreset,
 };
 
 static const struct ata_port_info ahci_imx_port_info = {
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index b1a4e57578e20..36e367a17d593 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -146,8 +146,8 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
 }
 
 static struct ata_port_operations ahci_qoriq_ops = {
-	.inherits	= &ahci_ops,
-	.hardreset	= ahci_qoriq_hardreset,
+	.inherits		= &ahci_ops,
+	.reset.hardreset	= ahci_qoriq_hardreset,
 };
 
 static const struct ata_port_info ahci_qoriq_port_info = {
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 81a1d838c0fc5..d51cd210be13b 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -613,11 +613,11 @@ static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
 static struct ata_port_operations xgene_ahci_v1_ops = {
 	.inherits = &ahci_ops,
 	.host_stop = xgene_ahci_host_stop,
-	.hardreset = xgene_ahci_hardreset,
+	.reset.hardreset = xgene_ahci_hardreset,
+	.reset.softreset = xgene_ahci_softreset,
+	.pmp_reset.softreset = xgene_ahci_pmp_softreset,
 	.read_id = xgene_ahci_read_id,
 	.qc_issue = xgene_ahci_qc_issue,
-	.softreset = xgene_ahci_softreset,
-	.pmp_softreset = xgene_ahci_pmp_softreset
 };
 
 static const struct ata_port_info xgene_ahci_v1_port_info = {
@@ -630,7 +630,7 @@ static const struct ata_port_info xgene_ahci_v1_port_info = {
 static struct ata_port_operations xgene_ahci_v2_ops = {
 	.inherits = &ahci_ops,
 	.host_stop = xgene_ahci_host_stop,
-	.hardreset = xgene_ahci_hardreset,
+	.reset.hardreset = xgene_ahci_hardreset,
 	.read_id = xgene_ahci_read_id,
 };
 
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index d3cda803ae06d..a78b662d33228 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1074,7 +1074,7 @@ static struct ata_port_operations piix_pata_ops = {
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
-	.prereset		= piix_pata_prereset,
+	.reset.prereset		= piix_pata_prereset,
 };
 
 static struct ata_port_operations piix_vmw_ops = {
@@ -1103,7 +1103,7 @@ static const struct scsi_host_template piix_sidpr_sht = {
 
 static struct ata_port_operations piix_sidpr_sata_ops = {
 	.inherits		= &piix_sata_ops,
-	.hardreset		= sata_std_hardreset,
+	.reset.hardreset	= sata_std_hardreset,
 	.scr_read		= piix_sidpr_scr_read,
 	.scr_write		= piix_sidpr_scr_write,
 	.set_lpm		= piix_sidpr_set_lpm,
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 3fd193fcbd6ea..cefb5013186ed 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -163,10 +163,10 @@ struct ata_port_operations ahci_ops = {
 
 	.freeze			= ahci_freeze,
 	.thaw			= ahci_thaw,
-	.softreset		= ahci_softreset,
-	.hardreset		= ahci_hardreset,
-	.postreset		= ahci_postreset,
-	.pmp_softreset		= ahci_softreset,
+	.reset.softreset	= ahci_softreset,
+	.reset.hardreset	= ahci_hardreset,
+	.reset.postreset	= ahci_postreset,
+	.pmp_reset.softreset	= ahci_softreset,
 	.error_handler		= ahci_error_handler,
 	.post_internal_cmd	= ahci_post_internal_cmd,
 	.dev_config		= ahci_dev_config,
@@ -193,7 +193,7 @@ EXPORT_SYMBOL_GPL(ahci_ops);
 
 struct ata_port_operations ahci_pmp_retry_srst_ops = {
 	.inherits		= &ahci_ops,
-	.softreset		= ahci_pmp_retry_softreset,
+	.reset.softreset	= ahci_pmp_retry_softreset,
 };
 EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
 
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 0db6821cc3aaf..65fb2cfc0e291 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -65,8 +65,8 @@
 #include "libata-transport.h"
 
 const struct ata_port_operations ata_base_port_ops = {
-	.prereset		= ata_std_prereset,
-	.postreset		= ata_std_postreset,
+	.reset.prereset		= ata_std_prereset,
+	.reset.postreset	= ata_std_postreset,
 	.error_handler		= ata_std_error_handler,
 	.sched_eh		= ata_std_sched_eh,
 	.end_eh			= ata_std_end_eh,
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index a7525c8e97bf3..366b7d2a10e5d 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2633,13 +2633,16 @@ static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)
 }
 
 int ata_eh_reset(struct ata_link *link, int classify,
-		 ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-		 ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+		 struct ata_reset_operations *reset_ops)
 {
 	struct ata_port *ap = link->ap;
 	struct ata_link *slave = ap->slave_link;
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
+	ata_reset_fn_t hardreset = reset_ops->hardreset;
+	ata_reset_fn_t softreset = reset_ops->softreset;
+	ata_prereset_fn_t prereset = reset_ops->prereset;
+	ata_postreset_fn_t postreset = reset_ops->postreset;
 	unsigned int *classes = ehc->classes;
 	unsigned int lflags = link->flags;
 	int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
@@ -3730,10 +3733,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
 /**
  *	ata_eh_recover - recover host port after error
  *	@ap: host port to recover
- *	@prereset: prereset method (can be NULL)
- *	@softreset: softreset method (can be NULL)
- *	@hardreset: hardreset method (can be NULL)
- *	@postreset: postreset method (can be NULL)
+ *	@reset_ops: The set of reset operations to use
  *	@r_failed_link: out parameter for failed link
  *
  *	This is the alpha and omega, eum and yang, heart and soul of
@@ -3749,9 +3749,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
  *	RETURNS:
  *	0 on success, -errno on failure.
  */
-int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
-		   ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-		   ata_postreset_fn_t postreset,
+int ata_eh_recover(struct ata_port *ap, struct ata_reset_operations *reset_ops,
 		   struct ata_link **r_failed_link)
 {
 	struct ata_link *link;
@@ -3819,8 +3817,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 		if (!(ehc->i.action & ATA_EH_RESET))
 			continue;
 
-		rc = ata_eh_reset(link, ata_link_nr_vacant(link),
-				  prereset, softreset, hardreset, postreset);
+		rc = ata_eh_reset(link, ata_link_nr_vacant(link), reset_ops);
 		if (rc) {
 			ata_link_err(link, "reset failed, giving up\n");
 			goto out;
@@ -4050,20 +4047,20 @@ void ata_eh_finish(struct ata_port *ap)
  */
 void ata_std_error_handler(struct ata_port *ap)
 {
-	struct ata_port_operations *ops = ap->ops;
+	struct ata_reset_operations *reset_ops = &ap->ops->reset;
 	struct ata_link *link = &ap->link;
 	int rc;
 
 	/* Ignore built-in hardresets if SCR access is not available */
-	if ((ops->hardreset == sata_std_hardreset ||
-	     ops->hardreset == sata_sff_hardreset) && !sata_scr_valid(link))
+	if ((reset_ops->hardreset == sata_std_hardreset ||
+	     reset_ops->hardreset == sata_sff_hardreset) &&
+	    !sata_scr_valid(link))
 		link->flags |= ATA_LFLAG_NO_HRST;
 
 	ata_eh_autopsy(ap);
 	ata_eh_report(ap);
 
-	rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
-			    ops->hardreset, ops->postreset, NULL);
+	rc = ata_eh_recover(ap, reset_ops, NULL);
 	if (rc) {
 		struct ata_device *dev;
 
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 1f1e887442654..99c67dbfb7536 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -15,9 +15,9 @@
 
 const struct ata_port_operations sata_pmp_port_ops = {
 	.inherits		= &sata_port_ops,
-	.pmp_prereset		= ata_std_prereset,
-	.pmp_hardreset		= sata_std_hardreset,
-	.pmp_postreset		= ata_std_postreset,
+	.pmp_reset.prereset	= ata_std_prereset,
+	.pmp_reset.hardreset	= sata_std_hardreset,
+	.pmp_reset.postreset	= ata_std_postreset,
 	.error_handler		= sata_pmp_error_handler,
 };
 
@@ -760,10 +760,7 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)
 /**
  *	sata_pmp_eh_recover_pmp - recover PMP
  *	@ap: ATA port PMP is attached to
- *	@prereset: prereset method (can be NULL)
- *	@softreset: softreset method
- *	@hardreset: hardreset method
- *	@postreset: postreset method (can be NULL)
+ *	@reset_ops: The set of reset operations to use
  *
  *	Recover PMP attached to @ap.  Recovery procedure is somewhat
  *	similar to that of ata_eh_recover() except that reset should
@@ -777,8 +774,7 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)
  *	0 on success, -errno on failure.
  */
 static int 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)
+				   struct ata_reset_operations *reset_ops)
 {
 	struct ata_link *link = &ap->link;
 	struct ata_eh_context *ehc = &link->eh_context;
@@ -800,8 +796,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 		struct ata_link *tlink;
 
 		/* reset */
-		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
-				  postreset);
+		rc = ata_eh_reset(link, 0, reset_ops);
 		if (rc) {
 			ata_link_err(link, "failed to reset PMP, giving up\n");
 			goto fail;
@@ -965,8 +960,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
  retry:
 	/* PMP attached? */
 	if (!sata_pmp_attached(ap)) {
-		rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
-				    ops->hardreset, ops->postreset, NULL);
+		rc = ata_eh_recover(ap, &ops->reset, NULL);
 		if (rc) {
 			ata_for_each_dev(dev, &ap->link, ALL)
 				ata_dev_disable(dev);
@@ -984,8 +978,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 	}
 
 	/* recover pmp */
-	rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
-				     ops->hardreset, ops->postreset);
+	rc = sata_pmp_eh_recover_pmp(ap, &ops->reset);
 	if (rc)
 		goto pmp_fail;
 
@@ -1011,8 +1004,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 		goto pmp_fail;
 
 	/* recover links */
-	rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
-			    ops->pmp_hardreset, ops->pmp_postreset, &link);
+	rc = ata_eh_recover(ap, &ops->pmp_reset, &link);
 	if (rc)
 		goto link_fail;
 
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index fc64fae9e23fe..0b6cfdfc27598 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -1735,6 +1735,6 @@ const struct ata_port_operations sata_port_ops = {
 	.inherits		= &ata_base_port_ops,
 
 	.qc_defer		= ata_std_qc_defer,
-	.hardreset		= sata_std_hardreset,
+	.reset.hardreset	= sata_std_hardreset,
 };
 EXPORT_SYMBOL_GPL(sata_port_ops);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 13aec8ce4458f..95a3ddf36eff6 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -31,10 +31,10 @@ const struct ata_port_operations ata_sff_port_ops = {
 
 	.freeze			= ata_sff_freeze,
 	.thaw			= ata_sff_thaw,
-	.prereset		= ata_sff_prereset,
-	.softreset		= ata_sff_softreset,
-	.hardreset		= sata_sff_hardreset,
-	.postreset		= ata_sff_postreset,
+	.reset.prereset		= ata_sff_prereset,
+	.reset.softreset	= ata_sff_softreset,
+	.reset.hardreset	= sata_sff_hardreset,
+	.reset.postreset	= ata_sff_postreset,
 	.error_handler		= ata_sff_error_handler,
 
 	.sff_dev_select		= ata_sff_dev_select,
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 898d5b368d82f..0a5f9a4fa906f 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -197,11 +197,9 @@ extern void ata_eh_autopsy(struct ata_port *ap);
 const char *ata_get_cmd_name(u8 command);
 extern void ata_eh_report(struct ata_port *ap);
 extern int ata_eh_reset(struct ata_link *link, int classify,
-			ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-			ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
-extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
-			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-			  ata_postreset_fn_t postreset,
+			struct ata_reset_operations *reset_ops);
+extern int ata_eh_recover(struct ata_port *ap,
+			  struct ata_reset_operations *reset_ops,
 			  struct ata_link **r_failed_disk);
 extern void ata_eh_finish(struct ata_port *ap);
 extern int ata_ering_map(struct ata_ering *ering,
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index ab38871b5e007..23fff10af2ac2 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -216,7 +216,7 @@ static struct ata_port_operations pacpi_ops = {
 	.mode_filter		= pacpi_mode_filter,
 	.set_piomode		= pacpi_set_piomode,
 	.set_dmamode		= pacpi_set_dmamode,
-	.prereset		= pacpi_pre_reset,
+	.reset.prereset		= pacpi_pre_reset,
 	.port_start		= pacpi_port_start,
 };
 
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index bb790edd60361..9d5cb9c34c522 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -392,11 +392,11 @@ static struct ata_port_operations ali_20_port_ops = {
  *	Port operations for DMA capable ALi with cable detect
  */
 static struct ata_port_operations ali_c2_port_ops = {
-	.inherits	= &ali_dma_base_ops,
-	.check_atapi_dma = ali_check_atapi_dma,
-	.cable_detect	= ali_c2_cable_detect,
-	.dev_config	= ali_lock_sectors,
-	.postreset	= ali_c2_c3_postreset,
+	.inherits		= &ali_dma_base_ops,
+	.check_atapi_dma	= ali_check_atapi_dma,
+	.cable_detect		= ali_c2_cable_detect,
+	.dev_config		= ali_lock_sectors,
+	.reset.postreset	= ali_c2_c3_postreset,
 };
 
 /*
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 5b02b89748b7f..a2fecadc927d4 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -394,7 +394,7 @@ static const struct scsi_host_template amd_sht = {
 
 static const struct ata_port_operations amd_base_port_ops = {
 	.inherits	= &ata_bmdma32_port_ops,
-	.prereset	= amd_pre_reset,
+	.reset.prereset	= amd_pre_reset,
 };
 
 static struct ata_port_operations amd33_port_ops = {
@@ -429,7 +429,7 @@ static const struct ata_port_operations nv_base_port_ops = {
 	.inherits	= &ata_bmdma_port_ops,
 	.cable_detect	= ata_cable_ignore,
 	.mode_filter	= nv_mode_filter,
-	.prereset	= nv_pre_reset,
+	.reset.prereset	= nv_pre_reset,
 	.host_stop	= nv_host_stop,
 };
 
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 40544282f455b..6160414172a31 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -301,7 +301,7 @@ static struct ata_port_operations artop6210_ops = {
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= artop6210_set_piomode,
 	.set_dmamode		= artop6210_set_dmamode,
-	.prereset		= artop62x0_pre_reset,
+	.reset.prereset		= artop62x0_pre_reset,
 	.qc_defer		= artop6210_qc_defer,
 };
 
@@ -310,7 +310,7 @@ static struct ata_port_operations artop6260_ops = {
 	.cable_detect		= artop6260_cable_detect,
 	.set_piomode		= artop6260_set_piomode,
 	.set_dmamode		= artop6260_set_dmamode,
-	.prereset		= artop62x0_pre_reset,
+	.reset.prereset		= artop62x0_pre_reset,
 };
 
 static void atp8xx_fixup(struct pci_dev *pdev)
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 8c5cc803aab35..4c612f9543f6c 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -264,7 +264,7 @@ static struct ata_port_operations atiixp_port_ops = {
 	.bmdma_start 	= atiixp_bmdma_start,
 	.bmdma_stop	= atiixp_bmdma_stop,
 
-	.prereset	= atiixp_prereset,
+	.reset.prereset	= atiixp_prereset,
 	.cable_detect	= atiixp_cable_detect,
 	.set_piomode	= atiixp_set_piomode,
 	.set_dmamode	= atiixp_set_dmamode,
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 2e6eccf2902fa..6fe49b303fee4 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -243,7 +243,7 @@ static struct ata_port_operations efar_ops = {
 	.cable_detect		= efar_cable_detect,
 	.set_piomode		= efar_set_piomode,
 	.set_dmamode		= efar_set_dmamode,
-	.prereset		= efar_pre_reset,
+	.reset.prereset		= efar_pre_reset,
 };
 
 
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 3ee9753097910..f469c40a89162 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -891,8 +891,8 @@ static const struct scsi_host_template ep93xx_pata_sht = {
 static struct ata_port_operations ep93xx_pata_port_ops = {
 	.inherits		= &ata_bmdma_port_ops,
 
-	.softreset		= ep93xx_pata_softreset,
-	.hardreset		= ATA_OP_NULL,
+	.reset.softreset	= ep93xx_pata_softreset,
+	.reset.hardreset	= ATA_OP_NULL,
 
 	.sff_dev_select		= ep93xx_pata_dev_select,
 	.sff_set_devctl		= ep93xx_pata_set_devctl,
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 5280e9960025e..b96e8bd2a3f83 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -322,7 +322,7 @@ static const struct scsi_host_template hpt36x_sht = {
 
 static struct ata_port_operations hpt366_port_ops = {
 	.inherits	= &ata_bmdma_port_ops,
-	.prereset	= hpt366_prereset,
+	.reset.prereset	= hpt366_prereset,
 	.cable_detect	= hpt36x_cable_detect,
 	.mode_filter	= hpt366_filter,
 	.set_piomode	= hpt366_set_piomode,
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 4af22b819416c..07e3a984cbb19 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -543,7 +543,7 @@ static struct ata_port_operations hpt370_port_ops = {
 	.cable_detect	= hpt37x_cable_detect,
 	.set_piomode	= hpt37x_set_piomode,
 	.set_dmamode	= hpt37x_set_dmamode,
-	.prereset	= hpt37x_pre_reset,
+	.reset.prereset	= hpt37x_pre_reset,
 };
 
 /*
@@ -567,7 +567,7 @@ static struct ata_port_operations hpt302_port_ops = {
 	.cable_detect	= hpt37x_cable_detect,
 	.set_piomode	= hpt37x_set_piomode,
 	.set_dmamode	= hpt37x_set_dmamode,
-	.prereset	= hpt37x_pre_reset,
+	.reset.prereset	= hpt37x_pre_reset,
 };
 
 /*
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 5b1ecccf3c838..2cc57fcf2c466 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -356,7 +356,7 @@ static struct ata_port_operations hpt3xxn_port_ops = {
 	.cable_detect	= hpt3x2n_cable_detect,
 	.set_piomode	= hpt3x2n_set_piomode,
 	.set_dmamode	= hpt3x2n_set_dmamode,
-	.prereset	= hpt3x2n_pre_reset,
+	.reset.prereset	= hpt3x2n_pre_reset,
 };
 
 /*
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index 61d8760f09d91..70f056e47e6bd 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -336,7 +336,7 @@ static struct ata_port_operations pata_icside_port_ops = {
 
 	.cable_detect		= ata_cable_40wire,
 	.set_dmamode		= pata_icside_set_dmamode,
-	.postreset		= pata_icside_postreset,
+	.reset.postreset	= pata_icside_postreset,
 
 	.port_start		= ATA_OP_NULL,	/* don't need PRD table */
 };
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index b7ac56103c8a3..5ea75933cb8b0 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -238,7 +238,7 @@ static struct ata_port_operations it8213_ops = {
 	.cable_detect		= it8213_cable_detect,
 	.set_piomode		= it8213_set_piomode,
 	.set_dmamode		= it8213_set_dmamode,
-	.prereset		= it8213_pre_reset,
+	.reset.prereset		= it8213_pre_reset,
 };
 
 
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index f51fb82197624..b885f33e89805 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -113,7 +113,7 @@ static const struct scsi_host_template jmicron_sht = {
 
 static struct ata_port_operations jmicron_ops = {
 	.inherits		= &ata_bmdma_port_ops,
-	.prereset		= jmicron_pre_reset,
+	.reset.prereset		= jmicron_pre_reset,
 };
 
 
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 8119caaad6055..deab673283889 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -99,7 +99,7 @@ static const struct scsi_host_template marvell_sht = {
 static struct ata_port_operations marvell_ops = {
 	.inherits		= &ata_bmdma_port_ops,
 	.cable_detect		= marvell_cable_detect,
-	.prereset		= marvell_pre_reset,
+	.reset.prereset		= marvell_pre_reset,
 };
 
 
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 69e4baf27d728..ce310ae7c93ac 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -145,7 +145,7 @@ static struct ata_port_operations mpiix_port_ops = {
 	.qc_issue	= mpiix_qc_issue,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= mpiix_set_piomode,
-	.prereset	= mpiix_pre_reset,
+	.reset.prereset	= mpiix_pre_reset,
 	.sff_data_xfer	= ata_sff_data_xfer32,
 };
 
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 44cc24d21d5f0..bdb55c1a32802 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -123,7 +123,7 @@ static struct ata_port_operations ns87410_port_ops = {
 	.qc_issue	= ns87410_qc_issue,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= ns87410_set_piomode,
-	.prereset	= ns87410_pre_reset,
+	.reset.prereset	= ns87410_pre_reset,
 };
 
 static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 0bb9607e73486..dc61a3004ba9a 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -942,7 +942,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
 		/* 16 bit but not True IDE */
 		base = cs0 + 0x800;
 		octeon_cf_ops.sff_data_xfer	= octeon_cf_data_xfer16;
-		octeon_cf_ops.softreset		= octeon_cf_softreset16;
+		octeon_cf_ops.reset.softreset	= octeon_cf_softreset16;
 		octeon_cf_ops.sff_check_status	= octeon_cf_check_status16;
 		octeon_cf_ops.sff_tf_read	= octeon_cf_tf_read16;
 		octeon_cf_ops.sff_tf_load	= octeon_cf_tf_load16;
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index dca82d92b004f..659f27aa34641 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -214,7 +214,7 @@ static struct ata_port_operations oldpiix_pata_ops = {
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= oldpiix_set_piomode,
 	.set_dmamode		= oldpiix_set_dmamode,
-	.prereset		= oldpiix_pre_reset,
+	.reset.prereset		= oldpiix_pre_reset,
 };
 
 
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 3d23f57eb1289..3db1b95d14045 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -156,7 +156,7 @@ static struct ata_port_operations opti_port_ops = {
 	.inherits	= &ata_sff_port_ops,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= opti_set_piomode,
-	.prereset	= opti_pre_reset,
+	.reset.prereset	= opti_pre_reset,
 };
 
 static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index dfc36b4ec9c6b..50124e205ece2 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -344,7 +344,7 @@ static struct ata_port_operations optidma_port_ops = {
 	.set_piomode	= optidma_set_pio_mode,
 	.set_dmamode	= optidma_set_dma_mode,
 	.set_mode	= optidma_set_mode,
-	.prereset	= optidma_pre_reset,
+	.reset.prereset	= optidma_pre_reset,
 };
 
 static struct ata_port_operations optiplus_port_ops = {
diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c
index 93ebf566b54ec..22bd3ff6b7ae8 100644
--- a/drivers/ata/pata_parport/pata_parport.c
+++ b/drivers/ata/pata_parport/pata_parport.c
@@ -321,8 +321,8 @@ static void pata_parport_drain_fifo(struct ata_queued_cmd *qc)
 static struct ata_port_operations pata_parport_port_ops = {
 	.inherits		= &ata_sff_port_ops,
 
-	.softreset		= pata_parport_softreset,
-	.hardreset		= NULL,
+	.reset.softreset	= pata_parport_softreset,
+	.reset.hardreset	= NULL,
 
 	.sff_dev_select		= pata_parport_dev_select,
 	.sff_set_devctl		= pata_parport_set_devctl,
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 6820c5597b145..29df7d501b94c 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -130,7 +130,7 @@ static struct ata_port_operations pdc2027x_pata100_ops = {
 	.inherits		= &ata_bmdma_port_ops,
 	.check_atapi_dma	= pdc2027x_check_atapi_dma,
 	.cable_detect		= pdc2027x_cable_detect,
-	.prereset		= pdc2027x_prereset,
+	.reset.prereset		= pdc2027x_prereset,
 };
 
 static struct ata_port_operations pdc2027x_pata133_ops = {
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 0a9689862f710..6d8b276c979d4 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -276,7 +276,7 @@ static struct ata_port_operations rdc_pata_ops = {
 	.cable_detect		= rdc_pata_cable_detect,
 	.set_piomode		= rdc_set_piomode,
 	.set_dmamode		= rdc_set_dmamode,
-	.prereset		= rdc_pata_prereset,
+	.reset.prereset		= rdc_pata_prereset,
 };
 
 static const struct ata_port_info rdc_port_info = {
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 31de06b662210..2b751e393771f 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -552,7 +552,7 @@ static struct ata_port_operations sis_133_for_sata_ops = {
 
 static struct ata_port_operations sis_base_ops = {
 	.inherits		= &ata_bmdma_port_ops,
-	.prereset		= sis_pre_reset,
+	.reset.prereset		= sis_pre_reset,
 };
 
 static struct ata_port_operations sis_133_ops = {
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 2a5ce46af5a0a..25bce3fe2a101 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -248,7 +248,7 @@ static struct ata_port_operations sl82c105_port_ops = {
 	.bmdma_stop	= sl82c105_bmdma_stop,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= sl82c105_set_piomode,
-	.prereset	= sl82c105_pre_reset,
+	.reset.prereset	= sl82c105_pre_reset,
 	.sff_irq_check	= sl82c105_sff_irq_check,
 };
 
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index 26d448a869e2f..596e86a031b3e 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -170,7 +170,7 @@ static struct ata_port_operations triflex_port_ops = {
 	.bmdma_stop	= triflex_bmdma_stop,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= triflex_set_piomode,
-	.prereset	= triflex_prereset,
+	.reset.prereset	= triflex_prereset,
 };
 
 static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index bb80e7800dcbe..a8c9cf685b4bb 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -451,7 +451,7 @@ static struct ata_port_operations via_port_ops = {
 	.cable_detect	= via_cable_detect,
 	.set_piomode	= via_set_piomode,
 	.set_dmamode	= via_set_dmamode,
-	.prereset	= via_pre_reset,
+	.reset.prereset	= via_pre_reset,
 	.sff_tf_load	= via_tf_load,
 	.port_start	= via_port_start,
 	.mode_filter	= via_mode_filter,
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 8e6b2599f0d53..17a5a59861c38 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -140,7 +140,7 @@ static struct ata_port_operations adma_ata_ops = {
 
 	.freeze			= adma_freeze,
 	.thaw			= adma_thaw,
-	.prereset		= adma_prereset,
+	.reset.prereset		= adma_prereset,
 
 	.port_start		= adma_port_start,
 	.port_stop		= adma_port_stop,
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 66db8dd8ec267..23753c4ae1b56 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1087,7 +1087,7 @@ static struct ata_port_operations sata_dwc_ops = {
 	.inherits		= &ata_sff_port_ops,
 
 	.error_handler		= sata_dwc_error_handler,
-	.hardreset		= sata_dwc_hardreset,
+	.reset.hardreset	= sata_dwc_hardreset,
 
 	.qc_issue		= sata_dwc_qc_issue,
 
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index c64c9d99cd6c2..56247db5d1d24 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1395,9 +1395,9 @@ static struct ata_port_operations sata_fsl_ops = {
 
 	.freeze = sata_fsl_freeze,
 	.thaw = sata_fsl_thaw,
-	.softreset = sata_fsl_softreset,
-	.hardreset = sata_fsl_hardreset,
-	.pmp_softreset = sata_fsl_softreset,
+	.reset.softreset = sata_fsl_softreset,
+	.reset.hardreset = sata_fsl_hardreset,
+	.pmp_reset.softreset = sata_fsl_softreset,
 	.error_handler = sata_fsl_error_handler,
 	.post_internal_cmd = sata_fsl_post_internal_cmd,
 
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 596c6d294da90..6349026ed027c 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -428,7 +428,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
 
 static struct ata_port_operations ahci_highbank_ops = {
 	.inherits		= &ahci_ops,
-	.hardreset		= ahci_highbank_hardreset,
+	.reset.hardreset	= ahci_highbank_hardreset,
 	.transmit_led_message   = ecx_transmit_led_message,
 };
 
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index db9c255dc9f2e..46a8c20daf180 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -730,7 +730,7 @@ static struct ata_port_operations inic_port_ops = {
 
 	.freeze			= inic_freeze,
 	.thaw			= inic_thaw,
-	.hardreset		= inic_hardreset,
+	.reset.hardreset	= inic_hardreset,
 	.error_handler		= inic_error_handler,
 	.post_internal_cmd	= inic_post_internal_cmd,
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 40fdc422940dd..7e1bd5610c3c8 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -687,7 +687,7 @@ static struct ata_port_operations mv5_ops = {
 
 	.freeze			= mv_eh_freeze,
 	.thaw			= mv_eh_thaw,
-	.hardreset		= mv_hardreset,
+	.reset.hardreset	= mv_hardreset,
 
 	.scr_read		= mv5_scr_read,
 	.scr_write		= mv5_scr_write,
@@ -709,10 +709,10 @@ static struct ata_port_operations mv6_ops = {
 
 	.freeze			= mv_eh_freeze,
 	.thaw			= mv_eh_thaw,
-	.hardreset		= mv_hardreset,
-	.softreset		= mv_softreset,
-	.pmp_hardreset		= mv_pmp_hardreset,
-	.pmp_softreset		= mv_softreset,
+	.reset.hardreset	= mv_hardreset,
+	.reset.softreset	= mv_softreset,
+	.pmp_reset.hardreset	= mv_pmp_hardreset,
+	.pmp_reset.softreset	= mv_softreset,
 	.error_handler		= mv_pmp_error_handler,
 
 	.scr_read		= mv_scr_read,
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 36d99043ef50f..d1e6e80d0103b 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -462,7 +462,7 @@ static struct ata_port_operations nv_generic_ops = {
 	.lost_interrupt		= ATA_OP_NULL,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
-	.hardreset		= nv_hardreset,
+	.reset.hardreset	= nv_hardreset,
 };
 
 static struct ata_port_operations nv_nf2_ops = {
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 2df1a070b25a9..2a005aede123d 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -188,7 +188,7 @@ static struct ata_port_operations pdc_sata_ops = {
 	.scr_read		= pdc_sata_scr_read,
 	.scr_write		= pdc_sata_scr_write,
 	.port_start		= pdc_sata_port_start,
-	.hardreset		= pdc_sata_hardreset,
+	.reset.hardreset	= pdc_sata_hardreset,
 };
 
 /* First-generation chips need a more restrictive ->check_atapi_dma op,
@@ -206,7 +206,7 @@ static struct ata_port_operations pdc_pata_ops = {
 	.freeze			= pdc_freeze,
 	.thaw			= pdc_thaw,
 	.port_start		= pdc_common_port_start,
-	.softreset		= pdc_pata_softreset,
+	.reset.softreset	= pdc_pata_softreset,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 90289560e7cd8..b2be1ce87878f 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -123,8 +123,8 @@ static struct ata_port_operations qs_ata_ops = {
 
 	.freeze			= qs_freeze,
 	.thaw			= qs_thaw,
-	.prereset		= qs_prereset,
-	.softreset		= ATA_OP_NULL,
+	.reset.prereset		= qs_prereset,
+	.reset.softreset	= ATA_OP_NULL,
 	.error_handler		= qs_error_handler,
 	.lost_interrupt		= ATA_OP_NULL,
 
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index c1469d0768801..146a231f8fe40 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -624,7 +624,7 @@ static struct ata_port_operations sata_rcar_port_ops = {
 
 	.freeze			= sata_rcar_freeze,
 	.thaw			= sata_rcar_thaw,
-	.softreset		= sata_rcar_softreset,
+	.reset.softreset	= sata_rcar_softreset,
 
 	.scr_read		= sata_rcar_scr_read,
 	.scr_write		= sata_rcar_scr_write,
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index ca24c294bf468..92bb693c32d75 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -394,10 +394,10 @@ static struct ata_port_operations sil24_ops = {
 
 	.freeze			= sil24_freeze,
 	.thaw			= sil24_thaw,
-	.softreset		= sil24_softreset,
-	.hardreset		= sil24_hardreset,
-	.pmp_softreset		= sil24_softreset,
-	.pmp_hardreset		= sil24_pmp_hardreset,
+	.reset.softreset	= sil24_softreset,
+	.reset.hardreset	= sil24_hardreset,
+	.pmp_reset.softreset	= sil24_softreset,
+	.pmp_reset.hardreset	= sil24_pmp_hardreset,
 	.error_handler		= sil24_error_handler,
 	.post_internal_cmd	= sil24_post_internal_cmd,
 	.dev_config		= sil24_dev_config,
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 598a872f6a08c..c5d6aa36c9c30 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -340,8 +340,8 @@ static const struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
 	.inherits		= &ata_bmdma_port_ops,
-	.softreset              = k2_sata_softreset,
-	.hardreset              = k2_sata_hardreset,
+	.reset.softreset	= k2_sata_softreset,
+	.reset.hardreset	= k2_sata_hardreset,
 	.sff_tf_load		= k2_sata_tf_load,
 	.sff_tf_read		= k2_sata_tf_read,
 	.sff_check_status	= k2_stat_check_status,
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index c3042eca6332d..1c2ba6d30c2da 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -241,7 +241,7 @@ static struct ata_port_operations pdc_20621_ops = {
 
 	.freeze			= pdc_freeze,
 	.thaw			= pdc_thaw,
-	.softreset		= pdc_softreset,
+	.reset.softreset	= pdc_softreset,
 	.error_handler		= pdc_error_handler,
 	.lost_interrupt		= ATA_OP_NULL,
 	.post_internal_cmd	= pdc_post_internal_cmd,
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 60ea45926cd14..6ad4c00688df9 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -67,7 +67,7 @@ static struct ata_port_operations uli_ops = {
 	.inherits		= &ata_bmdma_port_ops,
 	.scr_read		= uli_scr_read,
 	.scr_write		= uli_scr_write,
-	.hardreset		= ATA_OP_NULL,
+	.reset.hardreset	= ATA_OP_NULL,
 };
 
 static const struct ata_port_info uli_port_info = {
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 57cbf2cef618f..59fb2c1ebcb00 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -119,7 +119,7 @@ static struct ata_port_operations svia_base_ops = {
 static struct ata_port_operations vt6420_sata_ops = {
 	.inherits		= &svia_base_ops,
 	.freeze			= svia_noop_freeze,
-	.prereset		= vt6420_prereset,
+	.reset.prereset		= vt6420_prereset,
 	.bmdma_start		= vt6420_bmdma_start,
 };
 
@@ -139,7 +139,7 @@ static struct ata_port_operations vt6421_sata_ops = {
 
 static struct ata_port_operations vt8251_ops = {
 	.inherits		= &svia_base_ops,
-	.hardreset		= sata_std_hardreset,
+	.reset.hardreset	= sata_std_hardreset,
 	.scr_read		= vt8251_scr_read,
 	.scr_write		= vt8251_scr_write,
 };
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 7b4e7a61965a2..adb9e7a94785f 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -559,8 +559,8 @@ static int sas_ata_prereset(struct ata_link *link, unsigned long deadline)
 }
 
 static struct ata_port_operations sas_sata_ops = {
-	.prereset		= sas_ata_prereset,
-	.hardreset		= sas_ata_hard_reset,
+	.reset.prereset		= sas_ata_prereset,
+	.reset.hardreset	= sas_ata_hard_reset,
 	.error_handler		= ata_std_error_handler,
 	.post_internal_cmd	= sas_ata_post_internal,
 	.qc_defer               = ata_std_qc_defer,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 511dad024708a..c5ae2d98eb224 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -947,6 +947,13 @@ struct ata_port {
  */
 #define ATA_OP_NULL		(void *)(unsigned long)(-ENOENT)
 
+struct ata_reset_operations {
+	ata_prereset_fn_t	prereset;
+	ata_reset_fn_t		softreset;
+	ata_reset_fn_t		hardreset;
+	ata_postreset_fn_t	postreset;
+};
+
 struct ata_port_operations {
 	/*
 	 * Command execution
@@ -973,14 +980,8 @@ struct ata_port_operations {
 
 	void (*freeze)(struct ata_port *ap);
 	void (*thaw)(struct ata_port *ap);
-	ata_prereset_fn_t	prereset;
-	ata_reset_fn_t		softreset;
-	ata_reset_fn_t		hardreset;
-	ata_postreset_fn_t	postreset;
-	ata_prereset_fn_t	pmp_prereset;
-	ata_reset_fn_t		pmp_softreset;
-	ata_reset_fn_t		pmp_hardreset;
-	ata_postreset_fn_t	pmp_postreset;
+	struct ata_reset_operations reset;
+	struct ata_reset_operations pmp_reset;
 	void (*error_handler)(struct ata_port *ap);
 	void (*lost_interrupt)(struct ata_port *ap);
 	void (*post_internal_cmd)(struct ata_queued_cmd *qc);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6.12.y 4/5] ata: libata: Add an argument to ata_eh_reset()
  2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 2/5] ata: libata-eh: Remove ata_do_eh() Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 3/5] ata: libata-eh: Simplify reset operation management Sasha Levin
@ 2026-11-10 15:12   ` Sasha Levin
  2026-11-10 15:12   ` [PATCH 6.12.y 5/5] ata: sata_inic162x: remove dangerous broken driver Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-11-10 15:12 UTC (permalink / raw)
  To: stable; +Cc: Bart Van Assche, Niklas Cassel, Sasha Levin

From: Bart Van Assche <bvanassche@acm.org>

[ Upstream commit 4b3c2ca268b0a66093793466e02d8566d642f19c ]

Pass the ATA port pointer as first argument to ata_eh_reset(). No
functionality has been changed. This patch prepares for enabling lock
context analysis. Without this patch, lockdep_assert_held() statements
would have to be added before each ata_eh_reset() call because the
compiler doesn't know that ap->link.p == ap. See also ata_link_init().

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Stable-dep-of: 96fdeb7e3fd8 ("ata: sata_inic162x: remove dangerous broken driver")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/ata/libata-eh.c  | 6 +++---
 drivers/ata/libata-pmp.c | 2 +-
 drivers/ata/libata.h     | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 366b7d2a10e5d..b78aa5371c14c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2632,10 +2632,9 @@ static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)
 	return 0;
 }
 
-int ata_eh_reset(struct ata_link *link, int classify,
+int ata_eh_reset(struct ata_port *ap, struct ata_link *link, int classify,
 		 struct ata_reset_operations *reset_ops)
 {
-	struct ata_port *ap = link->ap;
 	struct ata_link *slave = ap->slave_link;
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
@@ -3817,7 +3816,8 @@ int ata_eh_recover(struct ata_port *ap, struct ata_reset_operations *reset_ops,
 		if (!(ehc->i.action & ATA_EH_RESET))
 			continue;
 
-		rc = ata_eh_reset(link, ata_link_nr_vacant(link), reset_ops);
+		rc = ata_eh_reset(ap, link, ata_link_nr_vacant(link),
+				  reset_ops);
 		if (rc) {
 			ata_link_err(link, "reset failed, giving up\n");
 			goto out;
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 99c67dbfb7536..c3b3af28d17c9 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -796,7 +796,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 		struct ata_link *tlink;
 
 		/* reset */
-		rc = ata_eh_reset(link, 0, reset_ops);
+		rc = ata_eh_reset(ap, link, 0, reset_ops);
 		if (rc) {
 			ata_link_err(link, "failed to reset PMP, giving up\n");
 			goto fail;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 0a5f9a4fa906f..f98a3eb5d51e0 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -196,8 +196,8 @@ extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
 extern void ata_eh_autopsy(struct ata_port *ap);
 const char *ata_get_cmd_name(u8 command);
 extern void ata_eh_report(struct ata_port *ap);
-extern int ata_eh_reset(struct ata_link *link, int classify,
-			struct ata_reset_operations *reset_ops);
+extern int ata_eh_reset(struct ata_port *ap, struct ata_link *link,
+			int classify, struct ata_reset_operations *reset_ops);
 extern int ata_eh_recover(struct ata_port *ap,
 			  struct ata_reset_operations *reset_ops,
 			  struct ata_link **r_failed_disk);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6.12.y 5/5] ata: sata_inic162x: remove dangerous broken driver
  2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
                     ` (2 preceding siblings ...)
  2026-11-10 15:12   ` [PATCH 6.12.y 4/5] ata: libata: Add an argument to ata_eh_reset() Sasha Levin
@ 2026-11-10 15:12   ` Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-11-10 15:12 UTC (permalink / raw)
  To: stable; +Cc: Ethan Nelson-Moore, Damien Le Moal, Niklas Cassel, Sasha Levin

From: Ethan Nelson-Moore <enelsonmoore@gmail.com>

[ Upstream commit 96fdeb7e3fd8d937f8351ed90824c9d904e590a1 ]

The sata_inic162x driver was labeled as "very experimental" in
commit bb9696192826 ("libata: make it clear that sata_inic162x is
experimental") due to data corruption issues, but not marked as broken.
Since then, no changes have been made to it that could fix these
issues. Since the driver was not marked as broken, and the message
about potential data corruption is only visible in the code and dmesg,
it is possible that someone could enable the driver without realizing
its potential for data corruption. Remove the driver to protect users'
data.

Fixes: 1fd7a697a37b ("sata_inic162x: finally, driver for initio 162x SATA controllers, take #2")
Cc: stable@vger.kernel.org
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20260915014714.41274-1-enelsonmoore@gmail.com
Signed-off-by: Niklas Cassel <cassel@kernel.org>
[ sashal: adjusted driver deletion for the missing __must_hold annotation on inic_error_handler() ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/ata/Kconfig         |   7 -
 drivers/ata/Makefile        |   1 -
 drivers/ata/sata_inic162x.c | 902 ------------------------------------
 3 files changed, 910 deletions(-)
 delete mode 100644 drivers/ata/sata_inic162x.c

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 120a2b7067fc7..ff81f707d0b23 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -329,13 +329,6 @@ config SATA_AHCI_SEATTLE
 
 	 If unsure, say N
 
-config SATA_INIC162X
-	tristate "Initio 162x SATA support (Very Experimental)"
-	depends on PCI
-	select SATA_HOST
-	help
-	  This option enables support for Initio 162x Serial ATA.
-
 config SATA_ACARD_AHCI
 	tristate "ACard AHCI variant (ATP 8620)"
 	depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 20e6645ab7371..81e04e96b807e 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_SATA_AHCI_SEATTLE)	+= ahci_seattle.o libahci.o libahci_platform.o
 obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
 obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
 obj-$(CONFIG_SATA_GEMINI)	+= sata_gemini.o
-obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
 obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
deleted file mode 100644
index 46a8c20daf180..0000000000000
--- a/drivers/ata/sata_inic162x.c
+++ /dev/null
@@ -1,902 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * sata_inic162x.c - Driver for Initio 162x SATA controllers
- *
- * Copyright 2006  SUSE Linux Products GmbH
- * Copyright 2006  Tejun Heo <teheo@novell.com>
- *
- * **** WARNING ****
- *
- * This driver never worked properly and unfortunately data corruption is
- * relatively common.  There isn't anyone working on the driver and there's
- * no support from the vendor.  Do not use this driver in any production
- * environment.
- *
- * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491
- * https://bugzilla.kernel.org/show_bug.cgi?id=60565
- *
- * *****************
- *
- * This controller is eccentric and easily locks up if something isn't
- * right.  Documentation is available at initio's website but it only
- * documents registers (not programming model).
- *
- * This driver has interesting history.  The first version was written
- * from the documentation and a 2.4 IDE driver posted on a Taiwan
- * company, which didn't use any IDMA features and couldn't handle
- * LBA48.  The resulting driver couldn't handle LBA48 devices either
- * making it pretty useless.
- *
- * After a while, initio picked the driver up, renamed it to
- * sata_initio162x, updated it to use IDMA for ATA DMA commands and
- * posted it on their website.  It only used ATA_PROT_DMA for IDMA and
- * attaching both devices and issuing IDMA and !IDMA commands
- * simultaneously broke it due to PIRQ masking interaction but it did
- * show how to use the IDMA (ADMA + some initio specific twists)
- * engine.
- *
- * Then, I picked up their changes again and here's the usable driver
- * which uses IDMA for everything.  Everything works now including
- * LBA48, CD/DVD burning, suspend/resume and hotplug.  There are some
- * issues tho.  Result Tf is not resported properly, NCQ isn't
- * supported yet and CD/DVD writing works with DMA assisted PIO
- * protocol (which, for native SATA devices, shouldn't cause any
- * noticeable difference).
- *
- * Anyways, so, here's finally a working driver for inic162x.  Enjoy!
- *
- * initio: If you guys wanna improve the driver regarding result TF
- * access and other stuff, please feel free to contact me.  I'll be
- * happy to assist.
- */
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/blkdev.h>
-#include <scsi/scsi_device.h>
-
-#define DRV_NAME	"sata_inic162x"
-#define DRV_VERSION	"0.4"
-
-enum {
-	MMIO_BAR_PCI		= 5,
-	MMIO_BAR_CARDBUS	= 1,
-
-	NR_PORTS		= 2,
-
-	IDMA_CPB_TBL_SIZE	= 4 * 32,
-
-	INIC_DMA_BOUNDARY	= 0xffffff,
-
-	HOST_ACTRL		= 0x08,
-	HOST_CTL		= 0x7c,
-	HOST_STAT		= 0x7e,
-	HOST_IRQ_STAT		= 0xbc,
-	HOST_IRQ_MASK		= 0xbe,
-
-	PORT_SIZE		= 0x40,
-
-	/* registers for ATA TF operation */
-	PORT_TF_DATA		= 0x00,
-	PORT_TF_FEATURE		= 0x01,
-	PORT_TF_NSECT		= 0x02,
-	PORT_TF_LBAL		= 0x03,
-	PORT_TF_LBAM		= 0x04,
-	PORT_TF_LBAH		= 0x05,
-	PORT_TF_DEVICE		= 0x06,
-	PORT_TF_COMMAND		= 0x07,
-	PORT_TF_ALT_STAT	= 0x08,
-	PORT_IRQ_STAT		= 0x09,
-	PORT_IRQ_MASK		= 0x0a,
-	PORT_PRD_CTL		= 0x0b,
-	PORT_PRD_ADDR		= 0x0c,
-	PORT_PRD_XFERLEN	= 0x10,
-	PORT_CPB_CPBLAR		= 0x18,
-	PORT_CPB_PTQFIFO	= 0x1c,
-
-	/* IDMA register */
-	PORT_IDMA_CTL		= 0x14,
-	PORT_IDMA_STAT		= 0x16,
-
-	PORT_RPQ_FIFO		= 0x1e,
-	PORT_RPQ_CNT		= 0x1f,
-
-	PORT_SCR		= 0x20,
-
-	/* HOST_CTL bits */
-	HCTL_LEDEN		= (1 << 3),  /* enable LED operation */
-	HCTL_IRQOFF		= (1 << 8),  /* global IRQ off */
-	HCTL_FTHD0		= (1 << 10), /* fifo threshold 0 */
-	HCTL_FTHD1		= (1 << 11), /* fifo threshold 1*/
-	HCTL_PWRDWN		= (1 << 12), /* power down PHYs */
-	HCTL_SOFTRST		= (1 << 13), /* global reset (no phy reset) */
-	HCTL_RPGSEL		= (1 << 15), /* register page select */
-
-	HCTL_KNOWN_BITS		= HCTL_IRQOFF | HCTL_PWRDWN | HCTL_SOFTRST |
-				  HCTL_RPGSEL,
-
-	/* HOST_IRQ_(STAT|MASK) bits */
-	HIRQ_PORT0		= (1 << 0),
-	HIRQ_PORT1		= (1 << 1),
-	HIRQ_SOFT		= (1 << 14),
-	HIRQ_GLOBAL		= (1 << 15), /* STAT only */
-
-	/* PORT_IRQ_(STAT|MASK) bits */
-	PIRQ_OFFLINE		= (1 << 0),  /* device unplugged */
-	PIRQ_ONLINE		= (1 << 1),  /* device plugged */
-	PIRQ_COMPLETE		= (1 << 2),  /* completion interrupt */
-	PIRQ_FATAL		= (1 << 3),  /* fatal error */
-	PIRQ_ATA		= (1 << 4),  /* ATA interrupt */
-	PIRQ_REPLY		= (1 << 5),  /* reply FIFO not empty */
-	PIRQ_PENDING		= (1 << 7),  /* port IRQ pending (STAT only) */
-
-	PIRQ_ERR		= PIRQ_OFFLINE | PIRQ_ONLINE | PIRQ_FATAL,
-	PIRQ_MASK_DEFAULT	= PIRQ_REPLY | PIRQ_ATA,
-	PIRQ_MASK_FREEZE	= 0xff,
-
-	/* PORT_PRD_CTL bits */
-	PRD_CTL_START		= (1 << 0),
-	PRD_CTL_WR		= (1 << 3),
-	PRD_CTL_DMAEN		= (1 << 7),  /* DMA enable */
-
-	/* PORT_IDMA_CTL bits */
-	IDMA_CTL_RST_ATA	= (1 << 2),  /* hardreset ATA bus */
-	IDMA_CTL_RST_IDMA	= (1 << 5),  /* reset IDMA machinery */
-	IDMA_CTL_GO		= (1 << 7),  /* IDMA mode go */
-	IDMA_CTL_ATA_NIEN	= (1 << 8),  /* ATA IRQ disable */
-
-	/* PORT_IDMA_STAT bits */
-	IDMA_STAT_PERR		= (1 << 0),  /* PCI ERROR MODE */
-	IDMA_STAT_CPBERR	= (1 << 1),  /* ADMA CPB error */
-	IDMA_STAT_LGCY		= (1 << 3),  /* ADMA legacy */
-	IDMA_STAT_UIRQ		= (1 << 4),  /* ADMA unsolicited irq */
-	IDMA_STAT_STPD		= (1 << 5),  /* ADMA stopped */
-	IDMA_STAT_PSD		= (1 << 6),  /* ADMA pause */
-	IDMA_STAT_DONE		= (1 << 7),  /* ADMA done */
-
-	IDMA_STAT_ERR		= IDMA_STAT_PERR | IDMA_STAT_CPBERR,
-
-	/* CPB Control Flags*/
-	CPB_CTL_VALID		= (1 << 0),  /* CPB valid */
-	CPB_CTL_QUEUED		= (1 << 1),  /* queued command */
-	CPB_CTL_DATA		= (1 << 2),  /* data, rsvd in datasheet */
-	CPB_CTL_IEN		= (1 << 3),  /* PCI interrupt enable */
-	CPB_CTL_DEVDIR		= (1 << 4),  /* device direction control */
-
-	/* CPB Response Flags */
-	CPB_RESP_DONE		= (1 << 0),  /* ATA command complete */
-	CPB_RESP_REL		= (1 << 1),  /* ATA release */
-	CPB_RESP_IGNORED	= (1 << 2),  /* CPB ignored */
-	CPB_RESP_ATA_ERR	= (1 << 3),  /* ATA command error */
-	CPB_RESP_SPURIOUS	= (1 << 4),  /* ATA spurious interrupt error */
-	CPB_RESP_UNDERFLOW	= (1 << 5),  /* APRD deficiency length error */
-	CPB_RESP_OVERFLOW	= (1 << 6),  /* APRD exccess length error */
-	CPB_RESP_CPB_ERR	= (1 << 7),  /* CPB error flag */
-
-	/* PRD Control Flags */
-	PRD_DRAIN		= (1 << 1),  /* ignore data excess */
-	PRD_CDB			= (1 << 2),  /* atapi packet command pointer */
-	PRD_DIRECT_INTR		= (1 << 3),  /* direct interrupt */
-	PRD_DMA			= (1 << 4),  /* data transfer method */
-	PRD_WRITE		= (1 << 5),  /* data dir, rsvd in datasheet */
-	PRD_IOM			= (1 << 6),  /* io/memory transfer */
-	PRD_END			= (1 << 7),  /* APRD chain end */
-};
-
-/* Comman Parameter Block */
-struct inic_cpb {
-	u8		resp_flags;	/* Response Flags */
-	u8		error;		/* ATA Error */
-	u8		status;		/* ATA Status */
-	u8		ctl_flags;	/* Control Flags */
-	__le32		len;		/* Total Transfer Length */
-	__le32		prd;		/* First PRD pointer */
-	u8		rsvd[4];
-	/* 16 bytes */
-	u8		feature;	/* ATA Feature */
-	u8		hob_feature;	/* ATA Ex. Feature */
-	u8		device;		/* ATA Device/Head */
-	u8		mirctl;		/* Mirror Control */
-	u8		nsect;		/* ATA Sector Count */
-	u8		hob_nsect;	/* ATA Ex. Sector Count */
-	u8		lbal;		/* ATA Sector Number */
-	u8		hob_lbal;	/* ATA Ex. Sector Number */
-	u8		lbam;		/* ATA Cylinder Low */
-	u8		hob_lbam;	/* ATA Ex. Cylinder Low */
-	u8		lbah;		/* ATA Cylinder High */
-	u8		hob_lbah;	/* ATA Ex. Cylinder High */
-	u8		command;	/* ATA Command */
-	u8		ctl;		/* ATA Control */
-	u8		slave_error;	/* Slave ATA Error */
-	u8		slave_status;	/* Slave ATA Status */
-	/* 32 bytes */
-} __packed;
-
-/* Physical Region Descriptor */
-struct inic_prd {
-	__le32		mad;		/* Physical Memory Address */
-	__le16		len;		/* Transfer Length */
-	u8		rsvd;
-	u8		flags;		/* Control Flags */
-} __packed;
-
-struct inic_pkt {
-	struct inic_cpb	cpb;
-	struct inic_prd	prd[LIBATA_MAX_PRD + 1];	/* + 1 for cdb */
-	u8		cdb[ATAPI_CDB_LEN];
-} __packed;
-
-struct inic_host_priv {
-	void __iomem	*mmio_base;
-	u16		cached_hctl;
-};
-
-struct inic_port_priv {
-	struct inic_pkt	*pkt;
-	dma_addr_t	pkt_dma;
-	u32		*cpb_tbl;
-	dma_addr_t	cpb_tbl_dma;
-};
-
-static const struct scsi_host_template inic_sht = {
-	ATA_BASE_SHT(DRV_NAME),
-	.sg_tablesize		= LIBATA_MAX_PRD, /* maybe it can be larger? */
-
-	/*
-	 * This controller is braindamaged.  dma_boundary is 0xffff like others
-	 * but it will lock up the whole machine HARD if 65536 byte PRD entry
-	 * is fed.  Reduce maximum segment size.
-	 */
-	.dma_boundary		= INIC_DMA_BOUNDARY,
-	.max_segment_size	= 65536 - 512,
-};
-
-static const int scr_map[] = {
-	[SCR_STATUS]	= 0,
-	[SCR_ERROR]	= 1,
-	[SCR_CONTROL]	= 2,
-};
-
-static void __iomem *inic_port_base(struct ata_port *ap)
-{
-	struct inic_host_priv *hpriv = ap->host->private_data;
-
-	return hpriv->mmio_base + ap->port_no * PORT_SIZE;
-}
-
-static void inic_reset_port(void __iomem *port_base)
-{
-	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
-
-	/* stop IDMA engine */
-	readw(idma_ctl); /* flush */
-	msleep(1);
-
-	/* mask IRQ and assert reset */
-	writew(IDMA_CTL_RST_IDMA, idma_ctl);
-	readw(idma_ctl); /* flush */
-	msleep(1);
-
-	/* release reset */
-	writew(0, idma_ctl);
-
-	/* clear irq */
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-}
-
-static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
-{
-	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-
-	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
-		return -EINVAL;
-
-	*val = readl(scr_addr + scr_map[sc_reg] * 4);
-
-	/* this controller has stuck DIAG.N, ignore it */
-	if (sc_reg == SCR_ERROR)
-		*val &= ~SERR_PHYRDY_CHG;
-	return 0;
-}
-
-static int inic_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
-{
-	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-
-	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
-		return -EINVAL;
-
-	writel(val, scr_addr + scr_map[sc_reg] * 4);
-	return 0;
-}
-
-static void inic_stop_idma(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	readb(port_base + PORT_RPQ_FIFO);
-	readb(port_base + PORT_RPQ_CNT);
-	writew(0, port_base + PORT_IDMA_CTL);
-}
-
-static void inic_host_err_intr(struct ata_port *ap, u8 irq_stat, u16 idma_stat)
-{
-	struct ata_eh_info *ehi = &ap->link.eh_info;
-	struct inic_port_priv *pp = ap->private_data;
-	struct inic_cpb *cpb = &pp->pkt->cpb;
-	bool freeze = false;
-
-	ata_ehi_clear_desc(ehi);
-	ata_ehi_push_desc(ehi, "irq_stat=0x%x idma_stat=0x%x",
-			  irq_stat, idma_stat);
-
-	inic_stop_idma(ap);
-
-	if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
-		ata_ehi_push_desc(ehi, "hotplug");
-		ata_ehi_hotplugged(ehi);
-		freeze = true;
-	}
-
-	if (idma_stat & IDMA_STAT_PERR) {
-		ata_ehi_push_desc(ehi, "PCI error");
-		freeze = true;
-	}
-
-	if (idma_stat & IDMA_STAT_CPBERR) {
-		ata_ehi_push_desc(ehi, "CPB error");
-
-		if (cpb->resp_flags & CPB_RESP_IGNORED) {
-			__ata_ehi_push_desc(ehi, " ignored");
-			ehi->err_mask |= AC_ERR_INVALID;
-			freeze = true;
-		}
-
-		if (cpb->resp_flags & CPB_RESP_ATA_ERR)
-			ehi->err_mask |= AC_ERR_DEV;
-
-		if (cpb->resp_flags & CPB_RESP_SPURIOUS) {
-			__ata_ehi_push_desc(ehi, " spurious-intr");
-			ehi->err_mask |= AC_ERR_HSM;
-			freeze = true;
-		}
-
-		if (cpb->resp_flags &
-		    (CPB_RESP_UNDERFLOW | CPB_RESP_OVERFLOW)) {
-			__ata_ehi_push_desc(ehi, " data-over/underflow");
-			ehi->err_mask |= AC_ERR_HSM;
-			freeze = true;
-		}
-	}
-
-	if (freeze)
-		ata_port_freeze(ap);
-	else
-		ata_port_abort(ap);
-}
-
-static void inic_host_intr(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
-	u8 irq_stat;
-	u16 idma_stat;
-
-	/* read and clear IRQ status */
-	irq_stat = readb(port_base + PORT_IRQ_STAT);
-	writeb(irq_stat, port_base + PORT_IRQ_STAT);
-	idma_stat = readw(port_base + PORT_IDMA_STAT);
-
-	if (unlikely((irq_stat & PIRQ_ERR) || (idma_stat & IDMA_STAT_ERR)))
-		inic_host_err_intr(ap, irq_stat, idma_stat);
-
-	if (unlikely(!qc))
-		goto spurious;
-
-	if (likely(idma_stat & IDMA_STAT_DONE)) {
-		inic_stop_idma(ap);
-
-		/* Depending on circumstances, device error
-		 * isn't reported by IDMA, check it explicitly.
-		 */
-		if (unlikely(readb(port_base + PORT_TF_COMMAND) &
-			     (ATA_DF | ATA_ERR)))
-			qc->err_mask |= AC_ERR_DEV;
-
-		ata_qc_complete(qc);
-		return;
-	}
-
- spurious:
-	ata_port_warn(ap, "unhandled interrupt: cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
-		      qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
-}
-
-static irqreturn_t inic_interrupt(int irq, void *dev_instance)
-{
-	struct ata_host *host = dev_instance;
-	struct inic_host_priv *hpriv = host->private_data;
-	u16 host_irq_stat;
-	int i, handled = 0;
-
-	host_irq_stat = readw(hpriv->mmio_base + HOST_IRQ_STAT);
-
-	if (unlikely(!(host_irq_stat & HIRQ_GLOBAL)))
-		goto out;
-
-	spin_lock(&host->lock);
-
-	for (i = 0; i < NR_PORTS; i++)
-		if (host_irq_stat & (HIRQ_PORT0 << i)) {
-			inic_host_intr(host->ports[i]);
-			handled++;
-		}
-
-	spin_unlock(&host->lock);
-
- out:
-	return IRQ_RETVAL(handled);
-}
-
-static int inic_check_atapi_dma(struct ata_queued_cmd *qc)
-{
-	/* For some reason ATAPI_PROT_DMA doesn't work for some
-	 * commands including writes and other misc ops.  Use PIO
-	 * protocol instead, which BTW is driven by the DMA engine
-	 * anyway, so it shouldn't make much difference for native
-	 * SATA devices.
-	 */
-	if (atapi_cmd_type(qc->cdb[0]) == READ)
-		return 0;
-	return 1;
-}
-
-static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc)
-{
-	struct scatterlist *sg;
-	unsigned int si;
-	u8 flags = 0;
-
-	if (qc->tf.flags & ATA_TFLAG_WRITE)
-		flags |= PRD_WRITE;
-
-	if (ata_is_dma(qc->tf.protocol))
-		flags |= PRD_DMA;
-
-	for_each_sg(qc->sg, sg, qc->n_elem, si) {
-		prd->mad = cpu_to_le32(sg_dma_address(sg));
-		prd->len = cpu_to_le16(sg_dma_len(sg));
-		prd->flags = flags;
-		prd++;
-	}
-
-	WARN_ON(!si);
-	prd[-1].flags |= PRD_END;
-}
-
-static enum ata_completion_errors inic_qc_prep(struct ata_queued_cmd *qc)
-{
-	struct inic_port_priv *pp = qc->ap->private_data;
-	struct inic_pkt *pkt = pp->pkt;
-	struct inic_cpb *cpb = &pkt->cpb;
-	struct inic_prd *prd = pkt->prd;
-	bool is_atapi = ata_is_atapi(qc->tf.protocol);
-	bool is_data = ata_is_data(qc->tf.protocol);
-	unsigned int cdb_len = 0;
-
-	if (is_atapi)
-		cdb_len = qc->dev->cdb_len;
-
-	/* prepare packet, based on initio driver */
-	memset(pkt, 0, sizeof(struct inic_pkt));
-
-	cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN;
-	if (is_atapi || is_data)
-		cpb->ctl_flags |= CPB_CTL_DATA;
-
-	cpb->len = cpu_to_le32(qc->nbytes + cdb_len);
-	cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd));
-
-	cpb->device = qc->tf.device;
-	cpb->feature = qc->tf.feature;
-	cpb->nsect = qc->tf.nsect;
-	cpb->lbal = qc->tf.lbal;
-	cpb->lbam = qc->tf.lbam;
-	cpb->lbah = qc->tf.lbah;
-
-	if (qc->tf.flags & ATA_TFLAG_LBA48) {
-		cpb->hob_feature = qc->tf.hob_feature;
-		cpb->hob_nsect = qc->tf.hob_nsect;
-		cpb->hob_lbal = qc->tf.hob_lbal;
-		cpb->hob_lbam = qc->tf.hob_lbam;
-		cpb->hob_lbah = qc->tf.hob_lbah;
-	}
-
-	cpb->command = qc->tf.command;
-	/* don't load ctl - dunno why.  it's like that in the initio driver */
-
-	/* setup PRD for CDB */
-	if (is_atapi) {
-		memcpy(pkt->cdb, qc->cdb, ATAPI_CDB_LEN);
-		prd->mad = cpu_to_le32(pp->pkt_dma +
-				       offsetof(struct inic_pkt, cdb));
-		prd->len = cpu_to_le16(cdb_len);
-		prd->flags = PRD_CDB | PRD_WRITE;
-		if (!is_data)
-			prd->flags |= PRD_END;
-		prd++;
-	}
-
-	/* setup sg table */
-	if (is_data)
-		inic_fill_sg(prd, qc);
-
-	pp->cpb_tbl[0] = pp->pkt_dma;
-
-	return AC_ERR_OK;
-}
-
-static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	void __iomem *port_base = inic_port_base(ap);
-
-	/* fire up the ADMA engine */
-	writew(HCTL_FTHD0 | HCTL_LEDEN, port_base + HOST_CTL);
-	writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
-	writeb(0, port_base + PORT_CPB_PTQFIFO);
-
-	return 0;
-}
-
-static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	tf->error	= readb(port_base + PORT_TF_FEATURE);
-	tf->nsect	= readb(port_base + PORT_TF_NSECT);
-	tf->lbal	= readb(port_base + PORT_TF_LBAL);
-	tf->lbam	= readb(port_base + PORT_TF_LBAM);
-	tf->lbah	= readb(port_base + PORT_TF_LBAH);
-	tf->device	= readb(port_base + PORT_TF_DEVICE);
-	tf->status	= readb(port_base + PORT_TF_COMMAND);
-}
-
-static void inic_qc_fill_rtf(struct ata_queued_cmd *qc)
-{
-	struct ata_taskfile *rtf = &qc->result_tf;
-	struct ata_taskfile tf;
-
-	/* FIXME: Except for status and error, result TF access
-	 * doesn't work.  I tried reading from BAR0/2, CPB and BAR5.
-	 * None works regardless of which command interface is used.
-	 * For now return true iff status indicates device error.
-	 * This means that we're reporting bogus sector for RW
-	 * failures.  Eeekk....
-	 */
-	inic_tf_read(qc->ap, &tf);
-
-	if (tf.status & ATA_ERR) {
-		rtf->status = tf.status;
-		rtf->error = tf.error;
-	}
-}
-
-static void inic_freeze(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	writeb(PIRQ_MASK_FREEZE, port_base + PORT_IRQ_MASK);
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-}
-
-static void inic_thaw(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	writeb(0xff, port_base + PORT_IRQ_STAT);
-	writeb(PIRQ_MASK_DEFAULT, port_base + PORT_IRQ_MASK);
-}
-
-static int inic_check_ready(struct ata_link *link)
-{
-	void __iomem *port_base = inic_port_base(link->ap);
-
-	return ata_check_ready(readb(port_base + PORT_TF_COMMAND));
-}
-
-/*
- * SRST and SControl hardreset don't give valid signature on this
- * controller.  Only controller specific hardreset mechanism works.
- */
-static int inic_hardreset(struct ata_link *link, unsigned int *class,
-			  unsigned long deadline)
-{
-	struct ata_port *ap = link->ap;
-	void __iomem *port_base = inic_port_base(ap);
-	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
-	const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context);
-	int rc;
-
-	/* hammer it into sane state */
-	inic_reset_port(port_base);
-
-	writew(IDMA_CTL_RST_ATA, idma_ctl);
-	readw(idma_ctl);	/* flush */
-	ata_msleep(ap, 1);
-	writew(0, idma_ctl);
-
-	rc = sata_link_resume(link, timing, deadline);
-	if (rc) {
-		ata_link_warn(link,
-			      "failed to resume link after reset (errno=%d)\n",
-			      rc);
-		return rc;
-	}
-
-	*class = ATA_DEV_NONE;
-	if (ata_link_online(link)) {
-		struct ata_taskfile tf;
-
-		/* wait for link to become ready */
-		rc = ata_wait_after_reset(link, deadline, inic_check_ready);
-		/* link occupied, -ENODEV too is an error */
-		if (rc) {
-			ata_link_warn(link,
-				      "device not ready after hardreset (errno=%d)\n",
-				      rc);
-			return rc;
-		}
-
-		inic_tf_read(ap, &tf);
-		*class = ata_port_classify(ap, &tf);
-	}
-
-	return 0;
-}
-
-static void inic_error_handler(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-
-	inic_reset_port(port_base);
-	ata_std_error_handler(ap);
-}
-
-static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-	/* make DMA engine forget about the failed command */
-	if (qc->flags & ATA_QCFLAG_EH)
-		inic_reset_port(inic_port_base(qc->ap));
-}
-
-static void init_port(struct ata_port *ap)
-{
-	void __iomem *port_base = inic_port_base(ap);
-	struct inic_port_priv *pp = ap->private_data;
-
-	/* clear packet and CPB table */
-	memset(pp->pkt, 0, sizeof(struct inic_pkt));
-	memset(pp->cpb_tbl, 0, IDMA_CPB_TBL_SIZE);
-
-	/* setup CPB lookup table addresses */
-	writel(pp->cpb_tbl_dma, port_base + PORT_CPB_CPBLAR);
-}
-
-static int inic_port_resume(struct ata_port *ap)
-{
-	init_port(ap);
-	return 0;
-}
-
-static int inic_port_start(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct inic_port_priv *pp;
-
-	/* alloc and initialize private data */
-	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
-	if (!pp)
-		return -ENOMEM;
-	ap->private_data = pp;
-
-	/* Alloc resources */
-	pp->pkt = dmam_alloc_coherent(dev, sizeof(struct inic_pkt),
-				      &pp->pkt_dma, GFP_KERNEL);
-	if (!pp->pkt)
-		return -ENOMEM;
-
-	pp->cpb_tbl = dmam_alloc_coherent(dev, IDMA_CPB_TBL_SIZE,
-					  &pp->cpb_tbl_dma, GFP_KERNEL);
-	if (!pp->cpb_tbl)
-		return -ENOMEM;
-
-	init_port(ap);
-
-	return 0;
-}
-
-static struct ata_port_operations inic_port_ops = {
-	.inherits		= &sata_port_ops,
-
-	.check_atapi_dma	= inic_check_atapi_dma,
-	.qc_prep		= inic_qc_prep,
-	.qc_issue		= inic_qc_issue,
-	.qc_fill_rtf		= inic_qc_fill_rtf,
-
-	.freeze			= inic_freeze,
-	.thaw			= inic_thaw,
-	.reset.hardreset	= inic_hardreset,
-	.error_handler		= inic_error_handler,
-	.post_internal_cmd	= inic_post_internal_cmd,
-
-	.scr_read		= inic_scr_read,
-	.scr_write		= inic_scr_write,
-
-	.port_resume		= inic_port_resume,
-	.port_start		= inic_port_start,
-};
-
-static const struct ata_port_info inic_port_info = {
-	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
-	.pio_mask		= ATA_PIO4,
-	.mwdma_mask		= ATA_MWDMA2,
-	.udma_mask		= ATA_UDMA6,
-	.port_ops		= &inic_port_ops
-};
-
-static int init_controller(void __iomem *mmio_base, u16 hctl)
-{
-	int i;
-	u16 val;
-
-	hctl &= ~HCTL_KNOWN_BITS;
-
-	/* Soft reset whole controller.  Spec says reset duration is 3
-	 * PCI clocks, be generous and give it 10ms.
-	 */
-	writew(hctl | HCTL_SOFTRST, mmio_base + HOST_CTL);
-	readw(mmio_base + HOST_CTL); /* flush */
-
-	for (i = 0; i < 10; i++) {
-		msleep(1);
-		val = readw(mmio_base + HOST_CTL);
-		if (!(val & HCTL_SOFTRST))
-			break;
-	}
-
-	if (val & HCTL_SOFTRST)
-		return -EIO;
-
-	/* mask all interrupts and reset ports */
-	for (i = 0; i < NR_PORTS; i++) {
-		void __iomem *port_base = mmio_base + i * PORT_SIZE;
-
-		writeb(0xff, port_base + PORT_IRQ_MASK);
-		inic_reset_port(port_base);
-	}
-
-	/* port IRQ is masked now, unmask global IRQ */
-	writew(hctl & ~HCTL_IRQOFF, mmio_base + HOST_CTL);
-	val = readw(mmio_base + HOST_IRQ_MASK);
-	val &= ~(HIRQ_PORT0 | HIRQ_PORT1);
-	writew(val, mmio_base + HOST_IRQ_MASK);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int inic_pci_device_resume(struct pci_dev *pdev)
-{
-	struct ata_host *host = pci_get_drvdata(pdev);
-	struct inic_host_priv *hpriv = host->private_data;
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
-		if (rc)
-			return rc;
-	}
-
-	ata_host_resume(host);
-
-	return 0;
-}
-#endif
-
-static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	const struct ata_port_info *ppi[] = { &inic_port_info, NULL };
-	struct ata_host *host;
-	struct inic_host_priv *hpriv;
-	void __iomem * const *iomap;
-	int mmio_bar;
-	int i, rc;
-
-	ata_print_version_once(&pdev->dev, DRV_VERSION);
-
-	dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n");
-
-	/* alloc host */
-	host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
-	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
-	if (!host || !hpriv)
-		return -ENOMEM;
-
-	host->private_data = hpriv;
-
-	/* Acquire resources and fill host.  Note that PCI and cardbus
-	 * use different BARs.
-	 */
-	rc = pcim_enable_device(pdev);
-	if (rc)
-		return rc;
-
-	if (pci_resource_flags(pdev, MMIO_BAR_PCI) & IORESOURCE_MEM)
-		mmio_bar = MMIO_BAR_PCI;
-	else
-		mmio_bar = MMIO_BAR_CARDBUS;
-
-	rc = pcim_iomap_regions(pdev, 1 << mmio_bar, DRV_NAME);
-	if (rc)
-		return rc;
-	host->iomap = iomap = pcim_iomap_table(pdev);
-	hpriv->mmio_base = iomap[mmio_bar];
-	hpriv->cached_hctl = readw(hpriv->mmio_base + HOST_CTL);
-
-	for (i = 0; i < NR_PORTS; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		ata_port_pbar_desc(ap, mmio_bar, -1, "mmio");
-		ata_port_pbar_desc(ap, mmio_bar, i * PORT_SIZE, "port");
-	}
-
-	/* Set dma_mask.  This devices doesn't support 64bit addressing. */
-	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
-	if (rc) {
-		dev_err(&pdev->dev, "32-bit DMA enable failed\n");
-		return rc;
-	}
-
-	rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to initialize controller\n");
-		return rc;
-	}
-
-	pci_set_master(pdev);
-	return ata_host_activate(host, pdev->irq, inic_interrupt, IRQF_SHARED,
-				 &inic_sht);
-}
-
-static const struct pci_device_id inic_pci_tbl[] = {
-	{ PCI_VDEVICE(INIT, 0x1622), },
-	{ },
-};
-
-static struct pci_driver inic_pci_driver = {
-	.name 		= DRV_NAME,
-	.id_table	= inic_pci_tbl,
-#ifdef CONFIG_PM_SLEEP
-	.suspend	= ata_pci_device_suspend,
-	.resume		= inic_pci_device_resume,
-#endif
-	.probe 		= inic_init_one,
-	.remove		= ata_pci_remove_one,
-};
-
-module_pci_driver(inic_pci_driver);
-
-MODULE_AUTHOR("Tejun Heo");
-MODULE_DESCRIPTION("low-level driver for Initio 162x SATA");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(pci, inic_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-10 15:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:17 FAILED: patch "[PATCH] ata: sata_inic162x: remove dangerous broken driver" failed to apply to 6.12-stable tree Sasha Levin
2026-11-10 15:12 ` [PATCH 6.12.y 1/5] ata: libata-eh: Rename and make ata_set_mode() static Sasha Levin
2026-11-10 15:12   ` [PATCH 6.12.y 2/5] ata: libata-eh: Remove ata_do_eh() Sasha Levin
2026-11-10 15:12   ` [PATCH 6.12.y 3/5] ata: libata-eh: Simplify reset operation management Sasha Levin
2026-11-10 15:12   ` [PATCH 6.12.y 4/5] ata: libata: Add an argument to ata_eh_reset() Sasha Levin
2026-11-10 15:12   ` [PATCH 6.12.y 5/5] ata: sata_inic162x: remove dangerous broken driver Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox