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

Commit 4e541699 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata fixes from Tejun Heo:

 - PORTS_IMPL workaround for very early ahci controllers is misbehaving
   on new systems.  Disabled on recent ahci versions.

 - Old-style PIO state machine had a horrible locking problem.  Don't
   know how we've been getting away this far.  Fixed.

 - Other device specific updates.

* 'for-4.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: Intel DNV device IDs SATA
  libata: fix sff host state machine locking while polling
  libata-sff: use WARN instead of BUG on illegal host state machine state
  libata: disable forced PORTS_IMPL for >= AHCI 1.3
  libata: blacklist a Viking flash model for MWDMA corruption
  drivers: ata: wake port before DMA stop for ALPM
parents fb0dc5f1 342decff
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -264,6 +264,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
+1 −0
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ enum {
	AHCI_HFLAG_MULTI_MSI		= 0,
	AHCI_HFLAG_MULTI_MSIX		= 0,
#endif
	AHCI_HFLAG_WAKE_BEFORE_STOP	= (1 << 22), /* wake before DMA stop */

	/* ap->flags bits */

+1 −0
Original line number Diff line number Diff line
@@ -317,6 +317,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
	if (IS_ERR(hpriv))
		return PTR_ERR(hpriv);
	hpriv->plat_data = priv;
	hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;

	brcm_sata_alpm_init(hpriv);

+24 −3
Original line number Diff line number Diff line
@@ -496,8 +496,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
		}
	}

	/* fabricate port_map from cap.nr_ports */
	if (!port_map) {
	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
	if (!port_map && vers < 0x10300) {
		port_map = (1 << ahci_nr_ports(cap)) - 1;
		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);

@@ -593,8 +593,22 @@ EXPORT_SYMBOL_GPL(ahci_start_engine);
int ahci_stop_engine(struct ata_port *ap)
{
	void __iomem *port_mmio = ahci_port_base(ap);
	struct ahci_host_priv *hpriv = ap->host->private_data;
	u32 tmp;

	/*
	 * On some controllers, stopping a port's DMA engine while the port
	 * is in ALPM state (partial or slumber) results in failures on
	 * subsequent DMA engine starts.  For those controllers, put the
	 * port back in active state before stopping its DMA engine.
	 */
	if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) &&
	    (ap->link.lpm_policy > ATA_LPM_MAX_POWER) &&
	    ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) {
		dev_err(ap->host->dev, "Failed to wake up port before engine stop\n");
		return -EIO;
	}

	tmp = readl(port_mmio + PORT_CMD);

	/* check if the HBA is idle */
@@ -689,6 +703,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
	void __iomem *port_mmio = ahci_port_base(ap);

	if (policy != ATA_LPM_MAX_POWER) {
		/* wakeup flag only applies to the max power policy */
		hints &= ~ATA_LPM_WAKE_ONLY;

		/*
		 * Disable interrupts on Phy Ready. This keeps us from
		 * getting woken up due to spurious phy ready
@@ -704,6 +721,7 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
		u32 cmd = readl(port_mmio + PORT_CMD);

		if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
			if (!(hints & ATA_LPM_WAKE_ONLY))
				cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
			cmd |= PORT_CMD_ICC_ACTIVE;

@@ -712,6 +730,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,

			/* wait 10ms to be sure we've come out of LPM state */
			ata_msleep(ap, 10);

			if (hints & ATA_LPM_WAKE_ONLY)
				return 0;
		} else {
			cmd |= PORT_CMD_ALPE;
			if (policy == ATA_LPM_MIN_POWER)
+1 −0
Original line number Diff line number Diff line
@@ -4125,6 +4125,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "SAMSUNG CD-ROM SN-124", "N001",	ATA_HORKAGE_NODMA },
	{ "Seagate STT20000A", NULL,		ATA_HORKAGE_NODMA },
	{ " 2GB ATA Flash Disk", "ADMA428M",	ATA_HORKAGE_NODMA },
	{ "VRFDFC22048UCHC-TE*", NULL,		ATA_HORKAGE_NODMA },
	/* Odd clown on sil3726/4726 PMPs */
	{ "Config  Disk",	NULL,		ATA_HORKAGE_DISABLE },

Loading