Skip to content

Commit

Permalink
Merge tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/jgarzik/libata-dev

Pull libata updates from Jeff Garzik:

1) apply, and then revert, the sysfs export of ATA host controller
   number.  Discussion was continuing after patch application, trying to
   figure out how to best mesh exported data with the installers,
   boot-time agents and other parties that want this info.

2) Merge Zero-Power Optical Device Driver (ZPODD) support, bringing the
   wonderfulness of sane power management to your CD/DVD device.

   Includes one SCSI-subsystem patch (with appropriate ACKs), adding
   runtime PM support to 'sr' driver.  That is the ZPODD interaction
   bits.

   Patchset went through some 13 revisions before it got here; kudos to
   Intel for persistence.

3) pata_samsung_cf: use devm_clk_get()

4) more ata_piix, ahci PCI IDs

5) Add SATA driver for R-Car SoC

6) Convert libata to use devm_ioremap_resource (Note: I think Greg sent
   this to you, also)

7) Set proper Sense Key (SK) in the SCSI simulator when ATA passthrough
   indicates check condition.  Google and specification hawks everywhere
   shall rejoice.

* tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (22 commits)
  [libata] fix smatch warning for zpodd_wake_dev
  [libata] Set proper SK when CK_COND is set.
  [libata] Convert to devm_ioremap_resource()
  libata: add R-Car SATA driver
  ahci: Add Device IDs for Intel Wellsburg PCH
  ata_piix: Add Device IDs for Intel Wellsburg PCH
  [SCSI] remove can_power_off flag from scsi_device
  [libata] scsi: no poll when ODD is powered off
  [SCSI] sr: support runtime pm
  ahci: AHCI-mode SATA patch for Intel Avoton DeviceIDs
  ata_piix: IDE-mode SATA patch for Intel Avoton DeviceIDs
  [libata] PM code cleanup for ata port
  [libata] pm: differentiate system and runtime pm for ata port
  Revert "libata: export host controller number thru /sys"
  libata: do not suspend port if normal ODD is attached
  libata: expose pm qos flags for ata device
  libata: handle power transition of ODD
  libata: check zero power ready status for ZPODD
  libata: move acpi notification code to zpodd
  libata: identify and init ZPODD devices
  ...
  • Loading branch information
Linus Torvalds committed Feb 25, 2013
2 parents a883b70 + 53637e0 commit d9978ec
Show file tree
Hide file tree
Showing 17 changed files with 1,558 additions and 138 deletions.
21 changes: 21 additions & 0 deletions drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ config ATA_ACPI
You can disable this at kernel boot time by using the
option libata.noacpi=1

config SATA_ZPODD
bool "SATA Zero Power ODD Support"
depends on ATA_ACPI
default n
help
This option adds support for SATA ZPODD. It requires both
ODD and the platform support, and if enabled, will automatically
power on/off the ODD when certain condition is satisfied. This
does not impact user's experience of the ODD, only power is saved
when ODD is not in use(i.e. no disc inside).

If unsure, say N.

config SATA_PMP
bool "SATA Port Multiplier support"
default y
Expand Down Expand Up @@ -247,6 +260,14 @@ config SATA_PROMISE

If unsure, say N.

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

If unsure, say N.

config SATA_SIL
tristate "Silicon Image SATA support"
depends on PCI
Expand Down
2 changes: 2 additions & 0 deletions drivers/ata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ obj-$(CONFIG_ATA_PIIX) += ata_piix.o
obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_NV) += sata_nv.o
obj-$(CONFIG_SATA_PROMISE) += sata_promise.o
obj-$(CONFIG_SATA_RCAR) += sata_rcar.o
obj-$(CONFIG_SATA_SIL) += sata_sil.o
obj-$(CONFIG_SATA_SIS) += sata_sis.o
obj-$(CONFIG_SATA_SVW) += sata_svw.o
Expand Down Expand Up @@ -107,3 +108,4 @@ libata-y := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
libata-$(CONFIG_ATA_SFF) += libata-sff.o
libata-$(CONFIG_SATA_PMP) += libata-pmp.o
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
libata-$(CONFIG_SATA_ZPODD) += libata-zpodd.o
24 changes: 24 additions & 0 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,30 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */

/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Expand Down
17 changes: 17 additions & 0 deletions drivers/ata/ata_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,23 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (DH89xxCC) */
{ 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Avoton) */
{ 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Avoton) */
{ 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Avoton) */
{ 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Avoton) */
{ 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Wellsburg) */
{ 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Wellsburg) */
{ 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Wellsburg) */
{ 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Wellsburg) */
{ 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },

{ } /* terminate list */
};

Expand Down
177 changes: 77 additions & 100 deletions drivers/ata/libata-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
#include <scsi/scsi_device.h>
#include "libata.h"

Expand Down Expand Up @@ -835,50 +836,95 @@ void ata_acpi_on_resume(struct ata_port *ap)
}
}

/**
* ata_acpi_set_state - set the port power state
* @ap: target ATA port
* @state: state, on/off
*
* This function executes the _PS0/_PS3 ACPI method to set the power state.
* ACPI spec requires _PS0 when IDE power on and _PS3 when power off
*/
void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime)
{
int d_max_in = ACPI_STATE_D3_COLD;
if (!runtime)
goto out;

/*
* For ATAPI, runtime D3 cold is only allowed
* for ZPODD in zero power ready state
*/
if (dev->class == ATA_DEV_ATAPI &&
!(zpodd_dev_enabled(dev) && zpodd_zpready(dev)))
d_max_in = ACPI_STATE_D3_HOT;

out:
return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev,
NULL, d_max_in);
}

static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state)
{
bool runtime = PMSG_IS_AUTO(state);
struct ata_device *dev;
acpi_handle handle;
int acpi_state;

/* channel first and then drives for power on and vica versa
for power off */
handle = ata_ap_acpi_handle(ap);
if (handle && state.event == PM_EVENT_ON)
acpi_bus_set_power(handle, ACPI_STATE_D0);

ata_for_each_dev(dev, &ap->link, ENABLED) {
handle = ata_dev_acpi_handle(dev);
if (!handle)
continue;

if (state.event != PM_EVENT_ON) {
acpi_state = acpi_pm_device_sleep_state(
&dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3);
if (acpi_state > 0)
acpi_bus_set_power(handle, acpi_state);
/* TBD: need to check if it's runtime pm request */
acpi_pm_device_run_wake(
&dev->sdev->sdev_gendev, true);
if (!(state.event & PM_EVENT_RESUME)) {
acpi_state = ata_acpi_choose_suspend_state(dev, runtime);
if (acpi_state == ACPI_STATE_D0)
continue;
if (runtime && zpodd_dev_enabled(dev) &&
acpi_state == ACPI_STATE_D3_COLD)
zpodd_enable_run_wake(dev);
acpi_bus_set_power(handle, acpi_state);
} else {
/* Ditto */
acpi_pm_device_run_wake(
&dev->sdev->sdev_gendev, false);
if (runtime && zpodd_dev_enabled(dev))
zpodd_disable_run_wake(dev);
acpi_bus_set_power(handle, ACPI_STATE_D0);
}
}
}

handle = ata_ap_acpi_handle(ap);
if (handle && state.event != PM_EVENT_ON)
acpi_bus_set_power(handle, ACPI_STATE_D3);
/* ACPI spec requires _PS0 when IDE power on and _PS3 when power off */
static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
{
struct ata_device *dev;
acpi_handle port_handle;

port_handle = ata_ap_acpi_handle(ap);
if (!port_handle)
return;

/* channel first and then drives for power on and vica versa
for power off */
if (state.event & PM_EVENT_RESUME)
acpi_bus_set_power(port_handle, ACPI_STATE_D0);

ata_for_each_dev(dev, &ap->link, ENABLED) {
acpi_handle dev_handle = ata_dev_acpi_handle(dev);
if (!dev_handle)
continue;

acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ?
ACPI_STATE_D0 : ACPI_STATE_D3);
}

if (!(state.event & PM_EVENT_RESUME))
acpi_bus_set_power(port_handle, ACPI_STATE_D3);
}

/**
* ata_acpi_set_state - set the port power state
* @ap: target ATA port
* @state: state, on/off
*
* This function sets a proper ACPI D state for the device on
* system and runtime PM operations.
*/
void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
{
if (ap->flags & ATA_FLAG_ACPI_SATA)
sata_acpi_set_state(ap, state);
else
pata_acpi_set_state(ap, state);
}

/**
Expand Down Expand Up @@ -974,57 +1020,6 @@ void ata_acpi_on_disable(struct ata_device *dev)
ata_acpi_clear_gtf(dev);
}

static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
{
struct ata_device *ata_dev = context;

if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
pm_runtime_suspended(&ata_dev->sdev->sdev_gendev))
scsi_autopm_get_device(ata_dev->sdev);
}

static void ata_acpi_add_pm_notifier(struct ata_device *dev)
{
struct acpi_device *acpi_dev;
acpi_handle handle;
acpi_status status;

handle = ata_dev_acpi_handle(dev);
if (!handle)
return;

status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_FAILURE(status))
return;

if (dev->sdev->can_power_off) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev, dev);
device_set_run_wake(&dev->sdev->sdev_gendev, true);
}
}

static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
{
struct acpi_device *acpi_dev;
acpi_handle handle;
acpi_status status;

handle = ata_dev_acpi_handle(dev);
if (!handle)
return;

status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_FAILURE(status))
return;

if (dev->sdev->can_power_off) {
device_set_run_wake(&dev->sdev->sdev_gendev, false);
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev);
}
}

static void ata_acpi_register_power_resource(struct ata_device *dev)
{
struct scsi_device *sdev = dev->sdev;
Expand All @@ -1047,13 +1042,13 @@ static void ata_acpi_unregister_power_resource(struct ata_device *dev)

void ata_acpi_bind(struct ata_device *dev)
{
ata_acpi_add_pm_notifier(dev);
ata_acpi_register_power_resource(dev);
if (zpodd_dev_enabled(dev))
dev_pm_qos_expose_flags(&dev->sdev->sdev_gendev, 0);
}

void ata_acpi_unbind(struct ata_device *dev)
{
ata_acpi_remove_pm_notifier(dev);
ata_acpi_unregister_power_resource(dev);
}

Expand Down Expand Up @@ -1095,9 +1090,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
acpi_handle *handle)
{
struct ata_device *ata_dev;
acpi_status status;
struct acpi_device *acpi_dev;
struct acpi_device_power_state *states;

if (ap->flags & ATA_FLAG_ACPI_SATA) {
if (!sata_pmp_attached(ap))
Expand All @@ -1114,21 +1106,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
if (!*handle)
return -ENODEV;

status = acpi_bus_get_device(*handle, &acpi_dev);
if (ACPI_FAILURE(status))
return 0;

/*
* If firmware has _PS3 or _PR3 for this device,
* and this ata ODD device support device attention,
* it means this device can be powered off
*/
states = acpi_dev->power.states;
if ((states[ACPI_STATE_D3_HOT].flags.valid ||
states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
ata_dev->flags & ATA_DFLAG_DA)
sdev->can_power_off = 1;

return 0;
}

Expand Down
Loading

0 comments on commit d9978ec

Please sign in to comment.