Skip to content

Commit

Permalink
Merge branch 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/tj/libata

Pull libata updates from Tejun Heo:

 - ahci grew runtime power management support so that the controller can
   be turned off if no devices are attached.

 - sata_via isn't dead yet.  It got hotplug support and more refined
   workaround for certain WD drives.

 - Misc cleanups.  There's a merge from for-4.5-fixes to avoid confusing
   conflicts in ahci PCI ID table.

* 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ata: ahci_xgene: dereferencing uninitialized pointer in probe
  AHCI: Remove obsolete Intel Lewisburg SATA RAID device IDs
  ata: sata_rcar: Use ARCH_RENESAS
  sata_via: Implement hotplug for VT6421
  sata_via: Apply WD workaround only when needed on VT6421
  ahci: Add runtime PM support for the host controller
  ahci: Add functions to manage runtime PM of AHCI ports
  ahci: Convert driver to use modern PM hooks
  ahci: Cache host controller version
  scsi: Drop runtime PM usage count after host is added
  scsi: Set request queue runtime PM status back to active on resume
  block: Add blk_set_runtime_active()
  ata: ahci_mvebu: add support for Armada 3700 variant
  libata: fix unbalanced spin_lock_irqsave/spin_unlock_irq() in ata_scsi_park_show()
  libata: support AHCI on OCTEON platform
  • Loading branch information
torvalds committed Mar 19, 2016
2 parents ef504fa + 8134233 commit fcab86a
Show file tree
Hide file tree
Showing 18 changed files with 475 additions and 57 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/ata/ahci-platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Required properties:
- compatible : compatible string, one of:
- "allwinner,sun4i-a10-ahci"
- "hisilicon,hisi-ahci"
- "cavium,octeon-7130-ahci"
- "ibm,476gtr-ahci"
- "marvell,armada-380-ahci"
- "snps,dwc-ahci"
Expand Down
42 changes: 42 additions & 0 deletions Documentation/devicetree/bindings/mips/cavium/sata-uctl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
* UCTL SATA controller glue

UCTL is the bridge unit between the I/O interconnect (an internal bus)
and the SATA AHCI host controller (UAHC). It performs the following functions:
- provides interfaces for the applications to access the UAHC AHCI
registers on the CN71XX I/O space.
- provides a bridge for UAHC to fetch AHCI command table entries and data
buffers from Level 2 Cache.
- posts interrupts to the CIU.
- contains registers that:
- control the behavior of the UAHC
- control the clock/reset generation to UAHC
- control endian swapping for all UAHC registers and DMA accesses

Properties:

- compatible: "cavium,octeon-7130-sata-uctl"

Compatibility with the cn7130 SOC.

- reg: The base address of the UCTL register bank.

- #address-cells, #size-cells, ranges and dma-ranges must be present and hold
suitable values to map all child nodes.

Example:

uctl@118006c000000 {
compatible = "cavium,octeon-7130-sata-uctl";
reg = <0x11800 0x6c000000 0x0 0x100>;
ranges; /* Direct mapping */
dma-ranges;
#address-cells = <2>;
#size-cells = <2>;

sata: sata@16c0000000000 {
compatible = "cavium,octeon-7130-ahci";
reg = <0x16c00 0x00000000 0x0 0x200>;
interrupt-parent = <&cibsata>;
interrupts = <2 4>; /* Bit: 2, level */
};
};
9 changes: 9 additions & 0 deletions arch/mips/include/asm/octeon/cvmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val)
cvmx_read64(CVMX_MIO_BOOT_BIST_STAT);
}

static inline void cvmx_writeq_csr(void __iomem *csr_addr, uint64_t val)
{
cvmx_write_csr((__force uint64_t)csr_addr, val);
}

static inline void cvmx_write_io(uint64_t io_addr, uint64_t val)
{
cvmx_write64(io_addr, val);
Expand All @@ -287,6 +292,10 @@ static inline uint64_t cvmx_read_csr(uint64_t csr_addr)
return val;
}

static inline uint64_t cvmx_readq_csr(void __iomem *csr_addr)
{
return cvmx_read_csr((__force uint64_t) csr_addr);
}

static inline void cvmx_send_single(uint64_t data)
{
Expand Down
24 changes: 24 additions & 0 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3529,6 +3529,30 @@ void blk_post_runtime_resume(struct request_queue *q, int err)
spin_unlock_irq(q->queue_lock);
}
EXPORT_SYMBOL(blk_post_runtime_resume);

/**
* blk_set_runtime_active - Force runtime status of the queue to be active
* @q: the queue of the device
*
* If the device is left runtime suspended during system suspend the resume
* hook typically resumes the device and corrects runtime status
* accordingly. However, that does not affect the queue runtime PM status
* which is still "suspended". This prevents processing requests from the
* queue.
*
* This function can be used in driver's resume hook to correct queue
* runtime PM status and re-enable peeking requests from the queue. It
* should be called before first request is added to the queue.
*/
void blk_set_runtime_active(struct request_queue *q)
{
spin_lock_irq(q->queue_lock);
q->rpm_status = RPM_ACTIVE;
pm_runtime_mark_last_busy(q->dev);
pm_request_autosuspend(q->dev);
spin_unlock_irq(q->queue_lock);
}
EXPORT_SYMBOL(blk_set_runtime_active);
#endif

int __init blk_dev_init(void)
Expand Down
11 changes: 10 additions & 1 deletion drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ config AHCI_MVEBU

If unsure, say N.

config AHCI_OCTEON
tristate "Cavium Octeon Soc Serial ATA"
depends on SATA_AHCI_PLATFORM && CAVIUM_OCTEON_SOC
default y
help
This option enables support for Cavium Octeon SoC Serial ATA.

If unsure, say N.

config AHCI_SUNXI
tristate "Allwinner sunxi AHCI SATA support"
depends on ARCH_SUNXI
Expand Down Expand Up @@ -355,7 +364,7 @@ config SATA_PROMISE

config SATA_RCAR
tristate "Renesas R-Car SATA support"
depends on ARCH_SHMOBILE || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
help
This option enables support for Renesas R-Car Serial ATA.

Expand Down
1 change: 1 addition & 0 deletions drivers/ata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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
obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o
obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o
Expand Down
108 changes: 75 additions & 33 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ enum board_ids {
};

static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static void ahci_remove_one(struct pci_dev *dev);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
Expand All @@ -94,9 +95,13 @@ static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
#ifdef CONFIG_PM
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
static int ahci_pci_device_runtime_suspend(struct device *dev);
static int ahci_pci_device_runtime_resume(struct device *dev);
#ifdef CONFIG_PM_SLEEP
static int ahci_pci_device_suspend(struct device *dev);
static int ahci_pci_device_resume(struct device *dev);
#endif
#endif /* CONFIG_PM */

static struct scsi_host_template ahci_sht = {
AHCI_SHT("ahci"),
Expand Down Expand Up @@ -371,15 +376,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/

Expand Down Expand Up @@ -563,16 +564,20 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ } /* terminate list */
};

static const struct dev_pm_ops ahci_pci_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
ahci_pci_device_runtime_resume, NULL)
};

static struct pci_driver ahci_pci_driver = {
.name = DRV_NAME,
.id_table = ahci_pci_tbl,
.probe = ahci_init_one,
.remove = ata_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ahci_pci_device_suspend,
.resume = ahci_pci_device_resume,
#endif
.remove = ahci_remove_one,
.driver = {
.pm = &ahci_pci_pm_ops,
},
};

#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
Expand Down Expand Up @@ -801,42 +806,66 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,


#ifdef CONFIG_PM
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
static void ahci_pci_disable_interrupts(struct ata_host *host)
{
struct ata_host *host = pci_get_drvdata(pdev);
struct ahci_host_priv *hpriv = host->private_data;
void __iomem *mmio = hpriv->mmio;
u32 ctl;

if (mesg.event & PM_EVENT_SUSPEND &&
hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
dev_err(&pdev->dev,
"BIOS update required for suspend/resume\n");
return -EIO;
}
/* AHCI spec rev1.1 section 8.3.3:
* Software must disable interrupts prior to requesting a
* transition of the HBA to D3 state.
*/
ctl = readl(mmio + HOST_CTL);
ctl &= ~HOST_IRQ_EN;
writel(ctl, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */
}

if (mesg.event & PM_EVENT_SLEEP) {
/* AHCI spec rev1.1 section 8.3.3:
* Software must disable interrupts prior to requesting a
* transition of the HBA to D3 state.
*/
ctl = readl(mmio + HOST_CTL);
ctl &= ~HOST_IRQ_EN;
writel(ctl, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */
}
static int ahci_pci_device_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ata_host *host = pci_get_drvdata(pdev);

return ata_pci_device_suspend(pdev, mesg);
ahci_pci_disable_interrupts(host);
return 0;
}

static int ahci_pci_device_resume(struct pci_dev *pdev)
static int ahci_pci_device_runtime_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ata_host *host = pci_get_drvdata(pdev);
int rc;

rc = ata_pci_device_do_resume(pdev);
rc = ahci_pci_reset_controller(host);
if (rc)
return rc;
ahci_pci_init_controller(host);
return 0;
}

#ifdef CONFIG_PM_SLEEP
static int ahci_pci_device_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ata_host *host = pci_get_drvdata(pdev);
struct ahci_host_priv *hpriv = host->private_data;

if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
dev_err(&pdev->dev,
"BIOS update required for suspend/resume\n");
return -EIO;
}

ahci_pci_disable_interrupts(host);
return ata_host_suspend(host, PMSG_SUSPEND);
}

static int ahci_pci_device_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ata_host *host = pci_get_drvdata(pdev);
int rc;

/* Apple BIOS helpfully mangles the registers on resume */
if (is_mcp89_apple(pdev))
Expand All @@ -856,6 +885,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
}
#endif

#endif /* CONFIG_PM */

static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
{
int rc;
Expand Down Expand Up @@ -1718,7 +1749,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

pci_set_master(pdev);

return ahci_host_activate(host, &ahci_sht);
rc = ahci_host_activate(host, &ahci_sht);
if (rc)
return rc;

pm_runtime_put_noidle(&pdev->dev);
return 0;
}

static void ahci_remove_one(struct pci_dev *pdev)
{
pm_runtime_get_noresume(&pdev->dev);
ata_pci_remove_one(pdev);
}

module_pci_driver(ahci_pci_driver);
Expand Down
1 change: 1 addition & 0 deletions drivers/ata/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ struct ahci_host_priv {
void __iomem * mmio; /* bus-independent mem map */
u32 cap; /* cap to use */
u32 cap2; /* cap2 to use */
u32 version; /* cached version */
u32 port_map; /* port map to use */
u32 saved_cap; /* saved initial cap */
u32 saved_cap2; /* saved initial cap2 */
Expand Down
14 changes: 9 additions & 5 deletions drivers/ata/ahci_mvebu.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,15 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
if (rc)
return rc;

dram = mv_mbus_dram_info();
if (!dram)
return -ENODEV;
if (of_device_is_compatible(pdev->dev.of_node,
"marvell,armada-380-ahci")) {
dram = mv_mbus_dram_info();
if (!dram)
return -ENODEV;

ahci_mvebu_mbus_config(hpriv, dram);
ahci_mvebu_regret_option(hpriv);
ahci_mvebu_mbus_config(hpriv, dram);
ahci_mvebu_regret_option(hpriv);
}

rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
&ahci_platform_sht);
Expand All @@ -133,6 +136,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev)

static const struct of_device_id ahci_mvebu_of_match[] = {
{ .compatible = "marvell,armada-380-ahci", },
{ .compatible = "marvell,armada-3700-ahci", },
{ },
};
MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
Expand Down
Loading

0 comments on commit fcab86a

Please sign in to comment.