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

Commit b3e5838a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata fixes from Tejun Heo:
 "Rather big for fixes pull.

   - SCC controllers never lived to see the light of the day.  Both
     libata and ide drivers removed.

   - In some configurations, link power management policy changes
     sometimes cause delayed spurious PHY events which can develop into
     noticeable failures.  This has been reported several times over the
     years.  Gabriele's patches suppress PHY events for a while after
     LPM policy changes which should help most of these failures without
     causing too much problem for hotplug use cases.

   - A few controller specific fixes"

[ Hmm.  I don't think removing SSC support is really a "fix", but hey, it
  removes a lot of lines of code.  Which I like.  So ...  good riddance ]

* 'for-4.1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: avoton port-disable reset-quirk
  ata: select DW_DMAC in case of SATA_DWC
  libata: Blacklist queued TRIM on all Samsung 800-series
  libata: Ignore spurious PHY event on LPM policy change
  libata: Add helper to determine when PHY events should be ignored
  ata: ahci_st: fixup layering violations / drvdata errors
  Remove celleb-only SCC PATA drivers
parents c91aa67e dbfe8ef5
Loading
Loading
Loading
Loading
+1 −9
Original line number Diff line number Diff line
@@ -270,6 +270,7 @@ config ATA_PIIX
config SATA_DWC
	tristate "DesignWare Cores SATA support"
	depends on 460EX
	select DW_DMAC
	help
	  This option enables support for the on-chip SATA controller of the
	  AppliedMicro processor 460EX.
@@ -729,15 +730,6 @@ config PATA_SC1200

	  If unsure, say N.

config PATA_SCC
	tristate "Toshiba's Cell Reference Set IDE support"
	depends on PCI && PPC_CELLEB
	help
	  This option enables support for the built-in IDE controller on
	  Toshiba Cell Reference Board.

	  If unsure, say N.

config PATA_SCH
	tristate "Intel SCH PATA support"
	depends on PCI
+0 −1
Original line number Diff line number Diff line
@@ -75,7 +75,6 @@ obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
obj-$(CONFIG_PATA_RADISYS)	+= pata_radisys.o
obj-$(CONFIG_PATA_RDC)		+= pata_rdc.o
obj-$(CONFIG_PATA_SC1200)	+= pata_sc1200.o
obj-$(CONFIG_PATA_SCC)		+= pata_scc.o
obj-$(CONFIG_PATA_SCH)		+= pata_sch.o
obj-$(CONFIG_PATA_SERVERWORKS)	+= pata_serverworks.o
obj-$(CONFIG_PATA_SIL680)	+= pata_sil680.o
+95 −8
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ enum board_ids {
	board_ahci_yes_fbs,

	/* board IDs for specific chipsets in alphabetical order */
	board_ahci_avn,
	board_ahci_mcp65,
	board_ahci_mcp77,
	board_ahci_mcp89,
@@ -84,6 +85,8 @@ enum board_ids {
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
				 unsigned long deadline);
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
			      unsigned long deadline);
static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
@@ -107,6 +110,11 @@ static struct ata_port_operations ahci_p5wdh_ops = {
	.hardreset		= ahci_p5wdh_hardreset,
};

static struct ata_port_operations ahci_avn_ops = {
	.inherits		= &ahci_ops,
	.hardreset		= ahci_avn_hardreset,
};

static const struct ata_port_info ahci_port_info[] = {
	/* by features */
	[board_ahci] = {
@@ -151,6 +159,12 @@ static const struct ata_port_info ahci_port_info[] = {
		.port_ops	= &ahci_ops,
	},
	/* by chipsets */
	[board_ahci_avn] = {
		.flags		= AHCI_FLAG_COMMON,
		.pio_mask	= ATA_PIO4,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_avn_ops,
	},
	[board_ahci_mcp65] = {
		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
				 AHCI_HFLAG_YES_NCQ),
@@ -290,14 +304,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
@@ -670,6 +684,79 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
	return rc;
}

/*
 * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
 *
 * It has been observed with some SSDs that the timing of events in the
 * link synchronization phase can leave the port in a state that can not
 * be recovered by a SATA-hard-reset alone.  The failing signature is
 * SStatus.DET stuck at 1 ("Device presence detected but Phy
 * communication not established").  It was found that unloading and
 * reloading the driver when this problem occurs allows the drive
 * connection to be recovered (DET advanced to 0x3).  The critical
 * component of reloading the driver is that the port state machines are
 * reset by bouncing "port enable" in the AHCI PCS configuration
 * register.  So, reproduce that effect by bouncing a port whenever we
 * see DET==1 after a reset.
 */
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
			      unsigned long deadline)
{
	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
	struct ata_port *ap = link->ap;
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_host_priv *hpriv = ap->host->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	unsigned long tmo = deadline - jiffies;
	struct ata_taskfile tf;
	bool online;
	int rc, i;

	DPRINTK("ENTER\n");

	ahci_stop_engine(ap);

	for (i = 0; i < 2; i++) {
		u16 val;
		u32 sstatus;
		int port = ap->port_no;
		struct ata_host *host = ap->host;
		struct pci_dev *pdev = to_pci_dev(host->dev);

		/* clear D2H reception area to properly wait for D2H FIS */
		ata_tf_init(link->device, &tf);
		tf.command = ATA_BUSY;
		ata_tf_to_fis(&tf, 0, 0, d2h_fis);

		rc = sata_link_hardreset(link, timing, deadline, &online,
				ahci_check_ready);

		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
				(sstatus & 0xf) != 1)
			break;

		ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
				port);

		pci_read_config_word(pdev, 0x92, &val);
		val &= ~(1 << port);
		pci_write_config_word(pdev, 0x92, val);
		ata_msleep(ap, 1000);
		val |= 1 << port;
		pci_write_config_word(pdev, 0x92, val);
		deadline += tmo;
	}

	hpriv->start_engine(ap);

	if (online)
		*class = ahci_dev_classify(ap);

	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
	return rc;
}


#ifdef CONFIG_PM
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
+24 −25
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ struct st_ahci_drv_data {
	struct reset_control *pwr;
	struct reset_control *sw_rst;
	struct reset_control *pwr_rst;
	struct ahci_host_priv *hpriv;
};

static void st_ahci_configure_oob(void __iomem *mmio)
@@ -55,9 +54,10 @@ static void st_ahci_configure_oob(void __iomem *mmio)
	writel(new_val, mmio + ST_AHCI_OOBR);
}

static int st_ahci_deassert_resets(struct device *dev)
static int st_ahci_deassert_resets(struct ahci_host_priv *hpriv,
				struct device *dev)
{
	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
	struct st_ahci_drv_data *drv_data = hpriv->plat_data;
	int err;

	if (drv_data->pwr) {
@@ -90,8 +90,8 @@ static int st_ahci_deassert_resets(struct device *dev)
static void st_ahci_host_stop(struct ata_host *host)
{
	struct ahci_host_priv *hpriv = host->private_data;
	struct st_ahci_drv_data *drv_data = hpriv->plat_data;
	struct device *dev = host->dev;
	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
	int err;

	if (drv_data->pwr) {
@@ -103,29 +103,30 @@ static void st_ahci_host_stop(struct ata_host *host)
	ahci_platform_disable_resources(hpriv);
}

static int st_ahci_probe_resets(struct platform_device *pdev)
static int st_ahci_probe_resets(struct ahci_host_priv *hpriv,
				struct device *dev)
{
	struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev);
	struct st_ahci_drv_data *drv_data = hpriv->plat_data;

	drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn");
	drv_data->pwr = devm_reset_control_get(dev, "pwr-dwn");
	if (IS_ERR(drv_data->pwr)) {
		dev_info(&pdev->dev, "power reset control not defined\n");
		dev_info(dev, "power reset control not defined\n");
		drv_data->pwr = NULL;
	}

	drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst");
	drv_data->sw_rst = devm_reset_control_get(dev, "sw-rst");
	if (IS_ERR(drv_data->sw_rst)) {
		dev_info(&pdev->dev, "soft reset control not defined\n");
		dev_info(dev, "soft reset control not defined\n");
		drv_data->sw_rst = NULL;
	}

	drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst");
	drv_data->pwr_rst = devm_reset_control_get(dev, "pwr-rst");
	if (IS_ERR(drv_data->pwr_rst)) {
		dev_dbg(&pdev->dev, "power soft reset control not defined\n");
		dev_dbg(dev, "power soft reset control not defined\n");
		drv_data->pwr_rst = NULL;
	}

	return st_ahci_deassert_resets(&pdev->dev);
	return st_ahci_deassert_resets(hpriv, dev);
}

static struct ata_port_operations st_ahci_port_ops = {
@@ -154,15 +155,12 @@ static int st_ahci_probe(struct platform_device *pdev)
	if (!drv_data)
		return -ENOMEM;

	platform_set_drvdata(pdev, drv_data);

	hpriv = ahci_platform_get_resources(pdev);
	if (IS_ERR(hpriv))
		return PTR_ERR(hpriv);
	hpriv->plat_data = drv_data;

	drv_data->hpriv = hpriv;

	err = st_ahci_probe_resets(pdev);
	err = st_ahci_probe_resets(hpriv, &pdev->dev);
	if (err)
		return err;

@@ -170,7 +168,7 @@ static int st_ahci_probe(struct platform_device *pdev)
	if (err)
		return err;

	st_ahci_configure_oob(drv_data->hpriv->mmio);
	st_ahci_configure_oob(hpriv->mmio);

	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
				      &ahci_platform_sht);
@@ -185,8 +183,9 @@ static int st_ahci_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int st_ahci_suspend(struct device *dev)
{
	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
	struct ahci_host_priv *hpriv = drv_data->hpriv;
	struct ata_host *host = dev_get_drvdata(dev);
	struct ahci_host_priv *hpriv = host->private_data;
	struct st_ahci_drv_data *drv_data = hpriv->plat_data;
	int err;

	err = ahci_platform_suspend_host(dev);
@@ -208,21 +207,21 @@ static int st_ahci_suspend(struct device *dev)

static int st_ahci_resume(struct device *dev)
{
	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
	struct ahci_host_priv *hpriv = drv_data->hpriv;
	struct ata_host *host = dev_get_drvdata(dev);
	struct ahci_host_priv *hpriv = host->private_data;
	int err;

	err = ahci_platform_enable_resources(hpriv);
	if (err)
		return err;

	err = st_ahci_deassert_resets(dev);
	err = st_ahci_deassert_resets(hpriv, dev);
	if (err) {
		ahci_platform_disable_resources(hpriv);
		return err;
	}

	st_ahci_configure_oob(drv_data->hpriv->mmio);
	st_ahci_configure_oob(hpriv->mmio);

	return ahci_platform_resume_host(dev);
}
+1 −2
Original line number Diff line number Diff line
@@ -1707,8 +1707,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
	if (unlikely(resetting))
		status &= ~PORT_IRQ_BAD_PMP;

	/* if LPM is enabled, PHYRDY doesn't mean anything */
	if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
	if (sata_lpm_ignore_phy_events(&ap->link)) {
		status &= ~PORT_IRQ_PHYRDY;
		ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
	}
Loading