Commit abce00f9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://github.com/jgarzik/libata-dev

* 'upstream-linus' of git://github.com/jgarzik/libata-dev:
  ahci: support the STA2X11 I/O Hub
  pata_bf54x: fix BMIDE status register emulation
  ata: add ata port hibernate callbacks
  ata: update ata port's runtime status during system resume
  [SCSI] runtime resume parent for child's system-resume
  ahci: platform support for suspend/resume
  libata-core: kill duplicate statement in ata_do_set_mode()
  pata_of_platform: remove direct dependency on OF_IRQ
  SATA/PATA: convert drivers/ata/* to use module_platform_driver()
  pata_cs5536: forward port changes from cs5536
  libata-sff: use ATAPI_{COD|IO}
  ata: add ata port runtime PM callbacks
  ata: add ata port system PM callbacks
  [SCSI] sd: check runtime PM status in sd_shutdown
  [SCSI] check runtime PM status in system PM
  [SCSI] add flag to skip the runtime PM calls on the host
  ata: make ata port as parent device of scsi host
  ahci: start engine only during soft/hard resets
parents 90160371 318893e1
...@@ -820,7 +820,7 @@ config PATA_PLATFORM ...@@ -820,7 +820,7 @@ config PATA_PLATFORM
config PATA_OF_PLATFORM config PATA_OF_PLATFORM
tristate "OpenFirmware platform device PATA support" tristate "OpenFirmware platform device PATA support"
depends on PATA_PLATFORM && OF && OF_IRQ depends on PATA_PLATFORM && OF
help help
This option enables support for generic directly connected ATA This option enables support for generic directly connected ATA
devices commonly found on embedded systems with OpenFirmware devices commonly found on embedded systems with OpenFirmware
......
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
#define DRV_VERSION "3.0" #define DRV_VERSION "3.0"
enum { enum {
AHCI_PCI_BAR = 5, AHCI_PCI_BAR_STA2X11 = 0,
AHCI_PCI_BAR_STANDARD = 5,
}; };
enum board_ids { enum board_ids {
...@@ -375,6 +376,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { ...@@ -375,6 +376,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
/* ST Microelectronics */
{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */
/* Marvell */ /* Marvell */
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
...@@ -622,6 +626,13 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) ...@@ -622,6 +626,13 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
{ {
int rc; int rc;
/*
* If the device fixup already set the dma_mask to some non-standard
* value, don't extend it here. This happens on STA2X11, for example.
*/
if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
return 0;
if (using_dac && if (using_dac &&
!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
...@@ -1026,6 +1037,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1026,6 +1037,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ahci_host_priv *hpriv; struct ahci_host_priv *hpriv;
struct ata_host *host; struct ata_host *host;
int n_ports, i, rc; int n_ports, i, rc;
int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
...@@ -1057,6 +1069,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1057,6 +1069,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&pdev->dev, dev_info(&pdev->dev,
"PDC42819 can only drive SATA devices with this driver\n"); "PDC42819 can only drive SATA devices with this driver\n");
/* The Connext uses non-standard BAR */
if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
/* acquire resources */ /* acquire resources */
rc = pcim_enable_device(pdev); rc = pcim_enable_device(pdev);
if (rc) if (rc)
...@@ -1065,7 +1081,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1065,7 +1081,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* AHCI controllers often implement SFF compatible interface. /* AHCI controllers often implement SFF compatible interface.
* Grab all PCI BARs just in case. * Grab all PCI BARs just in case.
*/ */
rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
if (rc == -EBUSY) if (rc == -EBUSY)
pcim_pin_device(pdev); pcim_pin_device(pdev);
if (rc) if (rc)
...@@ -1108,7 +1124,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1108,7 +1124,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1); pci_intx(pdev, 1);
hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
/* save initial config */ /* save initial config */
ahci_pci_save_initial_config(pdev, hpriv); ahci_pci_save_initial_config(pdev, hpriv);
...@@ -1172,8 +1188,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1172,8 +1188,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i]; struct ata_port *ap = host->ports[i];
ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
ata_port_pbar_desc(ap, AHCI_PCI_BAR, ata_port_pbar_desc(ap, ahci_pci_bar,
0x100 + ap->port_no * 0x80, "port"); 0x100 + ap->port_no * 0x80, "port");
/* set enclosure management message type */ /* set enclosure management message type */
......
...@@ -202,6 +202,71 @@ static int __devexit ahci_remove(struct platform_device *pdev) ...@@ -202,6 +202,71 @@ static int __devexit ahci_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int ahci_suspend(struct device *dev)
{
struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
void __iomem *mmio = hpriv->mmio;
u32 ctl;
int rc;
if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
dev_err(dev, "firmware 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 */
rc = ata_host_suspend(host, PMSG_SUSPEND);
if (rc)
return rc;
if (pdata && pdata->suspend)
return pdata->suspend(dev);
return 0;
}
static int ahci_resume(struct device *dev)
{
struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev);
int rc;
if (pdata && pdata->resume) {
rc = pdata->resume(dev);
if (rc)
return rc;
}
if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
rc = ahci_reset_controller(host);
if (rc)
return rc;
ahci_init_controller(host);
}
ata_host_resume(host);
return 0;
}
static struct dev_pm_ops ahci_pm_ops = {
.suspend = &ahci_suspend,
.resume = &ahci_resume,
};
#endif
static const struct of_device_id ahci_of_match[] = { static const struct of_device_id ahci_of_match[] = {
{ .compatible = "calxeda,hb-ahci", }, { .compatible = "calxeda,hb-ahci", },
{}, {},
...@@ -214,6 +279,9 @@ static struct platform_driver ahci_driver = { ...@@ -214,6 +279,9 @@ static struct platform_driver ahci_driver = {
.name = "ahci", .name = "ahci",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = ahci_of_match, .of_match_table = ahci_of_match,
#ifdef CONFIG_PM
.pm = &ahci_pm_ops,
#endif
}, },
.id_table = ahci_devtype, .id_table = ahci_devtype,
}; };
......
...@@ -746,9 +746,6 @@ static void ahci_start_port(struct ata_port *ap) ...@@ -746,9 +746,6 @@ static void ahci_start_port(struct ata_port *ap)
/* enable FIS reception */ /* enable FIS reception */
ahci_start_fis_rx(ap); ahci_start_fis_rx(ap);
/* enable DMA */
ahci_start_engine(ap);
/* turn on LEDs */ /* turn on LEDs */
if (ap->flags & ATA_FLAG_EM) { if (ap->flags & ATA_FLAG_EM) {
ata_for_each_link(link, ap, EDGE) { ata_for_each_link(link, ap, EDGE) {
...@@ -2022,7 +2019,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) ...@@ -2022,7 +2019,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
ahci_power_down(ap); ahci_power_down(ap);
else { else {
ata_port_err(ap, "%s (%d)\n", emsg, rc); ata_port_err(ap, "%s (%d)\n", emsg, rc);
ahci_start_port(ap); ata_port_freeze(ap);
} }
return rc; return rc;
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/pm_runtime.h>
#include "libata.h" #include "libata.h"
#include "libata-transport.h" #include "libata-transport.h"
...@@ -3248,10 +3249,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) ...@@ -3248,10 +3249,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
ata_force_xfermask(dev); ata_force_xfermask(dev);
pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
if (libata_dma_mask & mode_mask) if (libata_dma_mask & mode_mask)
dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask,
dev->udma_mask);
else else
dma_mask = 0; dma_mask = 0;
...@@ -5234,16 +5235,13 @@ bool ata_link_offline(struct ata_link *link) ...@@ -5234,16 +5235,13 @@ bool ata_link_offline(struct ata_link *link)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
unsigned int action, unsigned int ehi_flags, unsigned int action, unsigned int ehi_flags,
int wait) int wait)
{ {
unsigned long flags;
int i, rc;
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
struct ata_link *link; struct ata_link *link;
unsigned long flags;
int rc;
/* Previous resume operation might still be in /* Previous resume operation might still be in
* progress. Wait for PM_PENDING to clear. * progress. Wait for PM_PENDING to clear.
...@@ -5276,31 +5274,16 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, ...@@ -5276,31 +5274,16 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
if (wait) { if (wait) {
ata_port_wait_eh(ap); ata_port_wait_eh(ap);
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
if (rc)
return rc;
}
} }
return 0; return rc;
} }
/** #define to_ata_port(d) container_of(d, struct ata_port, tdev)
* ata_host_suspend - suspend host
* @host: host to suspend static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
* @mesg: PM message
*
* Suspend @host. Actual operation is performed by EH. This
* function requests EH to perform PM operations and waits for EH
* to finish.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno on failure.
*/
int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
{ {
struct ata_port *ap = to_ata_port(dev);
unsigned int ehi_flags = ATA_EHI_QUIET; unsigned int ehi_flags = ATA_EHI_QUIET;
int rc; int rc;
...@@ -5315,31 +5298,108 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) ...@@ -5315,31 +5298,108 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
if (mesg.event == PM_EVENT_SUSPEND) if (mesg.event == PM_EVENT_SUSPEND)
ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1); rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, 1);
if (rc == 0)
host->dev->power.power_state = mesg;
return rc; return rc;
} }
static int ata_port_suspend(struct device *dev)
{
if (pm_runtime_suspended(dev))
return 0;
return ata_port_suspend_common(dev, PMSG_SUSPEND);
}
static int ata_port_do_freeze(struct device *dev)
{
if (pm_runtime_suspended(dev))
pm_runtime_resume(dev);
return ata_port_suspend_common(dev, PMSG_FREEZE);
}
static int ata_port_poweroff(struct device *dev)
{
if (pm_runtime_suspended(dev))
return 0;
return ata_port_suspend_common(dev, PMSG_HIBERNATE);
}
static int ata_port_resume_common(struct device *dev)
{
struct ata_port *ap = to_ata_port(dev);
int rc;
rc = ata_port_request_pm(ap, PMSG_ON, ATA_EH_RESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 1);
return rc;
}
static int ata_port_resume(struct device *dev)
{
int rc;
rc = ata_port_resume_common(dev);
if (!rc) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
}
return rc;
}
static int ata_port_runtime_idle(struct device *dev)
{
return pm_runtime_suspend(dev);
}
static const struct dev_pm_ops ata_port_pm_ops = {
.suspend = ata_port_suspend,
.resume = ata_port_resume,
.freeze = ata_port_do_freeze,
.thaw = ata_port_resume,
.poweroff = ata_port_poweroff,
.restore = ata_port_resume,
.runtime_suspend = ata_port_suspend,
.runtime_resume = ata_port_resume_common,
.runtime_idle = ata_port_runtime_idle,
};
/**
* ata_host_suspend - suspend host
* @host: host to suspend
* @mesg: PM message
*
* Suspend @host. Actual operation is performed by port suspend.
*/
int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
{
host->dev->power.power_state = mesg;
return 0;
}
/** /**
* ata_host_resume - resume host * ata_host_resume - resume host
* @host: host to resume * @host: host to resume
* *
* Resume @host. Actual operation is performed by EH. This * Resume @host. Actual operation is performed by port resume.
* function requests EH to perform PM operations and returns.
* Note that all resume operations are performed parallelly.
*
* LOCKING:
* Kernel thread context (may sleep).
*/ */
void ata_host_resume(struct ata_host *host) void ata_host_resume(struct ata_host *host)
{ {
ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host->dev->power.power_state = PMSG_ON; host->dev->power.power_state = PMSG_ON;
} }
#endif #endif
struct device_type ata_port_type = {
.name = "ata_port",
#ifdef CONFIG_PM
.pm = &ata_port_pm_ops,
#endif
};
/** /**
* ata_dev_init - Initialize an ata_device structure * ata_dev_init - Initialize an ata_device structure
* @dev: Device structure to initialize * @dev: Device structure to initialize
......
...@@ -3381,6 +3381,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) ...@@ -3381,6 +3381,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
if (!shost) if (!shost)
goto err_alloc; goto err_alloc;
shost->eh_noresume = 1;
*(struct ata_port **)&shost->hostdata[0] = ap; *(struct ata_port **)&shost->hostdata[0] = ap;
ap->scsi_host = shost; ap->scsi_host = shost;
...@@ -3398,7 +3399,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) ...@@ -3398,7 +3399,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
*/ */
shost->max_host_blocked = 1; shost->max_host_blocked = 1;
rc = scsi_add_host(ap->scsi_host, ap->host->dev); rc = scsi_add_host(ap->scsi_host, &ap->tdev);
if (rc) if (rc)
goto err_add; goto err_add;
} }
......
...@@ -929,11 +929,11 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) ...@@ -929,11 +929,11 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
bytes = (bc_hi << 8) | bc_lo; bytes = (bc_hi << 8) | bc_lo;
/* shall be cleared to zero, indicating xfer of data */ /* shall be cleared to zero, indicating xfer of data */
if (unlikely(ireason & (1 << 0))) if (unlikely(ireason & ATAPI_COD))
goto atapi_check; goto atapi_check;
/* make sure transfer direction matches expected */ /* make sure transfer direction matches expected */
i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; i_write = ((ireason & ATAPI_IO) == 0) ? 1 : 0;
if (unlikely(do_write != i_write)) if (unlikely(do_write != i_write))
goto atapi_check; goto atapi_check;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/pm_runtime.h>
#include "libata.h" #include "libata.h"
#include "libata-transport.h" #include "libata-transport.h"
...@@ -279,6 +280,7 @@ int ata_tport_add(struct device *parent, ...@@ -279,6 +280,7 @@ int ata_tport_add(struct device *parent,
struct device *dev = &ap->tdev; struct device *dev = &ap->tdev;
device_initialize(dev); device_initialize(dev);
dev->type = &ata_port_type;
dev->parent = get_device(parent); dev->parent = get_device(parent);
dev->release = ata_tport_release; dev->release = ata_tport_release;
...@@ -289,6 +291,9 @@ int ata_tport_add(struct device *parent, ...@@ -289,6 +291,9 @@ int ata_tport_add(struct device *parent,
goto tport_err; goto tport_err;
} }
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
transport_add_device(dev); transport_add_device(dev);
transport_configure_device(dev); transport_configure_device(dev);
......
...@@ -58,6 +58,7 @@ extern int atapi_passthru16; ...@@ -58,6 +58,7 @@ extern int atapi_passthru16;
extern int libata_fua; extern int libata_fua;
extern int libata_noacpi; extern int libata_noacpi;
extern int libata_allow_tpm; extern int libata_allow_tpm;
extern struct device_type ata_port_type;
extern struct ata_link *ata_dev_phys_link(struct ata_device *dev); extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
extern void ata_force_cbl(struct ata_port *ap); extern void ata_force_cbl(struct ata_port *ap);
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
......
...@@ -963,17 +963,7 @@ static struct platform_driver arasan_cf_driver = { ...@@ -963,17 +963,7 @@ static struct platform_driver arasan_cf_driver = {
}, },
}; };
static int __init arasan_cf_init(void) module_platform_driver(arasan_cf_driver);
{
return platform_driver_register(&arasan_cf_driver);
}
module_init(arasan_cf_init);
static void __exit arasan_cf_exit(void)
{
platform_driver_unregister(&arasan_cf_driver);
}
module_exit(arasan_cf_exit);
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
MODULE_DESCRIPTION("Arasan ATA Compact Flash driver"); MODULE_DESCRIPTION("Arasan ATA Compact Flash driver");
......
...@@ -454,20 +454,7 @@ static struct platform_driver pata_at91_driver = { ...@@ -454,20 +454,7 @@ static struct platform_driver pata_at91_driver = {
}, },
}; };
static int __init pata_at91_init(void) module_platform_driver(pata_at91_driver);
{
return platform_driver_register(&pata_at91_driver);
}
static void __exit pata_at91_exit(void)
{
platform_driver_unregister(&pata_at91_driver);
}
module_init(pata_at91_init);
module_exit(pata_at91_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver for CF in True IDE mode on AT91SAM9260 SoC"); MODULE_DESCRIPTION("Driver for CF in True IDE mode on AT91SAM9260 SoC");
......
...@@ -418,14 +418,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev) ...@@ -418,14 +418,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
(tcyc_tdvs<<8 | tdvs)); (tcyc_tdvs<<8 | tdvs));
ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss)); ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss));
ATAPI_SET_ULTRA_TIM_3(base, (trp<<8 | tzah)); ATAPI_SET_ULTRA_TIM_3(base, (trp<<8 | tzah));
/* Enable host ATAPI Untra DMA interrupts */
ATAPI_SET_INT_MASK(base,
ATAPI_GET_INT_MASK(base)
| UDMAIN_DONE_MASK
| UDMAOUT_DONE_MASK
| UDMAIN_TERM_MASK
| UDMAOUT_TERM_MASK);
} }
} }
} }
...@@ -470,10 +462,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev) ...@@ -470,10 +462,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td)); ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td));
ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw)); ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw));
ATAPI_SET_MULTI_TIM_2(base, (teoc<<8 | th)); ATAPI_SET_MULTI_TIM_2(base, (teoc<<8 | th));
/* Enable host ATAPI Multi DMA interrupts */
ATAPI_SET_INT_MASK(base, ATAPI_GET_INT_MASK(base)
| MULTI_DONE_MASK | MULTI_TERM_MASK);
SSYNC(); SSYNC();
} }
} }
...@@ -1153,15 +1141,11 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap) ...@@ -1153,15 +1141,11 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
{ {
unsigned char host_stat = 0; unsigned char host_stat = 0;
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
unsigned short int_status = ATAPI_GET_INT_STATUS(base);
if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON | ULTRA_XFER_ON))
host_stat |= ATA_DMA_ACTIVE; host_stat |= ATA_DMA_ACTIVE;
if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT| if (ATAPI_GET_INT_STATUS(base) & ATAPI_DEV_INT)
ATAPI_DEV_INT))
host_stat |= ATA_DMA_INTR; host_stat |= ATA_DMA_INTR;
if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT))
host_stat |= ATA_DMA_ERR|ATA_DMA_INTR;
dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat); dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat);
......
/* /*
* pata_cs5536.c - CS5536 PATA for new ATA layer * pata_cs5536.c - CS5536 PATA for new ATA layer
* (C) 2007 Martin K. Petersen <mkp@mkp.net> * (C) 2007 Martin K. Petersen <mkp@mkp.net>
* (C) 2011 Bartlomiej Zolnierkiewicz
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -55,24 +56,16 @@ MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); ...@@ -55,24 +56,16 @@ MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
#define DRV_VERSION "0.0.8" #define DRV_VERSION "0.0.8"
enum { enum {
CFG = 0, MSR_IDE_CFG = 0x51300010,
DTC = 1,
CAST = 2,
ETC = 3,
MSR_IDE_BASE = 0x51300000,
MSR_IDE_CFG = (MSR_IDE_BASE + 0x10),
MSR_IDE_DTC = (MSR_IDE_BASE + 0x12),
MSR_IDE_CAST = (MSR_IDE_BASE + 0x13),
MSR_IDE_ETC = (MSR_IDE_BASE + 0x14),
PCI_IDE_CFG = 0x40, PCI_IDE_CFG = 0x40,
PCI_IDE_DTC = 0x48,
PCI_IDE_CAST = 0x4c,
PCI_IDE_ETC = 0x50,
IDE_CFG_CHANEN = 0x2, CFG = 0,
IDE_CFG_CABLE = 0x10000, DTC = 2,
CAST = 3,
ETC = 4,
IDE_CFG_CHANEN = (1 << 1),
IDE_CFG_CABLE = (1 << 17) | (1 << 16),
IDE_D0_SHIFT = 24, IDE_D0_SHIFT = 24,
IDE_D1_SHIFT = 16, IDE_D1_SHIFT = 16,
...@@ -84,45 +77,50 @@ enum { ...@@ -84,45 +77,50 @@ enum {
IDE_CAST_CMD_MASK = 0xff, IDE_CAST_CMD_MASK = 0xff,
IDE_CAST_CMD_SHIFT = 24, IDE_CAST_CMD_SHIFT = 24,
IDE_ETC_NODMA = 0x03, IDE_ETC_UDMA_MASK = 0xc0,
}; };
static const u32 msr_reg[4] = { static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
};
static const u8 pci_reg[4] = {
PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC,
};
static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
{ {
if (unlikely(use_msr)) { if (unlikely(use_msr)) {
u32 dummy __maybe_unused; u32 dummy __maybe_unused;
rdmsr(msr_reg[reg], *val, dummy); rdmsr(MSR_IDE_CFG + reg, *val, dummy);
return 0; return 0;
} }
return pci_read_config_dword(pdev, pci_reg[reg], val); return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
} }
static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) static int cs5536_write(struct pci_dev *pdev, int reg, int val)
{ {
if (unlikely(use_msr)) { if (unlikely(use_msr)) {
wrmsr(msr_reg[reg], val, 0); wrmsr(MSR_IDE_CFG + reg, val, 0);
return 0; return 0;
} }
return pci_write_config_dword(pdev, pci_reg[reg], val); return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
}
static void cs5536_program_dtc(struct ata_device *adev, u8 tim)
{
struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev);
int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
u32 dtc;
cs5536_read(pdev, DTC, &dtc);
dtc &= ~(IDE_DRV_MASK << dshift);
dtc |= tim << dshift;
cs5536_write(pdev, DTC, dtc);
} }
/** /**
* cs5536_cable_detect - detect cable type * cs5536_cable_detect - detect cable type
* @ap: Port to detect on * @ap: Port to detect on
* *
* Perform cable detection for ATA66 capable cable. Return a libata * Perform cable detection for ATA66 capable cable.
* cable type. *
* Returns a cable type.
*/ */
static int cs5536_cable_detect(struct ata_port *ap) static int cs5536_cable_detect(struct ata_port *ap)
...@@ -132,7 +130,7 @@ static int cs5536_cable_detect(struct ata_port *ap) ...@@ -132,7 +130,7 @@ static int cs5536_cable_detect(struct ata_port *ap)
cs5536_read(pdev, CFG, &cfg); cs5536_read(pdev, CFG, &cfg);
if (cfg & (IDE_CFG_CABLE << ap->port_no)) if (cfg & IDE_CFG_CABLE)
return ATA_CBL_PATA80; return ATA_CBL_PATA80;
else else
return ATA_CBL_PATA40; return ATA_CBL_PATA40;
...@@ -162,19 +160,15 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) ...@@ -162,19 +160,15 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
struct ata_device *pair = ata_dev_pair(adev); struct ata_device *pair = ata_dev_pair(adev);
int mode = adev->pio_mode - XFER_PIO_0; int mode = adev->pio_mode - XFER_PIO_0;
int cmdmode = mode; int cmdmode = mode;
int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
u32 dtc, cast, etc; u32 cast;
if (pair) if (pair)
cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
cs5536_read(pdev, DTC, &dtc); cs5536_program_dtc(adev, drv_timings[mode]);
cs5536_read(pdev, CAST, &cast);
cs5536_read(pdev, ETC, &etc);
dtc &= ~(IDE_DRV_MASK << dshift); cs5536_read(pdev, CAST, &cast);
dtc |= drv_timings[mode] << dshift;
cast &= ~(IDE_CAST_DRV_MASK << cshift); cast &= ~(IDE_CAST_DRV_MASK << cshift);
cast |= addr_timings[mode] << cshift; cast |= addr_timings[mode] << cshift;
...@@ -182,12 +176,7 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) ...@@ -182,12 +176,7 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT;
etc &= ~(IDE_DRV_MASK << dshift);
etc |= IDE_ETC_NODMA << dshift;
cs5536_write(pdev, DTC, dtc);
cs5536_write(pdev, CAST, cast); cs5536_write(pdev, CAST, cast);
cs5536_write(pdev, ETC, etc);
} }
/** /**
...@@ -208,25 +197,21 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) ...@@ -208,25 +197,21 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
}; };
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 dtc, etc; u32 etc;
int mode = adev->dma_mode; int mode = adev->dma_mode;
int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
if (mode >= XFER_UDMA_0) {
cs5536_read(pdev, ETC, &etc); cs5536_read(pdev, ETC, &etc);
if (mode >= XFER_UDMA_0) {
etc &= ~(IDE_DRV_MASK << dshift); etc &= ~(IDE_DRV_MASK << dshift);
etc |= udma_timings[mode - XFER_UDMA_0] << dshift; etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
cs5536_write(pdev, ETC, etc);
} else { /* MWDMA */ } else { /* MWDMA */
cs5536_read(pdev, DTC, &dtc); etc &= ~(IDE_ETC_UDMA_MASK << dshift);
cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]);
dtc &= ~(IDE_DRV_MASK << dshift);
dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift;
cs5536_write(pdev, DTC, dtc);
} }
cs5536_write(pdev, ETC, etc);
} }
static struct scsi_host_template cs5536_sht = { static struct scsi_host_template cs5536_sht = {
......
...@@ -235,17 +235,7 @@ static struct platform_driver pata_imx_driver = { ...@@ -235,17 +235,7 @@ static struct platform_driver pata_imx_driver = {
}, },
}; };
static int __init pata_imx_init(void) module_platform_driver(pata_imx_driver);
{
return platform_driver_register(&pata_imx_driver);
}
static void __exit pata_imx_exit(void)
{
platform_driver_unregister(&pata_imx_driver);
}
module_init(pata_imx_init);
module_exit(pata_imx_exit);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("low-level driver for iMX PATA"); MODULE_DESCRIPTION("low-level driver for iMX PATA");
......
...@@ -205,21 +205,10 @@ static struct platform_driver ixp4xx_pata_platform_driver = { ...@@ -205,21 +205,10 @@ static struct platform_driver ixp4xx_pata_platform_driver = {
.remove = __devexit_p(ixp4xx_pata_remove), .remove = __devexit_p(ixp4xx_pata_remove),
}; };
static int __init ixp4xx_pata_init(void) module_platform_driver(ixp4xx_pata_platform_driver);
{
return platform_driver_register(&ixp4xx_pata_platform_driver);
}
static void __exit ixp4xx_pata_exit(void)
{
platform_driver_unregister(&ixp4xx_pata_platform_driver);
}
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA"); MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_NAME); MODULE_ALIAS("platform:" DRV_NAME);
module_init(ixp4xx_pata_init);
module_exit(ixp4xx_pata_exit);
...@@ -897,26 +897,7 @@ static struct platform_driver mpc52xx_ata_of_platform_driver = { ...@@ -897,26 +897,7 @@ static struct platform_driver mpc52xx_ata_of_platform_driver = {
}, },
}; };
module_platform_driver(mpc52xx_ata_of_platform_driver);
/* ======================================================================== */
/* Module */
/* ======================================================================== */
static int __init
mpc52xx_ata_init(void)
{
printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
return platform_driver_register(&mpc52xx_ata_of_platform_driver);
}
static void __exit
mpc52xx_ata_exit(void)
{
platform_driver_unregister(&mpc52xx_ata_of_platform_driver);
}
module_init(mpc52xx_ata_init);
module_exit(mpc52xx_ata_exit);
MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>"); MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
static int __devinit pata_of_platform_probe(struct platform_device *ofdev) static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
...@@ -22,7 +21,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev) ...@@ -22,7 +21,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
struct device_node *dn = ofdev->dev.of_node; struct device_node *dn = ofdev->dev.of_node;
struct resource io_res; struct resource io_res;
struct resource ctl_res; struct resource ctl_res;
struct resource irq_res; struct resource *irq_res;
unsigned int reg_shift = 0; unsigned int reg_shift = 0;
int pio_mode = 0; int pio_mode = 0;
int pio_mask; int pio_mask;
...@@ -51,11 +50,9 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev) ...@@ -51,11 +50,9 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
} }
} }
ret = of_irq_to_resource(dn, 0, &irq_res); irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
if (!ret) if (irq_res)
irq_res.start = irq_res.end = 0; irq_res->flags = 0;
else
irq_res.flags = 0;
prop = of_get_property(dn, "reg-shift", NULL); prop = of_get_property(dn, "reg-shift", NULL);
if (prop) if (prop)
...@@ -75,7 +72,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev) ...@@ -75,7 +72,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
pio_mask = 1 << pio_mode; pio_mask = 1 << pio_mode;
pio_mask |= (1 << pio_mode) - 1; pio_mask |= (1 << pio_mode) - 1;
return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, irq_res,
reg_shift, pio_mask); reg_shift, pio_mask);
} }
...@@ -101,17 +98,7 @@ static struct platform_driver pata_of_platform_driver = { ...@@ -101,17 +98,7 @@ static struct platform_driver pata_of_platform_driver = {
.remove = __devexit_p(pata_of_platform_remove), .remove = __devexit_p(pata_of_platform_remove),
}; };
static int __init pata_of_platform_init(void) module_platform_driver(pata_of_platform_driver);
{
return platform_driver_register(&pata_of_platform_driver);
}
module_init(pata_of_platform_init);
static void __exit pata_of_platform_exit(void)
{
platform_driver_unregister(&pata_of_platform_driver);
}
module_exit(pata_of_platform_exit);
MODULE_DESCRIPTION("OF-platform PATA driver"); MODULE_DESCRIPTION("OF-platform PATA driver");
MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
......
...@@ -132,20 +132,9 @@ static struct platform_driver palmld_pata_platform_driver = { ...@@ -132,20 +132,9 @@ static struct platform_driver palmld_pata_platform_driver = {
.remove = __devexit_p(palmld_pata_remove), .remove = __devexit_p(palmld_pata_remove),
}; };
static int __init palmld_pata_init(void) module_platform_driver(palmld_pata_platform_driver);
{
return platform_driver_register(&palmld_pata_platform_driver);
}
static void __exit palmld_pata_exit(void)
{
platform_driver_unregister(&palmld_pata_platform_driver);
}
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
MODULE_DESCRIPTION("PalmLD PATA driver"); MODULE_DESCRIPTION("PalmLD PATA driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME); MODULE_ALIAS("platform:" DRV_NAME);
module_init(palmld_pata_init);
module_exit(palmld_pata_exit);
...@@ -256,17 +256,7 @@ static struct platform_driver pata_platform_driver = { ...@@ -256,17 +256,7 @@ static struct platform_driver pata_platform_driver = {
}, },
}; };
static int __init pata_platform_init(void) module_platform_driver(pata_platform_driver);
{
return platform_driver_register(&pata_platform_driver);
}
static void __exit pata_platform_exit(void)
{
platform_driver_unregister(&pata_platform_driver);
}
module_init(pata_platform_init);
module_exit(pata_platform_exit);
module_param(pio_mask, int, 0); module_param(pio_mask, int, 0);
......
...@@ -390,18 +390,7 @@ static struct platform_driver pxa_ata_driver = { ...@@ -390,18 +390,7 @@ static struct platform_driver pxa_ata_driver = {
}, },
}; };
static int __init pxa_ata_init(void) module_platform_driver(pxa_ata_driver);
{
return platform_driver_register(&pxa_ata_driver);
}
static void __exit pxa_ata_exit(void)
{
platform_driver_unregister(&pxa_ata_driver);
}
module_init(pxa_ata_init);
module_exit(pxa_ata_exit);
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
MODULE_DESCRIPTION("DMA-capable driver for PATA on PXA CPU"); MODULE_DESCRIPTION("DMA-capable driver for PATA on PXA CPU");
......
...@@ -188,9 +188,6 @@ static __devexit int rb532_pata_driver_remove(struct platform_device *pdev) ...@@ -188,9 +188,6 @@ static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
return 0; return 0;
} }
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" DRV_NAME);
static struct platform_driver rb532_pata_platform_driver = { static struct platform_driver rb532_pata_platform_driver = {
.probe = rb532_pata_driver_probe, .probe = rb532_pata_driver_probe,
.remove = __devexit_p(rb532_pata_driver_remove), .remove = __devexit_p(rb532_pata_driver_remove),
...@@ -200,27 +197,13 @@ static struct platform_driver rb532_pata_platform_driver = { ...@@ -200,27 +197,13 @@ static struct platform_driver rb532_pata_platform_driver = {
}, },
}; };
/* ------------------------------------------------------------------------ */
#define DRV_INFO DRV_DESC " version " DRV_VERSION #define DRV_INFO DRV_DESC " version " DRV_VERSION
static int __init rb532_pata_module_init(void) module_platform_driver(rb532_pata_platform_driver);
{
printk(KERN_INFO DRV_INFO "\n");
return platform_driver_register(&rb532_pata_platform_driver);
}
static void __exit rb532_pata_module_exit(void)
{
platform_driver_unregister(&rb532_pata_platform_driver);
}
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
MODULE_DESCRIPTION(DRV_DESC); MODULE_DESCRIPTION(DRV_DESC);
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
module_init(rb532_pata_module_init);
module_exit(rb532_pata_module_exit);
...@@ -1777,18 +1777,7 @@ static struct platform_driver sata_dwc_driver = { ...@@ -1777,18 +1777,7 @@ static struct platform_driver sata_dwc_driver = {
.remove = sata_dwc_remove, .remove = sata_dwc_remove,
}; };
static int __init sata_dwc_init(void) module_platform_driver(sata_dwc_driver);
{
return platform_driver_register(&sata_dwc_driver);
}
static void __exit sata_dwc_exit(void)
{
platform_driver_unregister(&sata_dwc_driver);
}
module_init(sata_dwc_init);
module_exit(sata_dwc_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>"); MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>");
......
...@@ -1452,21 +1452,9 @@ static struct platform_driver fsl_sata_driver = { ...@@ -1452,21 +1452,9 @@ static struct platform_driver fsl_sata_driver = {
#endif #endif
}; };
static int __init sata_fsl_init(void) module_platform_driver(fsl_sata_driver);
{
platform_driver_register(&fsl_sata_driver);
return 0;
}
static void __exit sata_fsl_exit(void)
{
platform_driver_unregister(&fsl_sata_driver);
}
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor"); MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor");
MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver"); MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver");
MODULE_VERSION("1.10"); MODULE_VERSION("1.10");
module_init(sata_fsl_init);
module_exit(sata_fsl_exit);
...@@ -1812,7 +1812,7 @@ int scsi_error_handler(void *data) ...@@ -1812,7 +1812,7 @@ int scsi_error_handler(void *data)
* what we need to do to get it up and online again (if we can). * what we need to do to get it up and online again (if we can).
* If we fail, we end up taking the thing offline. * If we fail, we end up taking the thing offline.
*/ */
if (scsi_autopm_get_host(shost) != 0) { if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) {
SCSI_LOG_ERROR_RECOVERY(1, SCSI_LOG_ERROR_RECOVERY(1,
printk(KERN_ERR "Error handler scsi_eh_%d " printk(KERN_ERR "Error handler scsi_eh_%d "
"unable to autoresume\n", "unable to autoresume\n",
...@@ -1833,6 +1833,7 @@ int scsi_error_handler(void *data) ...@@ -1833,6 +1833,7 @@ int scsi_error_handler(void *data)
* which are still online. * which are still online.
*/ */
scsi_restart_operations(shost); scsi_restart_operations(shost);
if (!shost->eh_noresume)
scsi_autopm_put_host(shost); scsi_autopm_put_host(shost);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
......
...@@ -49,8 +49,22 @@ static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) ...@@ -49,8 +49,22 @@ static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
{ {
int err = 0; int err = 0;
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev)) {
/*
* sd is the only high-level SCSI driver to implement runtime
* PM, and sd treats runtime suspend, system suspend, and
* system hibernate identically (but not system freeze).
*/
if (pm_runtime_suspended(dev)) {
if (msg.event == PM_EVENT_SUSPEND ||
msg.event == PM_EVENT_HIBERNATE)
return 0; /* already suspended */
/* wake up device so that FREEZE will succeed */
pm_runtime_resume(dev);
}
err = scsi_dev_type_suspend(dev, msg); err = scsi_dev_type_suspend(dev, msg);
}
return err; return err;
} }
...@@ -58,8 +72,17 @@ static int scsi_bus_resume_common(struct device *dev) ...@@ -58,8 +72,17 @@ static int scsi_bus_resume_common(struct device *dev)
{ {
int err = 0; int err = 0;
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev)) {
/*
* Parent device may have runtime suspended as soon as
* it is woken up during the system resume.
*
* Resume it on behalf of child.
*/
pm_runtime_get_sync(dev->parent);
err = scsi_dev_type_resume(dev); err = scsi_dev_type_resume(dev);
pm_runtime_put_sync(dev->parent);
}
if (err == 0) { if (err == 0) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/string_helpers.h> #include <linux/string_helpers.h>
#include <linux/async.h> #include <linux/async.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -2741,6 +2742,9 @@ static void sd_shutdown(struct device *dev) ...@@ -2741,6 +2742,9 @@ static void sd_shutdown(struct device *dev)
if (!sdkp) if (!sdkp)
return; /* this can happen */ return; /* this can happen */
if (pm_runtime_suspended(dev))
goto exit;
if (sdkp->WCE) { if (sdkp->WCE) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
sd_sync_cache(sdkp); sd_sync_cache(sdkp);
...@@ -2751,6 +2755,7 @@ static void sd_shutdown(struct device *dev) ...@@ -2751,6 +2755,7 @@ static void sd_shutdown(struct device *dev)
sd_start_stop_device(sdkp, 0); sd_start_stop_device(sdkp, 0);
} }
exit:
scsi_disk_put(sdkp); scsi_disk_put(sdkp);
} }
......
...@@ -23,6 +23,8 @@ struct ata_port_info; ...@@ -23,6 +23,8 @@ struct ata_port_info;
struct ahci_platform_data { struct ahci_platform_data {
int (*init)(struct device *dev, void __iomem *addr); int (*init)(struct device *dev, void __iomem *addr);
void (*exit)(struct device *dev); void (*exit)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
const struct ata_port_info *ata_port_info; const struct ata_port_info *ata_port_info;
unsigned int force_port_map; unsigned int force_port_map;
unsigned int mask_port_map; unsigned int mask_port_map;
......
...@@ -669,6 +669,9 @@ struct Scsi_Host { ...@@ -669,6 +669,9 @@ struct Scsi_Host {
/* Asynchronous scan in progress */ /* Asynchronous scan in progress */
unsigned async_scan:1; unsigned async_scan:1;
/* Don't resume host in EH */
unsigned eh_noresume:1;
/* /*
* Optional work queue to be utilized by the transport * Optional work queue to be utilized by the transport
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment