From 273b542e7aa7d692ef7fddf63de9906e6827ccc3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 May 2016 12:35:03 +0100 Subject: pata_atiixp: fix trivial indentation misalignment on if statement Remove extraneous space on if statement and on the following line, trivial fix, no functional change Signed-off-by: Colin Ian King Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 970f776..49d705c 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -183,8 +183,8 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev) * We must now look at the PIO mode situation. We may need to * adjust the PIO mode to keep the timings acceptable */ - if (adev->dma_mode >= XFER_MW_DMA_2) - wanted_pio = 4; + if (adev->dma_mode >= XFER_MW_DMA_2) + wanted_pio = 4; else if (adev->dma_mode == XFER_MW_DMA_1) wanted_pio = 3; else if (adev->dma_mode == XFER_MW_DMA_0) -- cgit v0.10.2 From d2abf98e1feecfe333c2077f541986dedbe47cdb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 22 May 2016 11:06:01 +0200 Subject: MAINTAINERS: Add file patterns for ata device tree bindings Submitters of device tree binding documentation may forget to CC the subsystem maintainer if this is missing. Signed-off-by: Geert Uytterhoeven Cc: Tejun Heo Cc: linux-ide@vger.kernel.org Signed-off-by: Tejun Heo diff --git a/MAINTAINERS b/MAINTAINERS index 81e9c98..b4ebb67 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6732,6 +6732,7 @@ S: Maintained F: drivers/ata/ F: include/linux/ata.h F: include/linux/libata.h +F: Documentation/devicetree/bindings/ata/ LIBATA PATA ARASAN COMPACT FLASH CONTROLLER M: Viresh Kumar -- cgit v0.10.2 From 5219d6530ef0bca37bd8c4c637908638ce205ff9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 18 May 2016 16:11:28 -0400 Subject: ata: Use IS_ENABLED() instead of checking for built-in or module The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a83bbcc..90eabaf 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -580,7 +580,7 @@ static struct pci_driver ahci_pci_driver = { }, }; -#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) +#if IS_ENABLED(CONFIG_PATA_MARVELL) static int marvell_enable; #else static int marvell_enable = 1; diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index ae9feb1..ff468a6f 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -146,7 +146,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i if (pdev->device == 0x6101) ppi[1] = &ata_dummy_port_info; -#if defined(CONFIG_SATA_AHCI) || defined(CONFIG_SATA_AHCI_MODULE) +#if IS_ENABLED(CONFIG_SATA_AHCI) if (!marvell_pata_active(pdev)) { printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n"); return -ENODEV; -- cgit v0.10.2 From dc5a78ec8efb74964b77982b2ea79434ed8941e5 Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:29 -0400 Subject: dt-bindings: ata: rename brcm, sata-brcmstb.txt to brcm, sata-brcm.txt Renames the dt bindings document of Broadcom STB ahci driver to common Broadcom ahci driver bindings document Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt new file mode 100644 index 0000000..126ee13 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt @@ -0,0 +1,36 @@ +* Broadcom SATA3 AHCI Controller + +SATA nodes are defined to describe on-chip Serial ATA controllers. +Each SATA controller should have its own node. + +Required properties: +- compatible : should be one or more of + "brcm,bcm7425-ahci" + "brcm,bcm7445-ahci" + "brcm,sata3-ahci" +- reg : register mappings for AHCI and SATA_TOP_CTRL +- reg-names : "ahci" and "top-ctrl" +- interrupts : interrupt mapping for SATA IRQ + +Also see ahci-platform.txt. + +Example: + + sata@f045a000 { + compatible = "brcm,bcm7445-ahci", "brcm,sata3-ahci"; + reg = <0xf045a000 0xa9c>, <0xf0458040 0x24>; + reg-names = "ahci", "top-ctrl"; + interrupts = <0 30 0>; + #address-cells = <1>; + #size-cells = <0>; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy 0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy 1>; + }; + }; diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt b/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt deleted file mode 100644 index 6087283..0000000 --- a/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Broadcom SATA3 AHCI Controller for STB - -SATA nodes are defined to describe on-chip Serial ATA controllers. -Each SATA controller should have its own node. - -Required properties: -- compatible : should be one or more of - "brcm,bcm7425-ahci" - "brcm,bcm7445-ahci" - "brcm,sata3-ahci" -- reg : register mappings for AHCI and SATA_TOP_CTRL -- reg-names : "ahci" and "top-ctrl" -- interrupts : interrupt mapping for SATA IRQ - -Also see ahci-platform.txt. - -Example: - - sata@f045a000 { - compatible = "brcm,bcm7445-ahci", "brcm,sata3-ahci"; - reg = <0xf045a000 0xa9c>, <0xf0458040 0x24>; - reg-names = "ahci", "top-ctrl"; - interrupts = <0 30 0>; - #address-cells = <1>; - #size-cells = <0>; - - sata0: sata-port@0 { - reg = <0>; - phys = <&sata_phy 0>; - }; - - sata1: sata-port@1 { - reg = <1>; - phys = <&sata_phy 1>; - }; - }; -- cgit v0.10.2 From 5724ad14cc85513a55711d6b4d6142b8e188c7e2 Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:30 -0400 Subject: dt-bindings: ata: add support for Broadcom NSP SoC ahci Add support for Broadcom NSP SoC ahci Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt index 126ee13..0a5b3b4 100644 --- a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt +++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt @@ -7,6 +7,7 @@ Required properties: - compatible : should be one or more of "brcm,bcm7425-ahci" "brcm,bcm7445-ahci" + "brcm,bcm-nsp-ahci" "brcm,sata3-ahci" - reg : register mappings for AHCI and SATA_TOP_CTRL - reg-names : "ahci" and "top-ctrl" -- cgit v0.10.2 From a55448d1c01ca4b4e94e1d51249feee4aa315d6d Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:31 -0400 Subject: dt-bindings: phy: Add documentation for NSP SATA PHY Add documentation for SATA PHY available in Broadcom's NSP SoC. Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt index d023120..6ccce09 100644 --- a/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt @@ -5,6 +5,7 @@ Required properties: "brcm,bcm7425-sata-phy" "brcm,bcm7445-sata-phy" "brcm,iproc-ns2-sata-phy" + "brcm,iproc-nsp-sata-phy" "brcm,phy-sata3" - address-cells: should be 1 - size-cells: should be 0 @@ -22,7 +23,8 @@ Sub-nodes required properties: Sub-nodes optional properties: - brcm,enable-ssc: use spread spectrum clocking (SSC) on this port - This property is not applicable for "brcm,iproc-ns2-sata-phy". + This property is not applicable for "brcm,iproc-ns2-sata-phy" and + "brcm,iproc-nsp-sata-phy". Example: sata-phy@f0458100 { -- cgit v0.10.2 From eba68f829794a1c3eb7a78d53c652daa303580ed Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:32 -0400 Subject: ata: ahci_brcmstb: rename to support across Broadcom SoC's Rename the existing Broadcom STB ahci driver to common Broadcom SATA3 driver to share this across Broadcom SoCs. Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index e2dc4c0..8fe06e6 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -98,12 +98,12 @@ config SATA_AHCI_PLATFORM If unsure, say N. -config AHCI_BRCMSTB - tristate "Broadcom STB AHCI SATA support" +config AHCI_BRCM + tristate "Broadcom AHCI SATA support" depends on ARCH_BRCMSTB || BMIPS_GENERIC help This option enables support for the AHCI SATA3 controller found on - STB SoC's. + Broadcom SoC's. If unsure, say N. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 0b2afb7..a46e6b7 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -11,7 +11,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_BRCMSTB) += ahci_brcmstb.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_BRCM) += ahci_brcm.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_CEVA) += ahci_ceva.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c new file mode 100644 index 0000000..e87bcec --- /dev/null +++ b/drivers/ata/ahci_brcm.c @@ -0,0 +1,380 @@ +/* + * Broadcom SATA3 AHCI Controller Driver + * + * Copyright © 2009-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ahci.h" + +#define DRV_NAME "brcm-ahci" + +#define SATA_TOP_CTRL_VERSION 0x0 +#define SATA_TOP_CTRL_BUS_CTRL 0x4 + #define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */ + #define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */ + #define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */ + #define PIODATA_ENDIAN_SHIFT 6 + #define ENDIAN_SWAP_NONE 0 + #define ENDIAN_SWAP_FULL 2 + #define OVERRIDE_HWINIT BIT(16) +#define SATA_TOP_CTRL_TP_CTRL 0x8 +#define SATA_TOP_CTRL_PHY_CTRL 0xc + #define SATA_TOP_CTRL_PHY_CTRL_1 0x0 + #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14) + #define SATA_TOP_CTRL_PHY_CTRL_2 0x4 + #define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0) + #define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1) + #define SATA_TOP_CTRL_2_SW_RST_RX BIT(2) + #define SATA_TOP_CTRL_2_SW_RST_TX BIT(3) + #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14) + #define SATA_TOP_CTRL_PHY_OFFS 0x8 + #define SATA_TOP_MAX_PHYS 2 + +#define SATA_FIRST_PORT_CTRL 0x700 +#define SATA_NEXT_PORT_CTRL_OFFSET 0x80 +#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18) + +/* On big-endian MIPS, buses are reversed to big endian, so switch them back */ +#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN) +#define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */ +#define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */ +#else +#define DATA_ENDIAN 0 +#define MMIO_ENDIAN 0 +#endif + +#define BUS_CTRL_ENDIAN_CONF \ + ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \ + (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \ + (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT)) + +enum brcm_ahci_quirks { + BRCM_AHCI_QUIRK_NO_NCQ = BIT(0), + BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1), +}; + +struct brcm_ahci_priv { + struct device *dev; + void __iomem *top_ctrl; + u32 port_mask; + u32 quirks; +}; + +static const struct ata_port_info ahci_brcm_port_info = { + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, + .link_flags = ATA_LFLAG_NO_DB_DELAY, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_platform_ops, +}; + +static inline u32 brcm_sata_readreg(void __iomem *addr) +{ + /* + * MIPS endianness is configured by boot strap, which also reverses all + * bus endianness (i.e., big-endian CPU + big endian bus ==> native + * endian I/O). + * + * Other architectures (e.g., ARM) either do not support big endian, or + * else leave I/O in little endian mode. + */ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + return __raw_readl(addr); + else + return readl_relaxed(addr); +} + +static inline void brcm_sata_writereg(u32 val, void __iomem *addr) +{ + /* See brcm_sata_readreg() comments */ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + __raw_writel(val, addr); + else + writel_relaxed(val, addr); +} + +static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv) +{ + struct brcm_ahci_priv *priv = hpriv->plat_data; + u32 bus_ctrl, port_ctrl, host_caps; + int i; + + /* Enable support for ALPM */ + bus_ctrl = brcm_sata_readreg(priv->top_ctrl + + SATA_TOP_CTRL_BUS_CTRL); + brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT, + priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + host_caps = readl(hpriv->mmio + HOST_CAP); + writel(host_caps | HOST_CAP_ALPM, hpriv->mmio); + brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + + /* + * Adjust timeout to allow PLL sufficient time to lock while waking + * up from slumber mode. + */ + for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL; + i < SATA_TOP_MAX_PHYS; + i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) { + if (priv->port_mask & BIT(i)) + writel(0xff1003fc, + hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl)); + } +} + +static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port) +{ + void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL + + (port * SATA_TOP_CTRL_PHY_OFFS); + void __iomem *p; + u32 reg; + + if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) + return; + + /* clear PHY_DEFAULT_POWER_STATE */ + p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1; + reg = brcm_sata_readreg(p); + reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE; + brcm_sata_writereg(reg, p); + + /* reset the PHY digital logic */ + p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2; + reg = brcm_sata_readreg(p); + reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB | + SATA_TOP_CTRL_2_SW_RST_RX); + reg |= SATA_TOP_CTRL_2_SW_RST_TX; + brcm_sata_writereg(reg, p); + reg = brcm_sata_readreg(p); + reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET; + brcm_sata_writereg(reg, p); + reg = brcm_sata_readreg(p); + reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET; + brcm_sata_writereg(reg, p); + (void)brcm_sata_readreg(p); +} + +static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port) +{ + void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL + + (port * SATA_TOP_CTRL_PHY_OFFS); + void __iomem *p; + u32 reg; + + if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) + return; + + /* power-off the PHY digital logic */ + p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2; + reg = brcm_sata_readreg(p); + reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB | + SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX | + SATA_TOP_CTRL_2_PHY_GLOBAL_RESET); + brcm_sata_writereg(reg, p); + + /* set PHY_DEFAULT_POWER_STATE */ + p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1; + reg = brcm_sata_readreg(p); + reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE; + brcm_sata_writereg(reg, p); +} + +static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv) +{ + int i; + + for (i = 0; i < SATA_TOP_MAX_PHYS; i++) + if (priv->port_mask & BIT(i)) + brcm_sata_phy_enable(priv, i); +} + +static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv) +{ + int i; + + for (i = 0; i < SATA_TOP_MAX_PHYS; i++) + if (priv->port_mask & BIT(i)) + brcm_sata_phy_disable(priv, i); +} + +static u32 brcm_ahci_get_portmask(struct platform_device *pdev, + struct brcm_ahci_priv *priv) +{ + void __iomem *ahci; + struct resource *res; + u32 impl; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"); + ahci = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ahci)) + return 0; + + impl = readl(ahci + HOST_PORTS_IMPL); + + if (fls(impl) > SATA_TOP_MAX_PHYS) + dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n", + impl); + else if (!impl) + dev_info(priv->dev, "no ports found\n"); + + devm_iounmap(&pdev->dev, ahci); + devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + + return impl; +} + +static void brcm_sata_init(struct brcm_ahci_priv *priv) +{ + /* Configure endianness */ + brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF, + priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); +} + +#ifdef CONFIG_PM_SLEEP +static int brcm_ahci_suspend(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + struct brcm_ahci_priv *priv = hpriv->plat_data; + int ret; + + ret = ahci_platform_suspend(dev); + brcm_sata_phys_disable(priv); + return ret; +} + +static int brcm_ahci_resume(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + struct brcm_ahci_priv *priv = hpriv->plat_data; + + brcm_sata_init(priv); + brcm_sata_phys_enable(priv); + brcm_sata_alpm_init(hpriv); + return ahci_platform_resume(dev); +} +#endif + +static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT(DRV_NAME), +}; + +static int brcm_ahci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct brcm_ahci_priv *priv; + struct ahci_host_priv *hpriv; + struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->dev = dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl"); + priv->top_ctrl = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->top_ctrl)) + return PTR_ERR(priv->top_ctrl); + + if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) { + priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; + priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; + } + + brcm_sata_init(priv); + + priv->port_mask = brcm_ahci_get_portmask(pdev, priv); + if (!priv->port_mask) + return -ENODEV; + + brcm_sata_phys_enable(priv); + + hpriv = ahci_platform_get_resources(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); + + ret = ahci_platform_enable_resources(hpriv); + if (ret) + return ret; + + if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ) + hpriv->flags |= AHCI_HFLAG_NO_NCQ; + + ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, + &ahci_platform_sht); + if (ret) + return ret; + + dev_info(dev, "Broadcom AHCI SATA3 registered\n"); + + return 0; +} + +static int brcm_ahci_remove(struct platform_device *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct ahci_host_priv *hpriv = host->private_data; + struct brcm_ahci_priv *priv = hpriv->plat_data; + int ret; + + ret = ata_platform_remove_one(pdev); + if (ret) + return ret; + + brcm_sata_phys_disable(priv); + + return 0; +} + +static const struct of_device_id ahci_of_match[] = { + {.compatible = "brcm,bcm7425-ahci"}, + {.compatible = "brcm,bcm7445-ahci"}, + {}, +}; +MODULE_DEVICE_TABLE(of, ahci_of_match); + +static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume); + +static struct platform_driver brcm_ahci_driver = { + .probe = brcm_ahci_probe, + .remove = brcm_ahci_remove, + .driver = { + .name = DRV_NAME, + .of_match_table = ahci_of_match, + .pm = &ahci_brcm_pm_ops, + }, +}; +module_platform_driver(brcm_ahci_driver); + +MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver"); +MODULE_AUTHOR("Brian Norris"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sata-brcmstb"); diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c deleted file mode 100644 index e87bcec..0000000 --- a/drivers/ata/ahci_brcmstb.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Broadcom SATA3 AHCI Controller Driver - * - * Copyright © 2009-2015 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ahci.h" - -#define DRV_NAME "brcm-ahci" - -#define SATA_TOP_CTRL_VERSION 0x0 -#define SATA_TOP_CTRL_BUS_CTRL 0x4 - #define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */ - #define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */ - #define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */ - #define PIODATA_ENDIAN_SHIFT 6 - #define ENDIAN_SWAP_NONE 0 - #define ENDIAN_SWAP_FULL 2 - #define OVERRIDE_HWINIT BIT(16) -#define SATA_TOP_CTRL_TP_CTRL 0x8 -#define SATA_TOP_CTRL_PHY_CTRL 0xc - #define SATA_TOP_CTRL_PHY_CTRL_1 0x0 - #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14) - #define SATA_TOP_CTRL_PHY_CTRL_2 0x4 - #define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0) - #define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1) - #define SATA_TOP_CTRL_2_SW_RST_RX BIT(2) - #define SATA_TOP_CTRL_2_SW_RST_TX BIT(3) - #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14) - #define SATA_TOP_CTRL_PHY_OFFS 0x8 - #define SATA_TOP_MAX_PHYS 2 - -#define SATA_FIRST_PORT_CTRL 0x700 -#define SATA_NEXT_PORT_CTRL_OFFSET 0x80 -#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18) - -/* On big-endian MIPS, buses are reversed to big endian, so switch them back */ -#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN) -#define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */ -#define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */ -#else -#define DATA_ENDIAN 0 -#define MMIO_ENDIAN 0 -#endif - -#define BUS_CTRL_ENDIAN_CONF \ - ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \ - (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \ - (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT)) - -enum brcm_ahci_quirks { - BRCM_AHCI_QUIRK_NO_NCQ = BIT(0), - BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1), -}; - -struct brcm_ahci_priv { - struct device *dev; - void __iomem *top_ctrl; - u32 port_mask; - u32 quirks; -}; - -static const struct ata_port_info ahci_brcm_port_info = { - .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, - .link_flags = ATA_LFLAG_NO_DB_DELAY, - .pio_mask = ATA_PIO4, - .udma_mask = ATA_UDMA6, - .port_ops = &ahci_platform_ops, -}; - -static inline u32 brcm_sata_readreg(void __iomem *addr) -{ - /* - * MIPS endianness is configured by boot strap, which also reverses all - * bus endianness (i.e., big-endian CPU + big endian bus ==> native - * endian I/O). - * - * Other architectures (e.g., ARM) either do not support big endian, or - * else leave I/O in little endian mode. - */ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) - return __raw_readl(addr); - else - return readl_relaxed(addr); -} - -static inline void brcm_sata_writereg(u32 val, void __iomem *addr) -{ - /* See brcm_sata_readreg() comments */ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) - __raw_writel(val, addr); - else - writel_relaxed(val, addr); -} - -static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv) -{ - struct brcm_ahci_priv *priv = hpriv->plat_data; - u32 bus_ctrl, port_ctrl, host_caps; - int i; - - /* Enable support for ALPM */ - bus_ctrl = brcm_sata_readreg(priv->top_ctrl + - SATA_TOP_CTRL_BUS_CTRL); - brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT, - priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); - host_caps = readl(hpriv->mmio + HOST_CAP); - writel(host_caps | HOST_CAP_ALPM, hpriv->mmio); - brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); - - /* - * Adjust timeout to allow PLL sufficient time to lock while waking - * up from slumber mode. - */ - for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL; - i < SATA_TOP_MAX_PHYS; - i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) { - if (priv->port_mask & BIT(i)) - writel(0xff1003fc, - hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl)); - } -} - -static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port) -{ - void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL + - (port * SATA_TOP_CTRL_PHY_OFFS); - void __iomem *p; - u32 reg; - - if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) - return; - - /* clear PHY_DEFAULT_POWER_STATE */ - p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1; - reg = brcm_sata_readreg(p); - reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE; - brcm_sata_writereg(reg, p); - - /* reset the PHY digital logic */ - p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2; - reg = brcm_sata_readreg(p); - reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB | - SATA_TOP_CTRL_2_SW_RST_RX); - reg |= SATA_TOP_CTRL_2_SW_RST_TX; - brcm_sata_writereg(reg, p); - reg = brcm_sata_readreg(p); - reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET; - brcm_sata_writereg(reg, p); - reg = brcm_sata_readreg(p); - reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET; - brcm_sata_writereg(reg, p); - (void)brcm_sata_readreg(p); -} - -static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port) -{ - void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL + - (port * SATA_TOP_CTRL_PHY_OFFS); - void __iomem *p; - u32 reg; - - if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) - return; - - /* power-off the PHY digital logic */ - p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2; - reg = brcm_sata_readreg(p); - reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB | - SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX | - SATA_TOP_CTRL_2_PHY_GLOBAL_RESET); - brcm_sata_writereg(reg, p); - - /* set PHY_DEFAULT_POWER_STATE */ - p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1; - reg = brcm_sata_readreg(p); - reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE; - brcm_sata_writereg(reg, p); -} - -static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv) -{ - int i; - - for (i = 0; i < SATA_TOP_MAX_PHYS; i++) - if (priv->port_mask & BIT(i)) - brcm_sata_phy_enable(priv, i); -} - -static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv) -{ - int i; - - for (i = 0; i < SATA_TOP_MAX_PHYS; i++) - if (priv->port_mask & BIT(i)) - brcm_sata_phy_disable(priv, i); -} - -static u32 brcm_ahci_get_portmask(struct platform_device *pdev, - struct brcm_ahci_priv *priv) -{ - void __iomem *ahci; - struct resource *res; - u32 impl; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"); - ahci = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ahci)) - return 0; - - impl = readl(ahci + HOST_PORTS_IMPL); - - if (fls(impl) > SATA_TOP_MAX_PHYS) - dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n", - impl); - else if (!impl) - dev_info(priv->dev, "no ports found\n"); - - devm_iounmap(&pdev->dev, ahci); - devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); - - return impl; -} - -static void brcm_sata_init(struct brcm_ahci_priv *priv) -{ - /* Configure endianness */ - brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF, - priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); -} - -#ifdef CONFIG_PM_SLEEP -static int brcm_ahci_suspend(struct device *dev) -{ - struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; - struct brcm_ahci_priv *priv = hpriv->plat_data; - int ret; - - ret = ahci_platform_suspend(dev); - brcm_sata_phys_disable(priv); - return ret; -} - -static int brcm_ahci_resume(struct device *dev) -{ - struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; - struct brcm_ahci_priv *priv = hpriv->plat_data; - - brcm_sata_init(priv); - brcm_sata_phys_enable(priv); - brcm_sata_alpm_init(hpriv); - return ahci_platform_resume(dev); -} -#endif - -static struct scsi_host_template ahci_platform_sht = { - AHCI_SHT(DRV_NAME), -}; - -static int brcm_ahci_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct brcm_ahci_priv *priv; - struct ahci_host_priv *hpriv; - struct resource *res; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - priv->dev = dev; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl"); - priv->top_ctrl = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->top_ctrl)) - return PTR_ERR(priv->top_ctrl); - - if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) { - priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; - priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; - } - - brcm_sata_init(priv); - - priv->port_mask = brcm_ahci_get_portmask(pdev, priv); - if (!priv->port_mask) - return -ENODEV; - - brcm_sata_phys_enable(priv); - - hpriv = ahci_platform_get_resources(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); - - ret = ahci_platform_enable_resources(hpriv); - if (ret) - return ret; - - if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ) - hpriv->flags |= AHCI_HFLAG_NO_NCQ; - - ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, - &ahci_platform_sht); - if (ret) - return ret; - - dev_info(dev, "Broadcom AHCI SATA3 registered\n"); - - return 0; -} - -static int brcm_ahci_remove(struct platform_device *pdev) -{ - struct ata_host *host = dev_get_drvdata(&pdev->dev); - struct ahci_host_priv *hpriv = host->private_data; - struct brcm_ahci_priv *priv = hpriv->plat_data; - int ret; - - ret = ata_platform_remove_one(pdev); - if (ret) - return ret; - - brcm_sata_phys_disable(priv); - - return 0; -} - -static const struct of_device_id ahci_of_match[] = { - {.compatible = "brcm,bcm7425-ahci"}, - {.compatible = "brcm,bcm7445-ahci"}, - {}, -}; -MODULE_DEVICE_TABLE(of, ahci_of_match); - -static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume); - -static struct platform_driver brcm_ahci_driver = { - .probe = brcm_ahci_probe, - .remove = brcm_ahci_remove, - .driver = { - .name = DRV_NAME, - .of_match_table = ahci_of_match, - .pm = &ahci_brcm_pm_ops, - }, -}; -module_platform_driver(brcm_ahci_driver); - -MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver"); -MODULE_AUTHOR("Brian Norris"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:sata-brcmstb"); -- cgit v0.10.2 From 3ee2e6dcaa3570df6f7ceeda6d8342bc47cf6b1c Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:33 -0400 Subject: ata: ahci_brcm: Add support for Broadcom NSP SoC Add SATA3 support for Broadcom NSP SoC Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 8fe06e6..2c8be74 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -100,7 +100,7 @@ config SATA_AHCI_PLATFORM config AHCI_BRCM tristate "Broadcom AHCI SATA support" - depends on ARCH_BRCMSTB || BMIPS_GENERIC + depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM_NSP help This option enables support for the AHCI SATA3 controller found on Broadcom SoC's. diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index e87bcec..6f8a734 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -71,6 +71,12 @@ (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \ (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT)) +enum brcm_ahci_version { + BRCM_SATA_BCM7425 = 1, + BRCM_SATA_BCM7445, + BRCM_SATA_NSP, +}; + enum brcm_ahci_quirks { BRCM_AHCI_QUIRK_NO_NCQ = BIT(0), BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1), @@ -81,6 +87,7 @@ struct brcm_ahci_priv { void __iomem *top_ctrl; u32 port_mask; u32 quirks; + enum brcm_ahci_version version; }; static const struct ata_port_info ahci_brcm_port_info = { @@ -247,9 +254,19 @@ static u32 brcm_ahci_get_portmask(struct platform_device *pdev, static void brcm_sata_init(struct brcm_ahci_priv *priv) { + void __iomem *ctrl = priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL; + /* Configure endianness */ - brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF, - priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + if (priv->version == BRCM_SATA_NSP) { + u32 data = brcm_sata_readreg(ctrl); + + data &= ~((0x03 << DMADATA_ENDIAN_SHIFT) | + (0x03 << DMADESC_ENDIAN_SHIFT)); + data |= (0x02 << DMADATA_ENDIAN_SHIFT) | + (0x02 << DMADESC_ENDIAN_SHIFT); + brcm_sata_writereg(data, ctrl); + } else + brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF, ctrl); } #ifdef CONFIG_PM_SLEEP @@ -282,8 +299,17 @@ static struct scsi_host_template ahci_platform_sht = { AHCI_SHT(DRV_NAME), }; +static const struct of_device_id ahci_of_match[] = { + {.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425}, + {.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445}, + {.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP}, + {}, +}; +MODULE_DEVICE_TABLE(of, ahci_of_match); + static int brcm_ahci_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; struct device *dev = &pdev->dev; struct brcm_ahci_priv *priv; struct ahci_host_priv *hpriv; @@ -293,6 +319,12 @@ static int brcm_ahci_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + + of_id = of_match_node(ahci_of_match, pdev->dev.of_node); + if (!of_id) + return -ENODEV; + + priv->version = (enum brcm_ahci_version)of_id->data; priv->dev = dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl"); @@ -300,7 +332,8 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (IS_ERR(priv->top_ctrl)) return PTR_ERR(priv->top_ctrl); - if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) { + if ((priv->version == BRCM_SATA_BCM7425) || + (priv->version == BRCM_SATA_NSP)) { priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; } @@ -354,13 +387,6 @@ static int brcm_ahci_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ahci_of_match[] = { - {.compatible = "brcm,bcm7425-ahci"}, - {.compatible = "brcm,bcm7445-ahci"}, - {}, -}; -MODULE_DEVICE_TABLE(of, ahci_of_match); - static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume); static struct platform_driver brcm_ahci_driver = { -- cgit v0.10.2 From 024812889ad1c2d6c718feb4acdc2a7828b82e64 Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:34 -0400 Subject: phy: Add SATA3 PHY support for Broadcom NSP SoC This patch adds support for Broadcom NSP SATA3 PHY in existing Broadcom SATA PHY driver. Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c index 6c4c5cb..18d6626 100644 --- a/drivers/phy/phy-brcm-sata.c +++ b/drivers/phy/phy-brcm-sata.c @@ -45,6 +45,7 @@ enum brcm_sata_phy_version { BRCM_SATA_PHY_STB_28NM, BRCM_SATA_PHY_STB_40NM, BRCM_SATA_PHY_IPROC_NS2, + BRCM_SATA_PHY_IPROC_NSP, }; struct brcm_sata_port { @@ -73,6 +74,13 @@ enum sata_phy_regs { PLL_REG_BANK_0 = 0x050, PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, + PLLCONTROL_0_FREQ_DET_RESTART = BIT(13), + PLLCONTROL_0_FREQ_MONITOR = BIT(12), + PLLCONTROL_0_SEQ_START = BIT(15), + PLL_CAP_CONTROL = 0x85, + PLL_ACTRL2 = 0x8b, + PLL_ACTRL2_SELDIV_MASK = 0x1f, + PLL_ACTRL2_SELDIV_SHIFT = 9, PLL1_REG_BANK = 0x060, PLL1_ACTRL2 = 0x82, @@ -80,6 +88,7 @@ enum sata_phy_regs { PLL1_ACTRL4 = 0x84, OOB_REG_BANK = 0x150, + OOB1_REG_BANK = 0x160, OOB_CTRL1 = 0x80, OOB_CTRL1_BURST_MAX_MASK = 0xf, OOB_CTRL1_BURST_MAX_SHIFT = 12, @@ -271,6 +280,73 @@ static int brcm_ns2_sata_init(struct brcm_sata_port *port) return 0; } +static int brcm_nsp_sata_init(struct brcm_sata_port *port) +{ + struct brcm_sata_phy *priv = port->phy_priv; + struct device *dev = port->phy_priv->dev; + void __iomem *base = priv->phy_base; + unsigned int oob_bank; + unsigned int val, try; + + /* Configure OOB control */ + if (port->portnum == 0) + oob_bank = OOB_REG_BANK; + else if (port->portnum == 1) + oob_bank = OOB1_REG_BANK; + else + return -EINVAL; + + val = 0x0; + val |= (0x0f << OOB_CTRL1_BURST_MAX_SHIFT); + val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT); + val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT); + val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT); + brcm_sata_phy_wr(base, oob_bank, OOB_CTRL1, 0x0, val); + + val = 0x0; + val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT); + val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT); + val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT); + brcm_sata_phy_wr(base, oob_bank, OOB_CTRL2, 0x0, val); + + + brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL2, + ~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT), + 0x0c << PLL_ACTRL2_SELDIV_SHIFT); + + brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CONTROL, + 0xff0, 0x4f0); + + val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR; + brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0, + ~val, val); + val = PLLCONTROL_0_SEQ_START; + brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0, + ~val, 0); + mdelay(10); + brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0, + ~val, val); + + /* Wait for pll_seq_done bit */ + try = 50; + while (try--) { + val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK, + BLOCK0_XGXSSTATUS); + if (val & BLOCK0_XGXSSTATUS_PLL_LOCK) + break; + msleep(20); + } + if (!try) { + /* PLL did not lock; give up */ + dev_err(dev, "port%d PLL did not lock\n", port->portnum); + return -ETIMEDOUT; + } + + dev_dbg(dev, "port%d initialized\n", port->portnum); + + return 0; +} + static int brcm_sata_phy_init(struct phy *phy) { int rc; @@ -284,6 +360,9 @@ static int brcm_sata_phy_init(struct phy *phy) case BRCM_SATA_PHY_IPROC_NS2: rc = brcm_ns2_sata_init(port); break; + case BRCM_SATA_PHY_IPROC_NSP: + rc = brcm_nsp_sata_init(port); + break; default: rc = -ENODEV; }; @@ -303,6 +382,8 @@ static const struct of_device_id brcm_sata_phy_of_match[] = { .data = (void *)BRCM_SATA_PHY_STB_40NM }, { .compatible = "brcm,iproc-ns2-sata-phy", .data = (void *)BRCM_SATA_PHY_IPROC_NS2 }, + { .compatible = "brcm,iproc-nsp-sata-phy", + .data = (void *)BRCM_SATA_PHY_IPROC_NSP }, {}, }; MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); -- cgit v0.10.2 From 8dbcad020f2e7f38125ab1e73771a2bcb6564e8d Mon Sep 17 00:00:00 2001 From: Yendapally Reddy Dhananjaya Reddy Date: Thu, 16 Jun 2016 09:53:35 -0400 Subject: ARM: dts: nsp: Add sata device tree entry Add sata support to the Northstar Plus SoC device tree. Signed-off-by: Yendapally Reddy Dhananjaya Reddy Acked-by: Florian Fainelli Signed-off-by: Tejun Heo diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi index def9e78..71ececf 100644 --- a/arch/arm/boot/dts/bcm-nsp.dtsi +++ b/arch/arm/boot/dts/bcm-nsp.dtsi @@ -266,6 +266,48 @@ <0x30028 0x04>, <0x3f408 0x04>; }; + + sata_phy: sata_phy@40100 { + compatible = "brcm,iproc-nsp-sata-phy"; + reg = <0x40100 0x340>; + reg-names = "phy"; + #address-cells = <1>; + #size-cells = <0>; + + sata_phy0: sata-phy@0 { + reg = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + sata_phy1: sata-phy@1 { + reg = <1>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + sata: ahci@41000 { + compatible = "brcm,bcm-nsp-ahci"; + reg-names = "ahci", "top-ctrl"; + reg = <0x41000 0x1000>, <0x40020 0x1c>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + phy-names = "sata-phy"; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + phy-names = "sata-phy"; + }; + }; }; pcie0: pcie@18012000 { diff --git a/arch/arm/boot/dts/bcm958625k.dts b/arch/arm/boot/dts/bcm958625k.dts index e298450..2d84226 100644 --- a/arch/arm/boot/dts/bcm958625k.dts +++ b/arch/arm/boot/dts/bcm958625k.dts @@ -68,6 +68,18 @@ status = "okay"; }; +&sata_phy0 { + status = "okay"; +}; + +&sata_phy1 { + status = "okay"; +}; + +&sata { + status = "okay"; +}; + &nand { nandcs@0 { compatible = "brcm,nandcs"; -- cgit v0.10.2 From f3f99d37e668f080d167cf11f3b2e986df2d315d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 17 Jun 2016 17:37:12 +0200 Subject: ata: fix "ering" sysfs time printing The sysfs file for the libata error handling has multiple issues in the way it prints time stamps: * it prints a 9-digit nanosecond value using a %06lu format string, which drops some leading zeroes * it converts a 64-bit jiffes value to a timespec using jiffies_to_timespec(), which takes a 'long' argument, so the result is wrong after a jiffies overflow (49 days). * we try to avoid using timespec because that generally overflows in 2038, although this particular usage is ok. This replaces the jiffies_to_timespec call with an open-coded implementation that gets it right. Signed-off-by: Arnd Bergmann Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index e2d9497..7ef16c0 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -495,12 +495,13 @@ struct ata_show_ering_arg { static int ata_show_ering(struct ata_ering_entry *ent, void *void_arg) { struct ata_show_ering_arg* arg = void_arg; - struct timespec time; + u64 seconds; + u32 rem; - jiffies_to_timespec(ent->timestamp,&time); + seconds = div_u64_rem(ent->timestamp, HZ, &rem); arg->written += sprintf(arg->buf + arg->written, - "[%5lu.%06lu]", - time.tv_sec, time.tv_nsec); + "[%5llu.%09lu]", seconds, + rem * NSEC_PER_SEC / HZ); arg->written += get_ata_err_names(ent->err_mask, arg->buf + arg->written); return 0; -- cgit v0.10.2 From 3e70af86e52e9e9e8fe32027b0471a8da93b498e Mon Sep 17 00:00:00 2001 From: Iago Abal Date: Mon, 27 Jun 2016 09:51:42 +0200 Subject: drivers: ata: pata_arasan_cf: use the same name for the same lock Note that `&acdev->host->lock' and `qc->ap->lock' denote the same lock, and it's particularly confusing to spin_lock on the former but spin_unlock on the latter. Signed-off-by: Iago Abal Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 80fe0f6..b4d5477 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -565,7 +565,7 @@ chan_request_fail: qc->ap->hsm_task_state = HSM_ST_ERR; cf_ctrl_reset(acdev); - spin_unlock_irqrestore(qc->ap->lock, flags); + spin_unlock_irqrestore(&acdev->host->lock, flags); sff_intr: dma_complete(acdev); } -- cgit v0.10.2 From a3e8ab1b462d609147afb8df1291e54708593f15 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Thu, 7 Jul 2016 01:13:08 +0800 Subject: libata-scsi: do not respond with "invalid field" for FORMAT UNIT It does not make sense and is confusing to respond with "Invalid field in CDB" while we have no support at all implemented for FORMAT UNIT. It is decent to let it go to the default, which will respond with "Invalid command operation code" instead. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bfec66f..f1125fd 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4039,11 +4039,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) args.done = cmd->scsi_done; switch(scsicmd[0]) { - /* TODO: worth improving? */ - case FORMAT_UNIT: - ata_scsi_invalid_field(dev, cmd, 0); - break; - case INQUIRY: if (scsicmd[1] & 2) /* is CmdDt set? */ ata_scsi_invalid_field(dev, cmd, 1); -- cgit v0.10.2 From 8554e5e1c793b376598551c45242f61777607499 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Thu, 7 Jul 2016 01:13:09 +0800 Subject: libata-scsi: correct cbd to CDB in comment It's Command Descriptor Block. Also capitalized it. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f1125fd..c9cd216 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -304,7 +304,7 @@ static void ata_scsi_set_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd, u16 field, u8 bit) { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + /* "Invalid field in CDB" */ scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, field, bit, 1); } -- cgit v0.10.2 From 56b8cbabb422366e89577c5862ce0aa79cada240 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Tue, 12 Jul 2016 22:12:01 +0800 Subject: libata-scsi: set correct VERSION field for ZAC devices Commit 856c46639309 ("libata: support device-managed ZAC devices") had the line that "bumps" the VERSION field in standard INQUIRY data removed. Add it back and claim SPC-5 version compatibility, which matches with the current version descriptor "SPC-5 (no version claimed)" that is used for ZAC devices. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index c9cd216..3e79485 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2109,8 +2109,10 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL)) hdr[1] |= (1 << 7); - if (args->dev->class == ATA_DEV_ZAC) + if (args->dev->class == ATA_DEV_ZAC) { hdr[0] = TYPE_ZBC; + hdr[2] = 0x7; /* claim SPC-5 version compatibility */ + } memcpy(rbuf, hdr, sizeof(hdr)); memcpy(&rbuf[8], "ATA ", 8); -- cgit v0.10.2 From 0c12735e8abf4734b011aec979092db5e63556b0 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Tue, 12 Jul 2016 21:37:02 +0800 Subject: libata-scsi: fix SET FEATURES "filtering" for ata_msense_caching() Without this fix, the DRA bit of the caching mode page would not be updated when the read look-ahead feature is toggled (e.g. with `smartctl --set`), but will only be until, for example, the write cache feature is touched. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6be7770..077daf0d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5127,7 +5127,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc) switch (qc->tf.command) { case ATA_CMD_SET_FEATURES: if (qc->tf.feature != SETFEATURES_WC_ON && - qc->tf.feature != SETFEATURES_WC_OFF) + qc->tf.feature != SETFEATURES_WC_OFF && + qc->tf.feature != SETFEATURES_RA_ON && + qc->tf.feature != SETFEATURES_RA_OFF) break; /* fall through */ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ diff --git a/include/linux/ata.h b/include/linux/ata.h index 99346be..2d68793 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -409,6 +409,9 @@ enum { SETFEATURES_WC_ON = 0x02, /* Enable write cache */ SETFEATURES_WC_OFF = 0x82, /* Disable write cache */ + SETFEATURES_RA_ON = 0xaa, /* Enable read look-ahead */ + SETFEATURES_RA_OFF = 0x55, /* Disable read look-ahead */ + /* Enable/Disable Automatic Acoustic Management */ SETFEATURES_AAM_ON = 0x42, SETFEATURES_AAM_OFF = 0xC2, -- cgit v0.10.2 From 415ffdde15551769b24afe0e2021e231298773f8 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Tue, 12 Jul 2016 21:29:34 +0800 Subject: libata-scsi: set CmdQue bit in standard INQUIRY data to 1 Avoid performance bottleneck when being SCSI pass-through'd to virtual machines with other OSes (e.g. Windows) via virtio-scsi and scsi-block in qemu. Ref.: https://github.com/YanVugenfirer/kvm-guest-drivers-windows/issues/63 Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3e79485..b0d4bba 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2097,7 +2097,10 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) 0, 0x5, /* claim SPC-3 version compatibility */ 2, - 95 - 4 + 95 - 4, + 0, + 0, + 2 }; VPRINTK("ENTER\n"); -- cgit v0.10.2 From 29a37ea40147eb8ef648cb89a7c595e483101ff4 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Tue, 12 Jul 2016 21:29:35 +0800 Subject: libata-scsi: correct SPC version descriptor The comment suggests we should be having an SPC-3 version descriptor but the 0260h is the code for "SPC-2 (no version claimed)". Correct it to 0300h so that it has the "SPC-3 (no version claimed)" descriptor. Note that we are claiming SPC-3 version compatibility in the VERSION field of the standard INQUIRY data. Therefore, I assume the typo was on the code but not on the comment. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b0d4bba..f6888fc 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2075,8 +2075,8 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) 0x03, 0x20, /* SBC-2 (no version claimed) */ - 0x02, - 0x60 /* SPC-3 (no version claimed) */ + 0x03, + 0x00 /* SPC-3 (no version claimed) */ }; const u8 versions_zbc[] = { 0x00, -- cgit v0.10.2 From a548cc00cf7b0cb3c5b311e0129453f280faed94 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 12 Jul 2016 12:16:19 +0100 Subject: ata: hpt366: fix incorrect mask when checking at cmd_high_time According to the HPT366 data sheet, PCI config space dword 0x40-0x43 bits 11:8 specify the primary drive cmd_high_time, however, currently just 3 bits of the 4 are being used because the mask is 0x700 and not 0x0f00. Fix the mask, allowing for the 40MHz clock to be detected. Signed-off-by: Colin Ian King Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index e5fb752..a219a50 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -368,7 +368,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* PCI clocking determines the ATA timing values to use */ /* info_hpt366 is safe against re-entry so we can scribble on it */ - switch ((reg1 & 0x700) >> 8) { + switch ((reg1 & 0xf00) >> 8) { case 9: hpriv = &hpt366_40; break; -- cgit v0.10.2 From c9cd3504eb03755db8e64f894ccd4ebee59734b7 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 13 Jul 2016 02:54:11 +0800 Subject: libata-scsi: fix D_SENSE bit relection in control mode page The bit should always be set to 1 when the requested version of page is "changeable" because we've made it so in ata_mselect_control(). Also, it should always be set to 1 if ATA_DFLAG_D_SENSE is set (when the requested version of page is "current" or "default"). Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f6888fc..9c7c9f2 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2451,7 +2451,7 @@ static unsigned int ata_msense_ctl_mode(struct ata_device *dev, u8 *buf, bool changeable) { modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); - if (changeable && (dev->flags & ATA_DFLAG_D_SENSE)) + if (changeable || (dev->flags & ATA_DFLAG_D_SENSE)) buf[2] |= (1 << 2); /* Descriptor sense requested */ return sizeof(def_control_mpage); } -- cgit v0.10.2 From f086b7489a4ced0067ed39766146b60ff1fe4b9d Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 13 Jul 2016 02:54:12 +0800 Subject: libata-scsi: rename ata_msense_ctl_mode() to ata_msense_control() To make it consistent with the recently added ata_mselect_control(). We probably shouldn't have the word "mode" in its name anyway, since that's not the case for other ata_msense_*() / ata_mselect_*() either. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9c7c9f2..f0593bc 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2437,7 +2437,7 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) } /** - * ata_msense_ctl_mode - Simulate MODE SENSE control mode page + * ata_msense_control - Simulate MODE SENSE control mode page * @dev: ATA device of interest * @buf: output buffer * @changeable: whether changeable parameters are requested @@ -2447,7 +2447,7 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) * LOCKING: * None. */ -static unsigned int ata_msense_ctl_mode(struct ata_device *dev, u8 *buf, +static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, bool changeable) { modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); @@ -2571,13 +2571,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; case CONTROL_MPAGE: - p += ata_msense_ctl_mode(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, page_control == 1); break; case ALL_MPAGES: p += ata_msense_rw_recovery(p, page_control == 1); p += ata_msense_caching(args->id, p, page_control == 1); - p += ata_msense_ctl_mode(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, page_control == 1); break; default: /* invalid page code */ @@ -3672,7 +3672,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, /* * Check that read-only bits are not modified. */ - ata_msense_ctl_mode(dev, mpage, false); + ata_msense_control(dev, mpage, false); for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) { if (i == 0) continue; -- cgit v0.10.2 From 5c79097a28c2525740dd9e4470676ec9d25bee45 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 13 Jul 2016 04:31:22 +0800 Subject: libata-scsi: reject WRITE SAME (16) with n_block that exceeds limit Currently if a WRITE SAME (16) command is issued to the SATL with "number of blocks" that is larger than the "Maximum write same length" (which is the maximum number of blocks per TRIM command allowed in libata, currently 65535 * 512 / 8 blocks), the SATL will accept the command and translate it to a TRIM command with the upper limit. However, according to SBC (as of sbc4r11.pdf), the "device server" should terminate the command with "Invalid field in CDB" in that case. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f0593bc..b0ca322 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3310,7 +3310,13 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) goto invalid_param_len; buf = page_address(sg_page(scsi_sglist(scmd))); - size = ata_set_lba_range_entries(buf, 512, block, n_block); + + if (n_block <= 65535 * 512 / 8) { + size = ata_set_lba_range_entries(buf, 512, block, n_block); + } else { + fp = 2; + goto invalid_fld; + } if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { /* Newer devices support queued TRIM commands */ -- cgit v0.10.2 From 2983860c766870b701c4a34f435c1e18db086244 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 13 Jul 2016 04:31:23 +0800 Subject: libata-scsi: avoid repeated calculation of number of TRIM ranges Currently libata statically allows only 1-block (512-byte) payload for each TRIM command. Each payload can carry 64 TRIM ranges since each range requires 8 bytes. It is silly to keep doing the calculation (512 / 8) in different places. Hence, define the new ATA_MAX_TRIM_RNUM for the result. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b0ca322..3dca0d1 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2319,7 +2319,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) * with the unmap bit set. */ if (ata_id_has_trim(args->id)) { - put_unaligned_be64(65535 * 512 / 8, &rbuf[36]); + put_unaligned_be64(65535 * ATA_MAX_TRIM_RNUM, &rbuf[36]); put_unaligned_be32(1, &rbuf[28]); } @@ -3311,8 +3311,8 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) buf = page_address(sg_page(scsi_sglist(scmd))); - if (n_block <= 65535 * 512 / 8) { - size = ata_set_lba_range_entries(buf, 512, block, n_block); + if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) { + size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block); } else { fp = 2; goto invalid_fld; diff --git a/include/linux/ata.h b/include/linux/ata.h index 2d68793..d20b1ee 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -48,6 +48,7 @@ enum { ATA_MAX_SECTORS_1024 = 1024, ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */ ATA_MAX_SECTORS_TAPE = 65535, + ATA_MAX_TRIM_RNUM = 64, /* 512-byte payload / (6-byte LBA + 2-byte range per entry) */ ATA_ID_WORDS = 256, ATA_ID_CONFIG = 0, @@ -1069,12 +1070,12 @@ static inline void ata_id_to_hd_driveid(u16 *id) * TO NV CACHE PINNED SET. */ static inline unsigned ata_set_lba_range_entries(void *_buffer, - unsigned buf_size, u64 sector, unsigned long count) + unsigned num, u64 sector, unsigned long count) { __le64 *buffer = _buffer; unsigned i = 0, used_bytes; - while (i < buf_size / 8 ) { /* 6-byte LBA + 2-byte range per entry */ + while (i < num) { u64 entry = sector | ((u64)(count > 0xffff ? 0xffff : count) << 48); buffer[i++] = __cpu_to_le64(entry); -- cgit v0.10.2 From b1c04e80c6da5f5d3d4778ede23c59666135fdeb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 14 Jul 2016 09:05:42 +0900 Subject: libata: return boolean values from ata_is_* This way we don't have to worry about the exact bit postition of the test to leak out and any crazy propagation effects in the callers. Suggested-by: Tejun Heo Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/include/linux/libata.h b/include/linux/libata.h index d15c19e..4e5a09c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1063,32 +1063,32 @@ static inline unsigned int ata_prot_flags(u8 prot) return 0; } -static inline int ata_is_atapi(u8 prot) +static inline bool ata_is_atapi(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; } -static inline int ata_is_nodata(u8 prot) +static inline bool ata_is_nodata(u8 prot) { return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); } -static inline int ata_is_pio(u8 prot) +static inline bool ata_is_pio(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; } -static inline int ata_is_dma(u8 prot) +static inline bool ata_is_dma(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; } -static inline int ata_is_ncq(u8 prot) +static inline bool ata_is_ncq(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; } -static inline int ata_is_data(u8 prot) +static inline bool ata_is_data(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; } @@ -1407,7 +1407,7 @@ static inline bool sata_pmp_attached(struct ata_port *ap) return ap->nr_pmp_links != 0; } -static inline int ata_is_host_link(const struct ata_link *link) +static inline bool ata_is_host_link(const struct ata_link *link) { return link == &link->ap->link || link == link->ap->slave_link; } @@ -1422,7 +1422,7 @@ static inline bool sata_pmp_attached(struct ata_port *ap) return false; } -static inline int ata_is_host_link(const struct ata_link *link) +static inline bool ata_is_host_link(const struct ata_link *link) { return 1; } -- cgit v0.10.2 From 179b310ae77ea4f924fe338af5c8983c3f339098 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 14 Jul 2016 09:05:43 +0900 Subject: libata: use ata_is_ncq() accessors Use accessor functions instead of the raw value. Signed-off-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 71b0719..3e69c20 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1975,7 +1975,7 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) */ pp->active_link = qc->dev->link; - if (qc->tf.protocol == ATA_PROT_NCQ) + if (ata_is_ncq(qc->tf.protocol)) writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 077daf0d..f5eb07e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4842,7 +4842,7 @@ int ata_std_qc_defer(struct ata_queued_cmd *qc) { struct ata_link *link = qc->dev->link; - if (qc->tf.protocol == ATA_PROT_NCQ) { + if (ata_is_ncq(qc->tf.protocol)) { if (!ata_tag_valid(link->active_tag)) return 0; } else { @@ -5007,7 +5007,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) ata_sg_clean(qc); /* command should be marked inactive atomically with qc completion */ - if (qc->tf.protocol == ATA_PROT_NCQ) { + if (ata_is_ncq(qc->tf.protocol)) { link->sactive &= ~(1 << qc->tag); if (!link->sactive) ap->nr_active_links--; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3dca0d1..0447a39 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3130,8 +3130,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->command = cdb[9]; } - /* For NCQ commands with FPDMA protocol, copy the tag value */ - if (tf->protocol == ATA_PROT_NCQ) + /* For NCQ commands copy the tag value */ + if (ata_is_ncq(tf->protocol)) tf->nsect = qc->tag << 3; /* enforce correct master/slave bit */ -- cgit v0.10.2 From b38d4d85b89c68b2748a5e225185073424510486 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 14 Jul 2016 09:05:44 +0900 Subject: libsas: use ata_is_ncq() and ata_has_dma() accessors Use accessors instead of the raw protocol value. Signed-off-by: Hannes Reinecke [hch: trivial cleanup of the ata_task assignments] Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 935c430..497bc15 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -233,15 +233,8 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) task->task_state_flags = SAS_TASK_STATE_PENDING; qc->lldd_task = task; - switch (qc->tf.protocol) { - case ATA_PROT_NCQ: - task->ata_task.use_ncq = 1; - /* fall through */ - case ATAPI_PROT_DMA: - case ATA_PROT_DMA: - task->ata_task.dma_xfer = 1; - break; - } + task->ata_task.use_ncq = ata_is_ncq(qc->tf.protocol); + task->ata_task.dma_xfer = ata_is_dma(qc->tf.protocol); if (qc->scsicmd) ASSIGN_SAS_TASK(qc->scsicmd, task); -- cgit v0.10.2 From bd18bc04caeff361a4fff477224fa5b5fe5ce603 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 14 Jul 2016 09:05:46 +0900 Subject: ata: fixup ATA_PROT_NODATA The taskfile protocol is a numeric value, and can not be ORed. Currently this is harmless as the protocol is always zeroed before, but if it ever has a non-zero value the ORing would create incorrect results. Signed-off-by: Hannes Reinecke [hch: updated patch description] Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f5eb07e..522848a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1238,7 +1238,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors) } else tf.command = ATA_CMD_READ_NATIVE_MAX; - tf.protocol |= ATA_PROT_NODATA; + tf.protocol = ATA_PROT_NODATA; tf.device |= ATA_LBA; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); @@ -1297,7 +1297,7 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors) tf.device |= (new_sectors >> 24) & 0xf; } - tf.protocol |= ATA_PROT_NODATA; + tf.protocol = ATA_PROT_NODATA; tf.device |= ATA_LBA; tf.lbal = (new_sectors >> 0) & 0xff; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 61dc7a9..7832e55 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3177,7 +3177,7 @@ static void ata_eh_park_issue_cmd(struct ata_device *dev, int park) } tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; - tf.protocol |= ATA_PROT_NODATA; + tf.protocol = ATA_PROT_NODATA; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); if (park && (err_mask || tf.lbal != 0xc4)) { ata_dev_err(dev, "head unload failed!\n"); -- cgit v0.10.2 From 5b51ba6178f5502e6ab1bba75e91a365bc4c718b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 14 Jul 2016 09:05:47 +0900 Subject: libata-eh: decode all taskfile protocols Some taskfile protocol values where missing in ata_eh_link_report(). Signed-off-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7832e55..5688b86 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2607,9 +2607,12 @@ static void ata_eh_link_report(struct ata_link *link) [DMA_FROM_DEVICE] = "in", }; static const char *prot_str[] = { + [ATA_PROT_UNKNOWN] = "unknown", + [ATA_PROT_NODATA] = "nodata", [ATA_PROT_PIO] = "pio", [ATA_PROT_DMA] = "dma", [ATA_PROT_NCQ] = "ncq", + [ATAPI_PROT_NODATA] = "nodata", [ATAPI_PROT_PIO] = "pio", [ATAPI_PROT_DMA] = "dma", }; -- cgit v0.10.2 From 5b844b63ddfb65aef923eaabe0420196fd71dd13 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 14 Jul 2016 09:05:48 +0900 Subject: ata: Handle ATA NCQ NO-DATA commands correctly Add a new taskfile protocol ATA_PROT_NCQ_NODATA to handle ATA NCQ NO-DATA commands correctly. And fixup ata_scsi_zbc_out_xlat() to use it. Signed-off-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5688b86..d551378 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2611,7 +2611,8 @@ static void ata_eh_link_report(struct ata_link *link) [ATA_PROT_NODATA] = "nodata", [ATA_PROT_PIO] = "pio", [ATA_PROT_DMA] = "dma", - [ATA_PROT_NCQ] = "ncq", + [ATA_PROT_NCQ] = "ncq dma", + [ATA_PROT_NCQ_NODATA] = "ncq nodata", [ATAPI_PROT_NODATA] = "nodata", [ATAPI_PROT_PIO] = "pio", [ATAPI_PROT_DMA] = "dma", diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0447a39..901b46a 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3082,6 +3082,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) goto invalid_fld; } + if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0) + tf->protocol = ATA_PROT_NCQ_NODATA; + /* enable LBA */ tf->flags |= ATA_TFLAG_LBA; @@ -3548,7 +3551,7 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) if (ata_ncq_enabled(qc->dev) && ata_fpdma_zac_mgmt_out_supported(qc->dev)) { - tf->protocol = ATA_PROT_NCQ; + tf->protocol = ATA_PROT_NCQ_NODATA; tf->command = ATA_CMD_NCQ_NON_DATA; tf->hob_nsect = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; tf->nsect = qc->tag << 3; diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 00c2af1..fa1530a 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -290,6 +290,8 @@ static const char *get_prot_descript(u8 protocol) return "ATA DMA"; case ATA_PROT_NCQ: return "ATA NCQ"; + case ATA_PROT_NCQ_NODATA: + return "ATA NCQ no data"; case ATAPI_PROT_NODATA: return "ATAPI no data"; case ATAPI_PROT_PIO: diff --git a/include/linux/ata.h b/include/linux/ata.h index d20b1ee..35857d1 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -530,6 +530,7 @@ enum ata_tf_protocols { ATA_PROT_PIO, /* PIO data xfer */ ATA_PROT_DMA, /* DMA */ ATA_PROT_NCQ, /* NCQ */ + ATA_PROT_NCQ_NODATA, /* NCQ no data */ ATAPI_PROT_NODATA, /* packet command, no data */ ATAPI_PROT_PIO, /* packet command, PIO data xfer*/ ATAPI_PROT_DMA, /* packet command with special DMA sauce */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 4e5a09c..1abd669 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1053,6 +1053,8 @@ static inline unsigned int ata_prot_flags(u8 prot) return ATA_PROT_FLAG_DMA; case ATA_PROT_NCQ: return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; + case ATA_PROT_NCQ_NODATA: + return ATA_PROT_FLAG_NCQ; case ATAPI_PROT_NODATA: return ATA_PROT_FLAG_ATAPI; case ATAPI_PROT_PIO: diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h index 75fff86..2fbbf99 100644 --- a/include/trace/events/libata.h +++ b/include/trace/events/libata.h @@ -126,6 +126,7 @@ ata_protocol_name(ATA_PROT_PIO), \ ata_protocol_name(ATA_PROT_DMA), \ ata_protocol_name(ATA_PROT_NCQ), \ + ata_protocol_name(ATA_PROT_NCQ_NODATA), \ ata_protocol_name(ATAPI_PROT_NODATA), \ ata_protocol_name(ATAPI_PROT_PIO), \ ata_protocol_name(ATAPI_PROT_DMA)) -- cgit v0.10.2 From 3f17422b425afd91f4fb45b8f47ffd61b02c0bb8 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 14 Jul 2016 09:05:49 +0900 Subject: libata-scsi: Fix translation of REPORT ZONES command Include reporting options when translating REPORT ZONES commmand to ATA NCQ, and make sure we only look at the actually specified bits in the CDB for the options. Signed-off-by: Damien Le Moal [hch: update patch description] Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 901b46a..45d8ae63 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3468,7 +3468,7 @@ static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc) goto invalid_param_len; } sect = n_block / 512; - options = cdb[14]; + options = cdb[14] & 0xbf; if (ata_ncq_enabled(qc->dev) && ata_fpdma_zac_mgmt_in_supported(qc->dev)) { @@ -3478,7 +3478,7 @@ static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc) tf->nsect = qc->tag << 3; tf->feature = sect & 0xff; tf->hob_feature = (sect >> 8) & 0xff; - tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES; + tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES | (options << 8); } else { tf->command = ATA_CMD_ZAC_MGMT_IN; tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES; -- cgit v0.10.2 From ee194b75318df718827677d150ebdc31086b121b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 14 Jul 2016 09:05:50 +0900 Subject: libata-scsi: Fix ZBC management out command translation The subcommand for NCQ NON-DATA must be specified in the feature (low byte), not the high-order count byte. Also make sure to properly cast the all bit to a u16 before shiting it by 8 to avoid undefined behavior. Signed-off-by: Damien Le Moal [hch: split the original patch into two, updated changelog] Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 45d8ae63..d978153 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3553,9 +3553,9 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) ata_fpdma_zac_mgmt_out_supported(qc->dev)) { tf->protocol = ATA_PROT_NCQ_NODATA; tf->command = ATA_CMD_NCQ_NON_DATA; - tf->hob_nsect = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; + tf->feature = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; tf->nsect = qc->tag << 3; - tf->auxiliary = sa | (reset_all & 0x1) << 8; + tf->auxiliary = sa | ((u16)(reset_all & 0x1) << 8); } else { tf->protocol = ATA_PROT_NODATA; tf->command = ATA_CMD_ZAC_MGMT_OUT; -- cgit v0.10.2 From 2950cefac0a7d8d4de1b321874a1f31df4bc19a8 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 14 Jul 2016 09:05:51 +0900 Subject: libata-scsi: minor cleanup for ata_scsi_zbc_out_xlat The reset_all variable name is misleading as this bit is also applicable to open, close, and finish actions. So rename that variable to "all" and remove the unnecessary mask operation that's already done earlier. Signed-off-by: Damien Le Moal [hch: split from the previous patch] Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index d978153..7d0e60b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3520,7 +3520,7 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; - u8 reset_all, sa; + u8 all, sa; u64 block; u32 n_block; u16 fp = (u16)-1; @@ -3547,7 +3547,7 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) if (block > dev->n_sectors) goto out_of_range; - reset_all = cdb[14] & 0x1; + all = cdb[14] & 0x1; if (ata_ncq_enabled(qc->dev) && ata_fpdma_zac_mgmt_out_supported(qc->dev)) { @@ -3555,12 +3555,12 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) tf->command = ATA_CMD_NCQ_NON_DATA; tf->feature = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; tf->nsect = qc->tag << 3; - tf->auxiliary = sa | ((u16)(reset_all & 0x1) << 8); + tf->auxiliary = sa | ((u16)all << 8); } else { tf->protocol = ATA_PROT_NODATA; tf->command = ATA_CMD_ZAC_MGMT_OUT; tf->feature = sa; - tf->hob_feature = reset_all & 0x1; + tf->hob_feature = all; } tf->lbah = (block >> 16) & 0xff; tf->lbam = (block >> 8) & 0xff; -- cgit v0.10.2 From 35303d5c36415754680f953aa6128b8b907d0543 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Fri, 15 Jul 2016 05:09:02 +0800 Subject: ata: make lba_{28,48}_ok() use ATA_MAX_SECTORS{,_LBA48} Since we set ATA_MAX_SECTORS_LBA48 to 65535 to avoid the corner case in some drives that commands with "count" set to 0000h (which reprsents 65536) does not work as expected, lba_48_ok(), which is used for number-of-blocks checking when libata pack commands, should use the same limit as well. In fact, there is no reason for the two functions not to use the macros anyway. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/include/linux/ata.h b/include/linux/ata.h index 35857d1..5b67ff4 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -46,7 +46,7 @@ enum { ATA_MAX_SECTORS_128 = 128, ATA_MAX_SECTORS = 256, ATA_MAX_SECTORS_1024 = 1024, - ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */ + ATA_MAX_SECTORS_LBA48 = 65535,/* avoid count to be 0000h */ ATA_MAX_SECTORS_TAPE = 65535, ATA_MAX_TRIM_RNUM = 64, /* 512-byte payload / (6-byte LBA + 2-byte range per entry) */ @@ -1100,13 +1100,13 @@ static inline bool ata_ok(u8 status) static inline bool lba_28_ok(u64 block, u32 n_block) { /* check the ending block number: must be LESS THAN 0x0fffffff */ - return ((block + n_block) < ((1 << 28) - 1)) && (n_block <= 256); + return ((block + n_block) < ((1 << 28) - 1)) && (n_block <= ATA_MAX_SECTORS); } static inline bool lba_48_ok(u64 block, u32 n_block) { /* check the ending block number */ - return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); + return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= ATA_MAX_SECTORS_LBA48); } #define sata_pmp_gscr_vendor(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff) -- cgit v0.10.2 From eb0effdf53b061bd57d8efc86032454e79487263 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 16 Jul 2016 22:16:41 +0900 Subject: libata: remove ata_is_nodata The only caller can just check for !ata_is_data instead. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 522848a..0749f71 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5044,7 +5044,7 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc) { struct ata_device *dev = qc->dev; - if (ata_is_nodata(qc->tf.protocol)) + if (!ata_is_data(qc->tf.protocol)) return; if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol)) diff --git a/include/linux/libata.h b/include/linux/libata.h index 1abd669..283b6be 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1070,11 +1070,6 @@ static inline bool ata_is_atapi(u8 prot) return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; } -static inline bool ata_is_nodata(u8 prot) -{ - return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); -} - static inline bool ata_is_pio(u8 prot) { return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; -- cgit v0.10.2 From d6e50e379eb1e7f2426eac61a1bbbf6e4cf68905 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 16 Jul 2016 22:16:42 +0900 Subject: libata: remove ATA_PROT_FLAG_DATA Instead we can simply check for PIO or DMA in ata_is_data. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/include/linux/libata.h b/include/linux/libata.h index 283b6be..5838fbf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -149,7 +149,6 @@ enum { /* protocol flags */ ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ - ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA, ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ @@ -1087,7 +1086,7 @@ static inline bool ata_is_ncq(u8 prot) static inline bool ata_is_data(u8 prot) { - return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; + return ata_prot_flags(prot) & (ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA); } static inline int is_multi_taskfile(struct ata_taskfile *tf) -- cgit v0.10.2 From 37f92d77dc45d1fb74eff8501f26e72a3dcaa3cf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 16 Jul 2016 22:16:43 +0900 Subject: ata: define ATA_PROT_* in terms of ATA_PROT_FLAG_* This avoid the need to always translate between the two in ata_prot_flags and generally cleans up the taskfile protocol usage. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index fa1530a..b051c03 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -281,7 +281,7 @@ static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) static const char *get_prot_descript(u8 protocol) { - switch ((enum ata_tf_protocols)protocol) { + switch (protocol) { case ATA_PROT_NODATA: return "ATA no data"; case ATA_PROT_PIO: diff --git a/include/linux/ata.h b/include/linux/ata.h index 5b67ff4..adbc812 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -523,17 +523,23 @@ enum { SERR_DEV_XCHG = (1 << 26), /* device exchanged */ }; -enum ata_tf_protocols { - /* ATA taskfile protocols */ - ATA_PROT_UNKNOWN, /* unknown/invalid */ - ATA_PROT_NODATA, /* no data */ - ATA_PROT_PIO, /* PIO data xfer */ - ATA_PROT_DMA, /* DMA */ - ATA_PROT_NCQ, /* NCQ */ - ATA_PROT_NCQ_NODATA, /* NCQ no data */ - ATAPI_PROT_NODATA, /* packet command, no data */ - ATAPI_PROT_PIO, /* packet command, PIO data xfer*/ - ATAPI_PROT_DMA, /* packet command with special DMA sauce */ +enum ata_prot_flags { + /* protocol flags */ + ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ + ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ + ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ + ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ + + /* taskfile protocols */ + ATA_PROT_UNKNOWN = (u8)-1, + ATA_PROT_NODATA = 0, + ATA_PROT_PIO = ATA_PROT_FLAG_PIO, + ATA_PROT_DMA = ATA_PROT_FLAG_DMA, + ATA_PROT_NCQ_NODATA = ATA_PROT_FLAG_NCQ, + ATA_PROT_NCQ = ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ, + ATAPI_PROT_NODATA = ATA_PROT_FLAG_ATAPI, + ATAPI_PROT_PIO = ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO, + ATAPI_PROT_DMA = ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA, }; enum ata_ioctls { diff --git a/include/linux/libata.h b/include/linux/libata.h index 5838fbf..e37d4f9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -146,12 +146,6 @@ enum { ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ - /* protocol flags */ - ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ - ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ - ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ - ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ - /* struct ata_device stuff */ ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ @@ -1038,55 +1032,29 @@ extern const unsigned long sata_deb_timing_long[]; extern struct ata_port_operations ata_dummy_port_ops; extern const struct ata_port_info ata_dummy_port_info; -/* - * protocol tests - */ -static inline unsigned int ata_prot_flags(u8 prot) -{ - switch (prot) { - case ATA_PROT_NODATA: - return 0; - case ATA_PROT_PIO: - return ATA_PROT_FLAG_PIO; - case ATA_PROT_DMA: - return ATA_PROT_FLAG_DMA; - case ATA_PROT_NCQ: - return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; - case ATA_PROT_NCQ_NODATA: - return ATA_PROT_FLAG_NCQ; - case ATAPI_PROT_NODATA: - return ATA_PROT_FLAG_ATAPI; - case ATAPI_PROT_PIO: - return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; - case ATAPI_PROT_DMA: - return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; - } - return 0; -} - static inline bool ata_is_atapi(u8 prot) { - return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; + return prot & ATA_PROT_FLAG_ATAPI; } static inline bool ata_is_pio(u8 prot) { - return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; + return prot & ATA_PROT_FLAG_PIO; } static inline bool ata_is_dma(u8 prot) { - return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; + return prot & ATA_PROT_FLAG_DMA; } static inline bool ata_is_ncq(u8 prot) { - return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; + return prot & ATA_PROT_FLAG_NCQ; } static inline bool ata_is_data(u8 prot) { - return ata_prot_flags(prot) & (ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA); + return prot & (ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA); } static inline int is_multi_taskfile(struct ata_taskfile *tf) -- cgit v0.10.2 From 01c292068e43e72091c22542df5f01b3c09714b2 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 19 Jul 2016 11:27:53 +0000 Subject: ata: sata_dwc_460ex: remove redundant dev_err call There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index b051c03..e0939bd 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -259,11 +259,8 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, /* Get physical SATA DMA register base address */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hsdev->dma->regs)) { - dev_err(&pdev->dev, - "ioremap failed for AHBDMA register address\n"); + if (IS_ERR(hsdev->dma->regs)) return PTR_ERR(hsdev->dma->regs); - } /* Initialize AHB DMAC */ return dw_dma_probe(hsdev->dma); @@ -1227,11 +1224,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Ioremap SATA registers */ res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&ofdev->dev, res); - if (IS_ERR(base)) { - dev_err(&ofdev->dev, - "ioremap failed for SATA register address\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ -- cgit v0.10.2 From 0516900adfa1955f91f1c310f9a2fa857949de1c Mon Sep 17 00:00:00 2001 From: Pang Raymond Date: Wed, 20 Jul 2016 12:13:46 +0000 Subject: AHCI: Clear GHC.IS to prevent unexpectly asserting INTx Due to PCI subsystem behaviour, unloading AHCI driver will disable MSI and enable INTx. When HBA supports MSIx or Multiple MSI, Driver's irq handler doesn't clear GHC.IS register. It works well when reading or writing data and GHC.IS is always non-zero. But when unloading driver (or any other operation which causes disable MSIx and enable INTx), PCI subsystem uses config write(Rx04.bit10) to enable INTx. Because GHC.IS is non-zero, HBA will falsely assume some port needs interrupt service. Then it asserts INTx. To make things worse, when AHCI controller shares the same interrupt pin with other PCI device, that PCI device's ISR will be called and nobody de-asserts previous INTx. This patch clears GHC.IS in ahci_port_stop() even when using MSIx or MMSI to prevent this case. It ensures GHC.IS is zero before PCI subsystem enables INTx. tj: Minor updates to the comment. Signed-off-by: Raymond Pang Signed-off-by: Tejun Heo diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 3e69c20..7461a58 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2392,12 +2392,20 @@ static int ahci_port_start(struct ata_port *ap) static void ahci_port_stop(struct ata_port *ap) { const char *emsg = NULL; + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *host_mmio = hpriv->mmio; int rc; /* de-initialize port */ rc = ahci_deinit_port(ap, &emsg); if (rc) ata_port_warn(ap, "%s (%d)\n", emsg, rc); + + /* + * Clear GHC.IS to prevent stuck INTx after disabling MSI and + * re-enabling INTx. + */ + writel(1 << ap->port_no, host_mmio + HOST_IRQ_STAT); } void ahci_print_info(struct ata_host *host, const char *scc_s) -- cgit v0.10.2 From 737bee9308c457090711684b976e0fe02785a094 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 20 Jul 2016 04:39:28 +0800 Subject: libata-scsi: better style in ata_msense_*() `changeable` is the "version" of mode page requested by the user. It will be less confusing/misleading if we do not check it "together" with the setting bits of the drive. Not to mention that we currently have ata_mselect_*() implemented in a way that each of them will serve exclusively a particular bit on each page. The old style will hence make the condition look even more unnecessarily arcane if the ata_msense_*() is reflecting more than one bit. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7d0e60b..2bdb5da 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2429,10 +2429,12 @@ static void modecpy(u8 *dest, const u8 *src, int n, bool changeable) static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) { modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable); - if (changeable || ata_id_wcache_enabled(id)) - buf[2] |= (1 << 2); /* write cache enable */ - if (!changeable && !ata_id_rahead_enabled(id)) - buf[12] |= (1 << 5); /* disable read ahead */ + if (changeable) { + buf[2] |= (1 << 2); /* ata_mselect_caching() */ + } else { + buf[2] |= (ata_id_wcache_enabled(id) << 2); /* write cache enable */ + buf[12] |= (!ata_id_rahead_enabled(id) << 5); /* disable read ahead */ + } return sizeof(def_cache_mpage); } @@ -2451,8 +2453,13 @@ static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, bool changeable) { modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); - if (changeable || (dev->flags & ATA_DFLAG_D_SENSE)) - buf[2] |= (1 << 2); /* Descriptor sense requested */ + if (changeable) { + buf[2] |= (1 << 2); /* ata_mselect_control() */ + } else { + bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); + + buf[2] |= (d_sense << 2); /* descriptor format sense data */ + } return sizeof(def_control_mpage); } -- cgit v0.10.2