Commit e543c8a9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-4.12-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata

Pull libata fixes from Tejun Heo:

 - Revert of sata_mv devm_ioremap_resource() conversion. It made init
   fail if there are overlapping resources which led to detection
   failures on some setups.

 - A workaround for an Acer laptop which sometimes reports corrupt port
   map.

 - Other non-critical fixes.

* 'for-4.12-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  libata: fix error checking in in ata_parse_force_one()
  Revert "ata: sata_mv: Convert to devm_ioremap_resource()"
  ata: libahci: properly propagate return value of platform_get_irq()
  ata: sata_rcar: Handle return value of clk_prepare_enable
  ahci: Acer SA5-271 SSD Not Detected Fix
parents 112eb072 f7cf69ae
...@@ -1364,6 +1364,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) ...@@ -1364,6 +1364,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
{} {}
#endif #endif
/*
* On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
* as DUMMY, or detected but eventually get a "link down" and never get up
* again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
* port_map may hold a value of 0x00.
*
* Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
* and can significantly reduce the occurrence of the problem.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=189471
*/
static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
struct pci_dev *pdev)
{
static const struct dmi_system_id sysids[] = {
{
.ident = "Acer Switch Alpha 12",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
},
},
{ }
};
if (dmi_check_system(sysids)) {
dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
hpriv->port_map = 0x7;
hpriv->cap = 0xC734FF02;
}
}
}
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
/* /*
* Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
...@@ -1636,6 +1670,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1636,6 +1670,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"online status unreliable, applying workaround\n"); "online status unreliable, applying workaround\n");
} }
/* Acer SA5-271 workaround modifies private_data */
acer_sa5_271_workaround(hpriv, pdev);
/* CAP.NP sometimes indicate the index of the last enabled /* CAP.NP sometimes indicate the index of the last enabled
* port, at other times, that of the last possible port, so * port, at other times, that of the last possible port, so
* determining the maximum port number requires looking at * determining the maximum port number requires looking at
......
...@@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev, ...@@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq <= 0) { if (irq <= 0) {
if (irq != -EPROBE_DEFER)
dev_err(dev, "no irq\n"); dev_err(dev, "no irq\n");
return -EINVAL; return irq;
} }
hpriv->irq = irq; hpriv->irq = irq;
......
...@@ -6800,7 +6800,7 @@ static int __init ata_parse_force_one(char **cur, ...@@ -6800,7 +6800,7 @@ static int __init ata_parse_force_one(char **cur,
} }
force_ent->port = simple_strtoul(id, &endp, 10); force_ent->port = simple_strtoul(id, &endp, 10);
if (p == endp || *endp != '\0') { if (id == endp || *endp != '\0') {
*reason = "invalid port/link"; *reason = "invalid port/link";
return -EINVAL; return -EINVAL;
} }
......
...@@ -4067,7 +4067,6 @@ static int mv_platform_probe(struct platform_device *pdev) ...@@ -4067,7 +4067,6 @@ static int mv_platform_probe(struct platform_device *pdev)
struct ata_host *host; struct ata_host *host;
struct mv_host_priv *hpriv; struct mv_host_priv *hpriv;
struct resource *res; struct resource *res;
void __iomem *mmio;
int n_ports = 0, irq = 0; int n_ports = 0, irq = 0;
int rc; int rc;
int port; int port;
...@@ -4086,9 +4085,8 @@ static int mv_platform_probe(struct platform_device *pdev) ...@@ -4086,9 +4085,8 @@ static int mv_platform_probe(struct platform_device *pdev)
* Get the register base first * Get the register base first
*/ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mmio = devm_ioremap_resource(&pdev->dev, res); if (res == NULL)
if (IS_ERR(mmio)) return -EINVAL;
return PTR_ERR(mmio);
/* allocate host */ /* allocate host */
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
...@@ -4132,7 +4130,12 @@ static int mv_platform_probe(struct platform_device *pdev) ...@@ -4132,7 +4130,12 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->board_idx = chip_soc; hpriv->board_idx = chip_soc;
host->iomap = NULL; host->iomap = NULL;
hpriv->base = mmio - SATAHC0_REG_BASE; hpriv->base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!hpriv->base)
return -ENOMEM;
hpriv->base -= SATAHC0_REG_BASE;
hpriv->clk = clk_get(&pdev->dev, NULL); hpriv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(hpriv->clk)) if (IS_ERR(hpriv->clk))
......
...@@ -890,7 +890,10 @@ static int sata_rcar_probe(struct platform_device *pdev) ...@@ -890,7 +890,10 @@ static int sata_rcar_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get access to sata clock\n"); dev_err(&pdev->dev, "failed to get access to sata clock\n");
return PTR_ERR(priv->clk); return PTR_ERR(priv->clk);
} }
clk_prepare_enable(priv->clk);
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
host = ata_host_alloc(&pdev->dev, 1); host = ata_host_alloc(&pdev->dev, 1);
if (!host) { if (!host) {
...@@ -970,8 +973,11 @@ static int sata_rcar_resume(struct device *dev) ...@@ -970,8 +973,11 @@ static int sata_rcar_resume(struct device *dev)
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct sata_rcar_priv *priv = host->private_data; struct sata_rcar_priv *priv = host->private_data;
void __iomem *base = priv->base; void __iomem *base = priv->base;
int ret;
clk_prepare_enable(priv->clk); ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
/* ack and mask */ /* ack and mask */
iowrite32(0, base + SATAINTSTAT_REG); iowrite32(0, base + SATAINTSTAT_REG);
...@@ -988,8 +994,11 @@ static int sata_rcar_restore(struct device *dev) ...@@ -988,8 +994,11 @@ static int sata_rcar_restore(struct device *dev)
{ {
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct sata_rcar_priv *priv = host->private_data; struct sata_rcar_priv *priv = host->private_data;
int ret;
clk_prepare_enable(priv->clk); ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
sata_rcar_setup_port(host); sata_rcar_setup_port(host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment