diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/Kconfig | 11 | ||||
-rw-r--r-- | drivers/ata/Makefile | 1 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 17 | ||||
-rw-r--r-- | drivers/ata/ahci_imx.c | 236 | ||||
-rw-r--r-- | drivers/ata/ata_piix.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-acpi.c | 282 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 29 | ||||
-rw-r--r-- | drivers/ata/libata-pmp.c | 12 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 44 | ||||
-rw-r--r-- | drivers/ata/libata-transport.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-zpodd.c | 12 | ||||
-rw-r--r-- | drivers/ata/libata.h | 19 | ||||
-rw-r--r-- | drivers/ata/pata_acpi.c | 4 | ||||
-rw-r--r-- | drivers/ata/pata_arasan_cf.c | 4 | ||||
-rw-r--r-- | drivers/ata/pata_at32.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_at91.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_imx.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_ixp4xx_cf.c | 4 | ||||
-rw-r--r-- | drivers/ata/pata_octeon_cf.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_platform.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_pxa.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_samsung_cf.c | 10 | ||||
-rw-r--r-- | drivers/ata/sata_fsl.c | 5 | ||||
-rw-r--r-- | drivers/ata/sata_highbank.c | 78 | ||||
-rw-r--r-- | drivers/ata/sata_inic162x.c | 14 | ||||
-rw-r--r-- | drivers/ata/sata_mv.c | 26 | ||||
-rw-r--r-- | drivers/ata/sata_rcar.c | 5 |
27 files changed, 524 insertions, 304 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 80dc988f01e..4e737728aee 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -97,6 +97,15 @@ config SATA_AHCI_PLATFORM If unsure, say N. +config AHCI_IMX + tristate "Freescale i.MX AHCI SATA support" + depends on SATA_AHCI_PLATFORM && MFD_SYSCON + help + This option enables support for the Freescale i.MX SoC's + onboard AHCI SATA. + + If unsure, say N. + config SATA_FSL tristate "Freescale 3.0Gbps SATA support" depends on FSL_SOC @@ -107,7 +116,7 @@ config SATA_FSL If unsure, say N. config SATA_INIC162X - tristate "Initio 162x SATA support" + tristate "Initio 162x SATA support (Very Experimental)" depends on PCI help This option enables support for Initio 162x Serial ATA. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index c04d0fd038a..46518c62246 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -10,6 +10,7 @@ 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 +obj-$(CONFIG_AHCI_IMX) += ahci_imx.o # SFF w/ custom DMA obj-$(CONFIG_PDC_ADMA) += pdc_adma.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5064f3ea20f..9d715ae5ff6 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1146,11 +1146,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) return rc; for (i = 0; i < host->n_ports; i++) { + const char* desc; struct ahci_port_priv *pp = host->ports[i]->private_data; + /* pp is NULL for dummy ports */ + if (pp) + desc = pp->irq_desc; + else + desc = dev_driver_string(host->dev); + rc = devm_request_threaded_irq(host->dev, irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED, - pp->irq_desc, host->ports[i]); + desc, host->ports[i]); if (rc) goto out_free_irqs; } @@ -1288,6 +1295,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) pi.flags |= ATA_FLAG_FPDMA_AA; + + /* + * All AHCI controllers should be forward-compatible + * with the new auxiliary field. This code should be + * conditionalized if any buggy AHCI controllers are + * encountered. + */ + pi.flags |= ATA_FLAG_FPDMA_AUX; } if (hpriv->cap & HOST_CAP_PMP) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c new file mode 100644 index 00000000000..58debb0acc3 --- /dev/null +++ b/drivers/ata/ahci_imx.c @@ -0,0 +1,236 @@ +/* + * Freescale IMX AHCI SATA platform driver + * Copyright 2013 Freescale Semiconductor, Inc. + * + * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/ahci_platform.h> +#include <linux/of_device.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include "ahci.h" + +enum { + HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ +}; + +struct imx_ahci_priv { + struct platform_device *ahci_pdev; + struct clk *sata_ref_clk; + struct clk *ahb_clk; + struct regmap *gpr; +}; + +static int imx6q_sata_init(struct device *dev, void __iomem *mmio) +{ + int ret = 0; + unsigned int reg_val; + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + + imxpriv->gpr = + syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (IS_ERR(imxpriv->gpr)) { + dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); + return PTR_ERR(imxpriv->gpr); + } + + ret = clk_prepare_enable(imxpriv->sata_ref_clk); + if (ret < 0) { + dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); + return ret; + } + + /* + * set PHY Paremeters, two steps to configure the GPR13, + * one write for rest of parameters, mask of first write + * is 0x07fffffd, and the other one write for setting + * the mpll_clk_en. + */ + regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK + | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK + | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK + | IMX6Q_GPR13_SATA_SPD_MODE_MASK + | IMX6Q_GPR13_SATA_MPLL_SS_EN + | IMX6Q_GPR13_SATA_TX_ATTEN_MASK + | IMX6Q_GPR13_SATA_TX_BOOST_MASK + | IMX6Q_GPR13_SATA_TX_LVL_MASK + | IMX6Q_GPR13_SATA_TX_EDGE_RATE + , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB + | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M + | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F + | IMX6Q_GPR13_SATA_SPD_MODE_3P0G + | IMX6Q_GPR13_SATA_MPLL_SS_EN + | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 + | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB + | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); + regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); + usleep_range(100, 200); + + /* + * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, + * and IP vendor specific register HOST_TIMER1MS. + * Configure CAP_SSS (support stagered spin up). + * Implement the port0. + * Get the ahb clock rate, and configure the TIMER1MS register. + */ + reg_val = readl(mmio + HOST_CAP); + if (!(reg_val & HOST_CAP_SSS)) { + reg_val |= HOST_CAP_SSS; + writel(reg_val, mmio + HOST_CAP); + } + reg_val = readl(mmio + HOST_PORTS_IMPL); + if (!(reg_val & 0x1)) { + reg_val |= 0x1; + writel(reg_val, mmio + HOST_PORTS_IMPL); + } + + reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; + writel(reg_val, mmio + HOST_TIMER1MS); + + return 0; +} + +static void imx6q_sata_exit(struct device *dev) +{ + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + + regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + clk_disable_unprepare(imxpriv->sata_ref_clk); +} + +static struct ahci_platform_data imx6q_sata_pdata = { + .init = imx6q_sata_init, + .exit = imx6q_sata_exit, +}; + +static const struct of_device_id imx_ahci_of_match[] = { + { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata}, + {}, +}; +MODULE_DEVICE_TABLE(of, imx_ahci_of_match); + +static int imx_ahci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *mem, *irq, res[2]; + const struct of_device_id *of_id; + const struct ahci_platform_data *pdata = NULL; + struct imx_ahci_priv *imxpriv; + struct device *ahci_dev; + struct platform_device *ahci_pdev; + int ret; + + imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); + if (!imxpriv) { + dev_err(dev, "can't alloc ahci_host_priv\n"); + return -ENOMEM; + } + + ahci_pdev = platform_device_alloc("ahci", -1); + if (!ahci_pdev) + return -ENODEV; + + ahci_dev = &ahci_pdev->dev; + ahci_dev->parent = dev; + + imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); + if (IS_ERR(imxpriv->ahb_clk)) { + dev_err(dev, "can't get ahb clock.\n"); + ret = PTR_ERR(imxpriv->ahb_clk); + goto err_out; + } + + imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); + if (IS_ERR(imxpriv->sata_ref_clk)) { + dev_err(dev, "can't get sata_ref clock.\n"); + ret = PTR_ERR(imxpriv->sata_ref_clk); + goto err_out; + } + + imxpriv->ahci_pdev = ahci_pdev; + platform_set_drvdata(pdev, imxpriv); + + of_id = of_match_device(imx_ahci_of_match, dev); + if (of_id) { + pdata = of_id->data; + } else { + ret = -EINVAL; + goto err_out; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!mem || !irq) { + dev_err(dev, "no mmio/irq resource\n"); + ret = -ENOMEM; + goto err_out; + } + + res[0] = *mem; + res[1] = *irq; + + ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32); + ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; + ahci_dev->of_node = dev->of_node; + + ret = platform_device_add_resources(ahci_pdev, res, 2); + if (ret) + goto err_out; + + ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata)); + if (ret) + goto err_out; + + ret = platform_device_add(ahci_pdev); + if (ret) { +err_out: + platform_device_put(ahci_pdev); + return ret; + } + + return 0; +} + +static int imx_ahci_remove(struct platform_device *pdev) +{ + struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev); + struct platform_device *ahci_pdev = imxpriv->ahci_pdev; + + platform_device_unregister(ahci_pdev); + return 0; +} + +static struct platform_driver imx_ahci_driver = { + .probe = imx_ahci_probe, + .remove = imx_ahci_remove, + .driver = { + .name = "ahci-imx", + .owner = THIS_MODULE, + .of_match_table = imx_ahci_of_match, + }, +}; +module_platform_driver(imx_ahci_driver); + +MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver"); +MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ahci:imx"); diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index b52a10c8eeb..513ad7ed0c9 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -330,7 +330,7 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller IDE (Wellsburg) */ { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, /* SATA Controller IDE (Wellsburg) */ - { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, /* SATA Controller IDE (Wellsburg) */ { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, /* SATA Controller IDE (Wellsburg) */ diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index cf4e7020ada..4ba8b040557 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -34,14 +34,6 @@ struct ata_acpi_gtf { u8 tf[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ } __packed; -/* - * Helper - belongs in the PCI layer somewhere eventually - */ -static int is_pci_dev(struct device *dev) -{ - return (dev->bus == &pci_bus_type); -} - static void ata_acpi_clear_gtf(struct ata_device *dev) { kfree(dev->gtf_cache); @@ -49,47 +41,18 @@ static void ata_acpi_clear_gtf(struct ata_device *dev) } /** - * ata_ap_acpi_handle - provide the acpi_handle for an ata_port - * @ap: the acpi_handle returned will correspond to this port - * - * Returns the acpi_handle for the ACPI namespace object corresponding to - * the ata_port passed into the function, or NULL if no such object exists - */ -acpi_handle ata_ap_acpi_handle(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_ACPI_SATA) - return NULL; - - return ap->scsi_host ? - DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL; -} -EXPORT_SYMBOL(ata_ap_acpi_handle); - -/** * ata_dev_acpi_handle - provide the acpi_handle for an ata_device - * @dev: the acpi_device returned will correspond to this port + * @dev: the acpi_handle returned will correspond to this device * * Returns the acpi_handle for the ACPI namespace object corresponding to * the ata_device passed into the function, or NULL if no such object exists + * or ACPI is disabled for this device due to consecutive errors. */ acpi_handle ata_dev_acpi_handle(struct ata_device *dev) { - acpi_integer adr; - struct ata_port *ap = dev->link->ap; - - if (libata_noacpi || dev->flags & ATA_DFLAG_ACPI_DISABLED) - return NULL; - - if (ap->flags & ATA_FLAG_ACPI_SATA) { - if (!sata_pmp_attached(ap)) - adr = SATA_ADR(ap->port_no, NO_PORT_MULT); - else - adr = SATA_ADR(ap->port_no, dev->link->pmp); - return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr); - } else - return acpi_get_child(ata_ap_acpi_handle(ap), dev->devno); + return dev->flags & ATA_DFLAG_ACPI_DISABLED ? + NULL : ACPI_HANDLE(&dev->tdev); } -EXPORT_SYMBOL(ata_dev_acpi_handle); /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) @@ -156,10 +119,8 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(ap->lock, flags); - if (wait) { + if (wait) ata_port_wait_eh(ap); - flush_work(&ap->hotplug_task.work); - } } static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) @@ -216,37 +177,55 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { .uevent = ata_acpi_ap_uevent, }; -void ata_acpi_hotplug_init(struct ata_host *host) +/* bind acpi handle to pata port */ +void ata_acpi_bind_port(struct ata_port *ap) { - int i; + acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - acpi_handle handle; - struct ata_device *dev; + if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle) + return; - if (!ap) - continue; + ACPI_HANDLE_SET(&ap->tdev, acpi_get_child(host_handle, ap->port_no)); - handle = ata_ap_acpi_handle(ap); - if (handle) { - /* we might be on a docking station */ - register_hotplug_dock_device(handle, - &ata_acpi_ap_dock_ops, ap, - NULL, NULL); - } + if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) + ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; - ata_for_each_dev(dev, &ap->link, ALL) { - handle = ata_dev_acpi_handle(dev); - if (!handle) - continue; + /* we might be on a docking station */ + register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev), + &ata_acpi_ap_dock_ops, ap, NULL, NULL); +} - /* we might be on a docking station */ - register_hotplug_dock_device(handle, - &ata_acpi_dev_dock_ops, - dev, NULL, NULL); - } +void ata_acpi_bind_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + acpi_handle port_handle = ACPI_HANDLE(&ap->tdev); + acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); + acpi_handle parent_handle; + u64 adr; + + /* + * For both sata/pata devices, host handle is required. + * For pata device, port handle is also required. + */ + if (libata_noacpi || !host_handle || + (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle)) + return; + + if (ap->flags & ATA_FLAG_ACPI_SATA) { + if (!sata_pmp_attached(ap)) + adr = SATA_ADR(ap->port_no, NO_PORT_MULT); + else + adr = SATA_ADR(ap->port_no, dev->link->pmp); + parent_handle = host_handle; + } else { + adr = dev->devno; + parent_handle = port_handle; } + + ACPI_HANDLE_SET(&dev->tdev, acpi_get_child(parent_handle, adr)); + + register_hotplug_dock_device(ata_dev_acpi_handle(dev), + &ata_acpi_dev_dock_ops, dev, NULL, NULL); } /** @@ -270,18 +249,34 @@ void ata_acpi_dissociate(struct ata_host *host) struct ata_port *ap = host->ports[i]; const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); - if (ata_ap_acpi_handle(ap) && gtm) + if (ACPI_HANDLE(&ap->tdev) && gtm) ata_acpi_stm(ap, gtm); } } -static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle, - struct ata_acpi_gtm *gtm) +/** + * ata_acpi_gtm - execute _GTM + * @ap: target ATA port + * @gtm: out parameter for _GTM result + * + * Evaluate _GTM and store the result in @gtm. + * + * LOCKING: + * EH context. + * + * RETURNS: + * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. + */ +int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm) { struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; union acpi_object *out_obj; acpi_status status; int rc = 0; + acpi_handle handle = ACPI_HANDLE(&ap->tdev); + + if (!handle) + return -EINVAL; status = acpi_evaluate_object(handle, "_GTM", NULL, &output); @@ -317,27 +312,6 @@ static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle, return rc; } -/** - * ata_acpi_gtm - execute _GTM - * @ap: target ATA port - * @gtm: out parameter for _GTM result - * - * Evaluate _GTM and store the result in @gtm. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. - */ -int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm) -{ - if (ata_ap_acpi_handle(ap)) - return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm); - else - return -EINVAL; -} - EXPORT_SYMBOL_GPL(ata_acpi_gtm); /** @@ -374,8 +348,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm) input.count = 3; input.pointer = in_params; - status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_STM", &input, - NULL); + status = acpi_evaluate_object(ACPI_HANDLE(&ap->tdev), "_STM", + &input, NULL); if (status == AE_NOT_FOUND) return -ENOENT; @@ -850,7 +824,7 @@ void ata_acpi_on_resume(struct ata_port *ap) const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); struct ata_device *dev; - if (ata_ap_acpi_handle(ap) && gtm) { + if (ACPI_HANDLE(&ap->tdev) && gtm) { /* _GTM valid */ /* restore timing parameters */ @@ -894,8 +868,7 @@ static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime) d_max_in = ACPI_STATE_D3_HOT; out: - return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev, - NULL, d_max_in); + return acpi_pm_device_sleep_state(&dev->tdev, NULL, d_max_in); } static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state) @@ -932,7 +905,7 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state) struct ata_device *dev; acpi_handle port_handle; - port_handle = ata_ap_acpi_handle(ap); + port_handle = ACPI_HANDLE(&ap->tdev); if (!port_handle) return; @@ -947,11 +920,11 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state) continue; acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ? - ACPI_STATE_D0 : ACPI_STATE_D3); + ACPI_STATE_D0 : ACPI_STATE_D3_COLD); } if (!(state.event & PM_EVENT_RESUME)) - acpi_bus_set_power(port_handle, ACPI_STATE_D3); + acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD); } /** @@ -1063,109 +1036,16 @@ void ata_acpi_on_disable(struct ata_device *dev) ata_acpi_clear_gtf(dev); } -static int compat_pci_ata(struct ata_port *ap) -{ - struct device *dev = ap->tdev.parent; - struct pci_dev *pdev; - - if (!is_pci_dev(dev)) - return 0; - - pdev = to_pci_dev(dev); - - if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA && - (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE) - return 0; - - return 1; -} - -static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle) -{ - if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA) - return -ENODEV; - - *handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent), - ap->port_no); - - if (!*handle) - return -ENODEV; - - if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0) - ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; - - return 0; -} - -static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, - acpi_handle *handle) -{ - struct ata_device *ata_dev; - - if (ap->flags & ATA_FLAG_ACPI_SATA) { - if (!sata_pmp_attached(ap)) - ata_dev = &ap->link.device[sdev->id]; - else - ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; - } - else { - ata_dev = &ap->link.device[sdev->id]; - } - - *handle = ata_dev_acpi_handle(ata_dev); - - if (!*handle) - return -ENODEV; - - return 0; -} - -static int is_ata_port(const struct device *dev) -{ - return dev->type == &ata_port_type; -} - -static struct ata_port *dev_to_ata_port(struct device *dev) -{ - while (!is_ata_port(dev)) { - if (!dev->parent) - return NULL; - dev = dev->parent; - } - return to_ata_port(dev); -} - -static int ata_acpi_find_device(struct device *dev, acpi_handle *handle) -{ - struct ata_port *ap = dev_to_ata_port(dev); - - if (!ap) - return -ENODEV; - - if (!compat_pci_ata(ap)) - return -ENODEV; - - if (scsi_is_host_device(dev)) - return ata_acpi_bind_host(ap, handle); - else if (scsi_is_sdev_device(dev)) { - struct scsi_device *sdev = to_scsi_device(dev); - - return ata_acpi_bind_device(ap, sdev, handle); - } else - return -ENODEV; -} - -static struct acpi_bus_type ata_acpi_bus = { - .name = "ATA", - .find_device = ata_acpi_find_device, -}; - -int ata_acpi_register(void) +void ata_scsi_acpi_bind(struct ata_device *dev) { - return scsi_register_acpi_bus_type(&ata_acpi_bus); + acpi_handle handle = ata_dev_acpi_handle(dev); + if (handle) + acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev); } -void ata_acpi_unregister(void) +void ata_scsi_acpi_unbind(struct ata_device *dev) { - scsi_unregister_acpi_bus_type(&ata_acpi_bus); + acpi_handle handle = ata_dev_acpi_handle(dev); + if (handle) + acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev); } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c24354d44f3..83b1a9fb2d4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -569,10 +569,10 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis) fis[14] = 0; fis[15] = tf->ctl; - fis[16] = 0; - fis[17] = 0; - fis[18] = 0; - fis[19] = 0; + fis[16] = tf->auxiliary & 0xff; + fis[17] = (tf->auxiliary >> 8) & 0xff; + fis[18] = (tf->auxiliary >> 16) & 0xff; + fis[19] = (tf->auxiliary >> 24) & 0xff; } /** @@ -2139,6 +2139,22 @@ static int ata_dev_config_ncq(struct ata_device *dev, else snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth, ddepth, aa_desc); + + if ((ap->flags & ATA_FLAG_FPDMA_AUX) && + ata_id_has_ncq_send_and_recv(dev->id)) { + err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV, + 0, ap->sector_buf, 1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to get NCQ Send/Recv Log Emask 0x%x\n", + err_mask); + } else { + dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; + memcpy(dev->ncq_send_recv_cmds, ap->sector_buf, + ATA_LOG_NCQ_SEND_RECV_SIZE); + } + } + return 0; } @@ -6150,8 +6166,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) if (rc) goto err_tadd; - ata_acpi_hotplug_init(host); - /* set cable, sata_spd_limit and report */ for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; @@ -6632,8 +6646,6 @@ static int __init ata_init(void) ata_parse_force_param(); - ata_acpi_register(); - rc = ata_sff_init(); if (rc) { kfree(ata_force_tbl); @@ -6660,7 +6672,6 @@ static void __exit ata_exit(void) ata_release_transport(ata_scsi_transport_template); libata_transport_exit(); ata_sff_exit(); - ata_acpi_unregister(); kfree(ata_force_tbl); } diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 1c41722bb7e..20fd337a573 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) /* Disable sending Early R_OK. * With "cached read" HDD testing and multiple ports busy on a SATA - * host controller, 3726 PMP will very rarely drop a deferred + * host controller, 3x26 PMP will very rarely drop a deferred * R_OK that was intended for the host. Symptom will be all * 5 drives under test will timeout, get reset, and recover. */ - if (vendor == 0x1095 && devid == 0x3726) { + if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { u32 reg; err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®); if (err_mask) { rc = -EIO; - reason = "failed to read Sil3726 Private Register"; + reason = "failed to read Sil3x26 Private Register"; goto fail; } reg &= ~0x1; err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg); if (err_mask) { rc = -EIO; - reason = "failed to write Sil3726 Private Register"; + reason = "failed to write Sil3x26 Private Register"; goto fail; } } @@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_port *ap) u16 devid = sata_pmp_gscr_devid(gscr); struct ata_link *link; - if (vendor == 0x1095 && devid == 0x3726) { - /* sil3726 quirks */ + if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { + /* sil3x26 quirks */ ata_for_each_link(link, ap, EDGE) { /* link reports offline after LPM */ link->flags |= ATA_LFLAG_NO_LPM; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 83c08907e04..97a0cef1295 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -49,7 +49,6 @@ #include <linux/hdreg.h> #include <linux/uaccess.h> #include <linux/suspend.h> -#include <linux/pm_qos.h> #include <asm/unaligned.h> #include "libata.h" @@ -206,8 +205,10 @@ static ssize_t ata_scsi_park_store(struct device *device, unsigned long flags; int rc; - rc = strict_strtol(buf, 10, &input); - if (rc || input < -2) + rc = kstrtol(buf, 10, &input); + if (rc) + return rc; + if (input < -2) return -EINVAL; if (input > ATA_TMOUT_MAX_PARK) { rc = -EOVERFLOW; @@ -3098,12 +3099,25 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) buf = page_address(sg_page(scsi_sglist(scmd))); size = ata_set_lba_range_entries(buf, 512, block, n_block); - tf->protocol = ATA_PROT_DMA; - tf->hob_feature = 0; - tf->feature = ATA_DSM_TRIM; - tf->hob_nsect = (size / 512) >> 8; - tf->nsect = size / 512; - tf->command = ATA_CMD_DSM; + if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { + /* Newer devices support queued TRIM commands */ + tf->protocol = ATA_PROT_NCQ; + tf->command = ATA_CMD_FPDMA_SEND; + tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; + tf->nsect = qc->tag << 3; + tf->hob_feature = (size / 512) >> 8; + tf->feature = size / 512; + + tf->auxiliary = 1; + } else { + tf->protocol = ATA_PROT_DMA; + tf->hob_feature = 0; + tf->feature = ATA_DSM_TRIM; + tf->hob_nsect = (size / 512) >> 8; + tf->nsect = size / 512; + tf->command = ATA_CMD_DSM; + } + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | ATA_TFLAG_WRITE; @@ -3665,9 +3679,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) if (!IS_ERR(sdev)) { dev->sdev = sdev; scsi_device_put(sdev); - if (zpodd_dev_enabled(dev)) - dev_pm_qos_expose_flags( - &sdev->sdev_gendev, 0); + ata_scsi_acpi_bind(dev); } else { dev->sdev = NULL; } @@ -3755,6 +3767,8 @@ static void ata_scsi_remove_dev(struct ata_device *dev) struct scsi_device *sdev; unsigned long flags; + ata_scsi_acpi_unbind(dev); + /* Alas, we need to grab scan_mutex to ensure SCSI device * state doesn't change underneath us and thus * scsi_device_get() always succeeds. The mutex locking can @@ -3764,9 +3778,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev) mutex_lock(&ap->scsi_host->scan_mutex); spin_lock_irqsave(ap->lock, flags); - if (zpodd_dev_enabled(dev)) - zpodd_exit(dev); - /* clearing dev->sdev is protected by host lock */ sdev = dev->sdev; dev->sdev = NULL; @@ -3816,6 +3827,9 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) dev->flags &= ~ATA_DFLAG_DETACHED; spin_unlock_irqrestore(ap->lock, flags); + if (zpodd_dev_enabled(dev)) + zpodd_exit(dev); + ata_scsi_remove_dev(dev); } } diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 077a856f5fd..150a917f0c3 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -287,6 +287,7 @@ int ata_tport_add(struct device *parent, dev->release = ata_tport_release; dev_set_name(dev, "ata%d", ap->print_id); transport_setup_device(dev); + ata_acpi_bind_port(ap); error = device_add(dev); if (error) { goto tport_err; @@ -644,6 +645,7 @@ static int ata_tdev_add(struct ata_device *ata_dev) dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp); transport_setup_device(dev); + ata_acpi_bind_dev(ata_dev); error = device_add(dev); if (error) { ata_tdev_free(ata_dev); diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c index cd8daf47188..68f9e3293e9 100644 --- a/drivers/ata/libata-zpodd.c +++ b/drivers/ata/libata-zpodd.c @@ -2,6 +2,7 @@ #include <linux/cdrom.h> #include <linux/pm_runtime.h> #include <linux/module.h> +#include <linux/pm_qos.h> #include <scsi/scsi_device.h> #include "libata.h" @@ -190,8 +191,8 @@ void zpodd_enable_run_wake(struct ata_device *dev) sdev_disable_disk_events(dev->sdev); zpodd->powered_off = true; - device_set_run_wake(&dev->sdev->sdev_gendev, true); - acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, true); + device_set_run_wake(&dev->tdev, true); + acpi_pm_device_run_wake(&dev->tdev, true); } /* Disable runtime wake capability if it is enabled */ @@ -200,8 +201,8 @@ void zpodd_disable_run_wake(struct ata_device *dev) struct zpodd *zpodd = dev->zpodd; if (zpodd->powered_off) { - acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, false); - device_set_run_wake(&dev->sdev->sdev_gendev, false); + acpi_pm_device_run_wake(&dev->tdev, false); + device_set_run_wake(&dev->tdev, false); } } @@ -262,7 +263,7 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev) static void ata_acpi_remove_pm_notifier(struct ata_device *dev) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->sdev->sdev_gendev); + acpi_handle handle = ata_dev_acpi_handle(dev); acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, zpodd_wake_dev); } @@ -290,6 +291,7 @@ void zpodd_init(struct ata_device *dev) ata_acpi_add_pm_notifier(dev); zpodd->dev = dev; dev->zpodd = zpodd; + dev_pm_qos_expose_flags(&dev->tdev, 0); } void zpodd_exit(struct ata_device *dev) diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 577d902bc4d..eeeb77845d4 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -118,11 +118,11 @@ extern void ata_acpi_on_resume(struct ata_port *ap); extern int ata_acpi_on_devcfg(struct ata_device *dev); extern void ata_acpi_on_disable(struct ata_device *dev); extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); -extern int ata_acpi_register(void); -extern void ata_acpi_unregister(void); -extern void ata_acpi_bind(struct ata_device *dev); -extern void ata_acpi_unbind(struct ata_device *dev); -extern void ata_acpi_hotplug_init(struct ata_host *host); +extern void ata_acpi_bind_port(struct ata_port *ap); +extern void ata_acpi_bind_dev(struct ata_device *dev); +extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev); +extern void ata_scsi_acpi_bind(struct ata_device *dev); +extern void ata_scsi_acpi_unbind(struct ata_device *dev); #else static inline void ata_acpi_dissociate(struct ata_host *host) { } static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } @@ -131,11 +131,10 @@ static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; } static inline void ata_acpi_on_disable(struct ata_device *dev) { } static inline void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) { } -static inline int ata_acpi_register(void) { return 0; } -static inline void ata_acpi_unregister(void) { } -static inline void ata_acpi_bind(struct ata_device *dev) { } -static inline void ata_acpi_unbind(struct ata_device *dev) { } -static inline void ata_acpi_hotplug_init(struct ata_host *host) {} +static inline void ata_acpi_bind_port(struct ata_port *ap) {} +static inline void ata_acpi_bind_dev(struct ata_device *dev) {} +static inline void ata_scsi_acpi_bind(struct ata_device *dev) {} +static inline void ata_scsi_acpi_unbind(struct ata_device *dev) {} #endif /* libata-scsi.c */ diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 09723b76bea..73212c9c6d5 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -39,7 +39,7 @@ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline) { struct ata_port *ap = link->ap; struct pata_acpi *acpi = ap->private_data; - if (ata_ap_acpi_handle(ap) == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0) + if (ACPI_HANDLE(&ap->tdev) == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0) return -ENODEV; return ata_sff_prereset(link, deadline); @@ -195,7 +195,7 @@ static int pacpi_port_start(struct ata_port *ap) struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pata_acpi *acpi; - if (ata_ap_acpi_handle(ap) == NULL) + if (ACPI_HANDLE(&ap->tdev) == NULL) return -ENODEV; acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL); diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 848ed3254dd..853f610af28 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -654,7 +654,7 @@ static void arasan_cf_freeze(struct ata_port *ap) ata_sff_freeze(ap); } -void arasan_cf_error_handler(struct ata_port *ap) +static void arasan_cf_error_handler(struct ata_port *ap) { struct arasan_cf_dev *acdev = ap->host->private_data; @@ -683,7 +683,7 @@ static void arasan_cf_dma_start(struct arasan_cf_dev *acdev) ata_sff_queue_work(&acdev->work); } -unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) +static unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct arasan_cf_dev *acdev = ap->host->private_data; diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index 8d493b4a096..d59d5239405 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -271,7 +271,7 @@ static int __init pata_at32_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct at32_ide_info *info; - struct ide_platform_data *board = pdev->dev.platform_data; + struct ide_platform_data *board = dev_get_platdata(&pdev->dev); struct resource *res; int irq; diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 5364f97b42c..d63ee8f41a4 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -315,7 +315,7 @@ static struct ata_port_operations pata_at91_port_ops = { static int pata_at91_probe(struct platform_device *pdev) { - struct at91_cf_data *board = pdev->dev.platform_data; + struct at91_cf_data *board = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct at91_ide_info *info; struct resource *mem_res; diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 4ec7c04b3f8..26386f0b89a 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -237,6 +237,7 @@ static const struct of_device_id imx_pata_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_pata_dt_ids); static struct platform_driver pata_imx_driver = { .probe = pata_imx_probe, diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index dcc6b243e52..1ec53f8ca96 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -48,7 +48,7 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev, u16 *buf16 = (u16 *) buf; struct ata_port *ap = dev->link->ap; void __iomem *mmio = ap->ioaddr.data_addr; - struct ixp4xx_pata_data *data = ap->host->dev->platform_data; + struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev); /* set the expansion bus in 16bit mode and restore * 8 bit mode after the transaction. @@ -143,7 +143,7 @@ static int ixp4xx_pata_probe(struct platform_device *pdev) struct resource *cs0, *cs1; struct ata_host *host; struct ata_port *ap; - struct ixp4xx_pata_data *data = pdev->dev.platform_data; + struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev); cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index e73bef3093d..c51bbb9ea8e 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -1037,7 +1037,7 @@ static void octeon_cf_shutdown(struct device *dev) union cvmx_mio_boot_dma_cfgx dma_cfg; union cvmx_mio_boot_dma_intx dma_int; - struct octeon_cf_port *cf_port = dev->platform_data; + struct octeon_cf_port *cf_port = dev_get_platdata(dev); if (cf_port->dma_base) { /* Stop and clear the dma engine. */ diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 71e093767f4..02794885de1 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -180,7 +180,7 @@ static int pata_platform_probe(struct platform_device *pdev) struct resource *io_res; struct resource *ctl_res; struct resource *irq_res; - struct pata_platform_info *pp_info = pdev->dev.platform_data; + struct pata_platform_info *pp_info = dev_get_platdata(&pdev->dev); /* * Simple resource validation .. diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index 942ef94b29e..a6f05acad61 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -238,7 +238,7 @@ static int pxa_ata_probe(struct platform_device *pdev) struct resource *ctl_res; struct resource *dma_res; struct resource *irq_res; - struct pata_pxa_pdata *pdata = pdev->dev.platform_data; + struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev); int ret = 0; /* diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 6ef27e98c50..898e544a7ae 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -241,8 +241,8 @@ static u8 pata_s3c_check_altstatus(struct ata_port *ap) /* * pata_s3c_data_xfer - Transfer data by PIO */ -unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char *buf, - unsigned int buflen, int rw) +static unsigned int pata_s3c_data_xfer(struct ata_device *dev, + unsigned char *buf, unsigned int buflen, int rw) { struct ata_port *ap = dev->link->ap; struct s3c_ide_info *info = ap->host->private_data; @@ -418,7 +418,7 @@ static struct ata_port_operations pata_s5p_port_ops = { .set_piomode = pata_s3c_set_piomode, }; -static void pata_s3c_enable(void *s3c_ide_regbase, bool state) +static void pata_s3c_enable(void __iomem *s3c_ide_regbase, bool state) { u32 temp = readl(s3c_ide_regbase + S3C_ATA_CTRL); temp = state ? (temp | 1) : (temp & ~1); @@ -475,7 +475,7 @@ static void pata_s3c_hwinit(struct s3c_ide_info *info, static int __init pata_s3c_probe(struct platform_device *pdev) { - struct s3c_ide_platdata *pdata = pdev->dev.platform_data; + struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct s3c_ide_info *info; struct resource *res; @@ -617,7 +617,7 @@ static int pata_s3c_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct ata_host *host = platform_get_drvdata(pdev); - struct s3c_ide_platdata *pdata = pdev->dev.platform_data; + struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev); struct s3c_ide_info *info = host->private_data; pata_s3c_hwinit(info, pdata); diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 19720a0a4a6..851bd3f43ac 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host, { struct sata_fsl_host_priv *host_priv = host->private_data; void __iomem *hcr_base = host_priv->hcr_base; + unsigned long flags; if (count > ICC_MAX_INT_COUNT_THRESHOLD) count = ICC_MAX_INT_COUNT_THRESHOLD; @@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host, (count > ICC_MIN_INT_COUNT_THRESHOLD)) ticks = ICC_SAFE_INT_TICKS; - spin_lock(&host->lock); + spin_lock_irqsave(&host->lock, flags); iowrite32((count << 24 | ticks), hcr_base + ICC); intr_coalescing_count = count; intr_coalescing_ticks = ticks; - spin_unlock(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n", intr_coalescing_count, intr_coalescing_ticks); diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index d047d92a456..7f5e5d96327 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -46,14 +46,19 @@ #define CR_BUSY 0x0001 #define CR_START 0x0001 #define CR_WR_RDN 0x0002 +#define CPHY_TX_INPUT_STS 0x2001 #define CPHY_RX_INPUT_STS 0x2002 -#define CPHY_SATA_OVERRIDE 0x4000 -#define CPHY_OVERRIDE 0x2005 +#define CPHY_SATA_TX_OVERRIDE 0x8000 +#define CPHY_SATA_RX_OVERRIDE 0x4000 +#define CPHY_TX_OVERRIDE 0x2004 +#define CPHY_RX_OVERRIDE 0x2005 #define SPHY_LANE 0x100 #define SPHY_HALF_RATE 0x0001 #define CPHY_SATA_DPLL_MODE 0x0700 #define CPHY_SATA_DPLL_SHIFT 8 #define CPHY_SATA_DPLL_RESET (1 << 11) +#define CPHY_SATA_TX_ATTEN 0x1c00 +#define CPHY_SATA_TX_ATTEN_SHIFT 10 #define CPHY_PHY_COUNT 6 #define CPHY_LANE_COUNT 4 #define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) @@ -66,6 +71,7 @@ struct phy_lane_info { void __iomem *phy_base; u8 lane_mapping; u8 phy_devs; + u8 tx_atten; }; static struct phy_lane_info port_data[CPHY_PORT_COUNT]; @@ -76,9 +82,11 @@ static DEFINE_SPINLOCK(sgpio_lock); #define SGPIO_PINS 3 #define SGPIO_PORTS 8 -/* can be cast as an ahci_host_priv for compatibility with most functions */ struct ecx_plat_data { u32 n_ports; + /* number of extra clocks that the SGPIO PIC controller expects */ + u32 pre_clocks; + u32 post_clocks; unsigned sgpio_gpio[SGPIO_PINS]; u32 sgpio_pattern; u32 port_to_sgpio[SGPIO_PORTS]; @@ -86,11 +94,11 @@ struct ecx_plat_data { #define SGPIO_SIGNALS 3 #define ECX_ACTIVITY_BITS 0x300000 -#define ECX_ACTIVITY_SHIFT 2 +#define ECX_ACTIVITY_SHIFT 0 #define ECX_LOCATE_BITS 0x80000 #define ECX_LOCATE_SHIFT 1 #define ECX_FAULT_BITS 0x400000 -#define ECX_FAULT_SHIFT 0 +#define ECX_FAULT_SHIFT 2 static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port, u32 shift) { @@ -155,6 +163,9 @@ static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state, spin_lock_irqsave(&sgpio_lock, flags); ecx_parse_sgpio(pdata, ap->port_no, state); sgpio_out = pdata->sgpio_pattern; + for (i = 0; i < pdata->pre_clocks; i++) + ecx_led_cycle_clock(pdata); + gpio_set_value(pdata->sgpio_gpio[SLOAD], 1); ecx_led_cycle_clock(pdata); gpio_set_value(pdata->sgpio_gpio[SLOAD], 0); @@ -167,6 +178,8 @@ static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state, sgpio_out >>= 1; ecx_led_cycle_clock(pdata); } + for (i = 0; i < pdata->post_clocks; i++) + ecx_led_cycle_clock(pdata); /* save off new led state for port/slot */ emp->led_state = state; @@ -201,6 +214,11 @@ static void highbank_set_em_messages(struct device *dev, of_property_read_u32_array(np, "calxeda,led-order", pdata->port_to_sgpio, pdata->n_ports); + if (of_property_read_u32(np, "calxeda,pre-clocks", &pdata->pre_clocks)) + pdata->pre_clocks = 0; + if (of_property_read_u32(np, "calxeda,post-clocks", + &pdata->post_clocks)) + pdata->post_clocks = 0; /* store em_loc */ hpriv->em_loc = 0; @@ -259,8 +277,27 @@ static void highbank_cphy_disable_overrides(u8 sata_port) if (unlikely(port_data[sata_port].phy_base == NULL)) return; tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); - tmp &= ~CPHY_SATA_OVERRIDE; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + tmp &= ~CPHY_SATA_RX_OVERRIDE; + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); +} + +static void cphy_override_tx_attenuation(u8 sata_port, u32 val) +{ + u8 lane = port_data[sata_port].lane_mapping; + u32 tmp; + + if (val & 0x8) + return; + + tmp = combo_phy_read(sata_port, CPHY_TX_INPUT_STS + lane * SPHY_LANE); + tmp &= ~CPHY_SATA_TX_OVERRIDE; + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); + + tmp |= CPHY_SATA_TX_OVERRIDE; + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); + + tmp |= (val << CPHY_SATA_TX_ATTEN_SHIFT) & CPHY_SATA_TX_ATTEN; + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); } static void cphy_override_rx_mode(u8 sata_port, u32 val) @@ -268,21 +305,21 @@ static void cphy_override_rx_mode(u8 sata_port, u32 val) u8 lane = port_data[sata_port].lane_mapping; u32 tmp; tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); - tmp &= ~CPHY_SATA_OVERRIDE; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + tmp &= ~CPHY_SATA_RX_OVERRIDE; + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); - tmp |= CPHY_SATA_OVERRIDE; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + tmp |= CPHY_SATA_RX_OVERRIDE; + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); tmp &= ~CPHY_SATA_DPLL_MODE; tmp |= val << CPHY_SATA_DPLL_SHIFT; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); tmp |= CPHY_SATA_DPLL_RESET; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); tmp &= ~CPHY_SATA_DPLL_RESET; - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); msleep(15); } @@ -299,16 +336,20 @@ static void highbank_cphy_override_lane(u8 sata_port) lane * SPHY_LANE); } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); cphy_override_rx_mode(sata_port, 3); + cphy_override_tx_attenuation(sata_port, port_data[sata_port].tx_atten); } static int highbank_initialize_phys(struct device *dev, void __iomem *addr) { struct device_node *sata_node = dev->of_node; - int phy_count = 0, phy, port = 0; + int phy_count = 0, phy, port = 0, i; void __iomem *cphy_base[CPHY_PHY_COUNT]; struct device_node *phy_nodes[CPHY_PHY_COUNT]; + u32 tx_atten[CPHY_PORT_COUNT]; + memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); + memset(tx_atten, 0xff, CPHY_PORT_COUNT); do { u32 tmp; @@ -336,6 +377,10 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr) of_node_put(phy_data.np); port += 1; } while (port < CPHY_PORT_COUNT); + of_property_read_u32_array(sata_node, "calxeda,tx-atten", + tx_atten, port); + for (i = 0; i < port; i++) + port_data[i].tx_atten = (u8) tx_atten[i]; return 0; } @@ -479,6 +524,9 @@ static int ahci_highbank_probe(struct platform_device *pdev) if (hpriv->cap & HOST_CAP_PMP) pi.flags |= ATA_FLAG_PMP; + if (hpriv->cap & HOST_CAP_64) + dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); + /* CAP.NP sometimes indicate the index of the last enabled * port, at other times, that of the last possible port, so * determining the maximum port number requires looking at diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index e4513174824..5c54d957370 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -6,6 +6,18 @@ * * This file is released under GPL v2. * + * **** 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). @@ -807,6 +819,8 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 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); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 35c6b6d09c2..56be3181989 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -553,10 +553,15 @@ struct mv_host_priv { u32 irq_mask_offset; u32 unmask_all_irqs; -#if defined(CONFIG_HAVE_CLK) + /* + * Needed on some devices that require their clocks to be enabled. + * These are optional: if the platform device does not have any + * clocks, they won't be used. Also, if the underlying hardware + * does not support the common clock framework (CONFIG_HAVE_CLK=n), + * all the clock operations become no-ops (see clk.h). + */ struct clk *clk; struct clk **port_clks; -#endif /* * These consistent DMA memory pools give us guaranteed * alignment for hardware-accessed data structures, @@ -4032,9 +4037,7 @@ static int mv_platform_probe(struct platform_device *pdev) struct resource *res; int n_ports = 0, irq = 0; int rc; -#if defined(CONFIG_HAVE_CLK) int port; -#endif ata_print_version_once(&pdev->dev, DRV_VERSION); @@ -4058,7 +4061,7 @@ static int mv_platform_probe(struct platform_device *pdev) of_property_read_u32(pdev->dev.of_node, "nr-ports", &n_ports); irq = irq_of_parse_and_map(pdev->dev.of_node, 0); } else { - mv_platform_data = pdev->dev.platform_data; + mv_platform_data = dev_get_platdata(&pdev->dev); n_ports = mv_platform_data->n_ports; irq = platform_get_irq(pdev, 0); } @@ -4068,13 +4071,11 @@ static int mv_platform_probe(struct platform_device *pdev) if (!host || !hpriv) return -ENOMEM; -#if defined(CONFIG_HAVE_CLK) hpriv->port_clks = devm_kzalloc(&pdev->dev, sizeof(struct clk *) * n_ports, GFP_KERNEL); if (!hpriv->port_clks) return -ENOMEM; -#endif host->private_data = hpriv; hpriv->n_ports = n_ports; hpriv->board_idx = chip_soc; @@ -4084,7 +4085,6 @@ static int mv_platform_probe(struct platform_device *pdev) resource_size(res)); hpriv->base -= SATAHC0_REG_BASE; -#if defined(CONFIG_HAVE_CLK) hpriv->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(hpriv->clk)) dev_notice(&pdev->dev, "cannot get optional clkdev\n"); @@ -4098,7 +4098,6 @@ static int mv_platform_probe(struct platform_device *pdev) if (!IS_ERR(hpriv->port_clks[port])) clk_prepare_enable(hpriv->port_clks[port]); } -#endif /* * (Re-)program MBUS remapping windows if we are asked to. @@ -4124,7 +4123,6 @@ static int mv_platform_probe(struct platform_device *pdev) return 0; err: -#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(hpriv->clk)) { clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); @@ -4135,7 +4133,6 @@ err: clk_put(hpriv->port_clks[port]); } } -#endif return rc; } @@ -4151,13 +4148,10 @@ err: static int mv_platform_remove(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); -#if defined(CONFIG_HAVE_CLK) struct mv_host_priv *hpriv = host->private_data; int port; -#endif ata_host_detach(host); -#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(hpriv->clk)) { clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); @@ -4168,7 +4162,6 @@ static int mv_platform_remove(struct platform_device *pdev) clk_put(hpriv->port_clks[port]); } } -#endif return 0; } @@ -4428,9 +4421,6 @@ static int mv_pci_device_resume(struct pci_dev *pdev) #endif #endif -static int mv_platform_probe(struct platform_device *pdev); -static int mv_platform_remove(struct platform_device *pdev); - static int __init mv_init(void) { int rc = -ENODEV; diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index 8108eb06544..c2d95e9fb97 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -778,10 +778,6 @@ static int sata_rcar_probe(struct platform_device *pdev) int irq; int ret = 0; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem == NULL) - return -EINVAL; - irq = platform_get_irq(pdev, 0); if (irq <= 0) return -EINVAL; @@ -807,6 +803,7 @@ static int sata_rcar_probe(struct platform_device *pdev) host->private_data = priv; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); |