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
This commit is contained in:
commit
abce00f962
@ -820,7 +820,7 @@ config PATA_PLATFORM
|
||||
|
||||
config PATA_OF_PLATFORM
|
||||
tristate "OpenFirmware platform device PATA support"
|
||||
depends on PATA_PLATFORM && OF && OF_IRQ
|
||||
depends on PATA_PLATFORM && OF
|
||||
help
|
||||
This option enables support for generic directly connected ATA
|
||||
devices commonly found on embedded systems with OpenFirmware
|
||||
|
@ -52,7 +52,8 @@
|
||||
#define DRV_VERSION "3.0"
|
||||
|
||||
enum {
|
||||
AHCI_PCI_BAR = 5,
|
||||
AHCI_PCI_BAR_STA2X11 = 0,
|
||||
AHCI_PCI_BAR_STANDARD = 5,
|
||||
};
|
||||
|
||||
enum board_ids {
|
||||
@ -375,6 +376,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
|
||||
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
|
||||
|
||||
/* ST Microelectronics */
|
||||
{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */
|
||||
|
||||
/* Marvell */
|
||||
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
|
||||
{ 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)
|
||||
{
|
||||
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 &&
|
||||
!pci_set_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)
|
||||
struct ahci_host_priv *hpriv;
|
||||
struct ata_host *host;
|
||||
int n_ports, i, rc;
|
||||
int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
@ -1057,6 +1069,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev_info(&pdev->dev,
|
||||
"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 */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
@ -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.
|
||||
* 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)
|
||||
pcim_pin_device(pdev);
|
||||
if (rc)
|
||||
@ -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))
|
||||
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 */
|
||||
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)
|
||||
for (i = 0; i < host->n_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,
|
||||
ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
|
||||
ata_port_pbar_desc(ap, ahci_pci_bar,
|
||||
0x100 + ap->port_no * 0x80, "port");
|
||||
|
||||
/* set enclosure management message type */
|
||||
|
@ -202,6 +202,71 @@ static int __devexit ahci_remove(struct platform_device *pdev)
|
||||
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[] = {
|
||||
{ .compatible = "calxeda,hb-ahci", },
|
||||
{},
|
||||
@ -214,6 +279,9 @@ static struct platform_driver ahci_driver = {
|
||||
.name = "ahci",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ahci_of_match,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &ahci_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.id_table = ahci_devtype,
|
||||
};
|
||||
|
@ -746,9 +746,6 @@ static void ahci_start_port(struct ata_port *ap)
|
||||
/* enable FIS reception */
|
||||
ahci_start_fis_rx(ap);
|
||||
|
||||
/* enable DMA */
|
||||
ahci_start_engine(ap);
|
||||
|
||||
/* turn on LEDs */
|
||||
if (ap->flags & ATA_FLAG_EM) {
|
||||
ata_for_each_link(link, ap, EDGE) {
|
||||
@ -2022,7 +2019,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
||||
ahci_power_down(ap);
|
||||
else {
|
||||
ata_port_err(ap, "%s (%d)\n", emsg, rc);
|
||||
ahci_start_port(ap);
|
||||
ata_port_freeze(ap);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "libata.h"
|
||||
#include "libata-transport.h"
|
||||
@ -3248,10 +3249,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
|
||||
ata_force_xfermask(dev);
|
||||
|
||||
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)
|
||||
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
|
||||
dma_mask = 0;
|
||||
|
||||
@ -5234,73 +5235,55 @@ bool ata_link_offline(struct ata_link *link)
|
||||
}
|
||||
|
||||
#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,
|
||||
int wait)
|
||||
{
|
||||
struct ata_link *link;
|
||||
unsigned long flags;
|
||||
int i, rc;
|
||||
int rc;
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
struct ata_link *link;
|
||||
|
||||
/* Previous resume operation might still be in
|
||||
* progress. Wait for PM_PENDING to clear.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
}
|
||||
|
||||
/* request PM ops to EH */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
ap->pm_mesg = mesg;
|
||||
if (wait) {
|
||||
rc = 0;
|
||||
ap->pm_result = &rc;
|
||||
}
|
||||
|
||||
ap->pflags |= ATA_PFLAG_PM_PENDING;
|
||||
ata_for_each_link(link, ap, HOST_FIRST) {
|
||||
link->eh_info.action |= action;
|
||||
link->eh_info.flags |= ehi_flags;
|
||||
}
|
||||
|
||||
ata_port_schedule_eh(ap);
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
/* wait and check result */
|
||||
if (wait) {
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
/* Previous resume operation might still be in
|
||||
* progress. Wait for PM_PENDING to clear.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* request PM ops to EH */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
ap->pm_mesg = mesg;
|
||||
if (wait) {
|
||||
rc = 0;
|
||||
ap->pm_result = &rc;
|
||||
}
|
||||
|
||||
ap->pflags |= ATA_PFLAG_PM_PENDING;
|
||||
ata_for_each_link(link, ap, HOST_FIRST) {
|
||||
link->eh_info.action |= action;
|
||||
link->eh_info.flags |= ehi_flags;
|
||||
}
|
||||
|
||||
ata_port_schedule_eh(ap);
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
/* wait and check result */
|
||||
if (wait) {
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_host_suspend - suspend host
|
||||
* @host: host to suspend
|
||||
* @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)
|
||||
#define to_ata_port(d) container_of(d, struct ata_port, tdev)
|
||||
|
||||
static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
struct ata_port *ap = to_ata_port(dev);
|
||||
unsigned int ehi_flags = ATA_EHI_QUIET;
|
||||
int rc;
|
||||
|
||||
@ -5315,31 +5298,108 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
|
||||
if (mesg.event == PM_EVENT_SUSPEND)
|
||||
ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
|
||||
|
||||
rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
|
||||
if (rc == 0)
|
||||
host->dev->power.power_state = mesg;
|
||||
rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, 1);
|
||||
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
|
||||
* @host: host to resume
|
||||
*
|
||||
* Resume @host. Actual operation is performed by EH. This
|
||||
* function requests EH to perform PM operations and returns.
|
||||
* Note that all resume operations are performed parallelly.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
* Resume @host. Actual operation is performed by port resume.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
#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
|
||||
* @dev: Device structure to initialize
|
||||
|
@ -3381,6 +3381,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
|
||||
if (!shost)
|
||||
goto err_alloc;
|
||||
|
||||
shost->eh_noresume = 1;
|
||||
*(struct ata_port **)&shost->hostdata[0] = ap;
|
||||
ap->scsi_host = shost;
|
||||
|
||||
@ -3398,7 +3399,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
|
||||
*/
|
||||
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)
|
||||
goto err_add;
|
||||
}
|
||||
|
@ -929,11 +929,11 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
|
||||
bytes = (bc_hi << 8) | bc_lo;
|
||||
|
||||
/* shall be cleared to zero, indicating xfer of data */
|
||||
if (unlikely(ireason & (1 << 0)))
|
||||
if (unlikely(ireason & ATAPI_COD))
|
||||
goto atapi_check;
|
||||
|
||||
/* 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))
|
||||
goto atapi_check;
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/libata.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "libata.h"
|
||||
#include "libata-transport.h"
|
||||
@ -279,6 +280,7 @@ int ata_tport_add(struct device *parent,
|
||||
struct device *dev = &ap->tdev;
|
||||
|
||||
device_initialize(dev);
|
||||
dev->type = &ata_port_type;
|
||||
|
||||
dev->parent = get_device(parent);
|
||||
dev->release = ata_tport_release;
|
||||
@ -289,6 +291,9 @@ int ata_tport_add(struct device *parent,
|
||||
goto tport_err;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
transport_add_device(dev);
|
||||
transport_configure_device(dev);
|
||||
|
||||
|
@ -58,6 +58,7 @@ extern int atapi_passthru16;
|
||||
extern int libata_fua;
|
||||
extern int libata_noacpi;
|
||||
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 void ata_force_cbl(struct ata_port *ap);
|
||||
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
|
||||
|
@ -963,17 +963,7 @@ static struct platform_driver arasan_cf_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init arasan_cf_init(void)
|
||||
{
|
||||
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_platform_driver(arasan_cf_driver);
|
||||
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
|
||||
MODULE_DESCRIPTION("Arasan ATA Compact Flash driver");
|
||||
|
@ -454,20 +454,7 @@ static struct platform_driver pata_at91_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_at91_init(void)
|
||||
{
|
||||
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_platform_driver(pata_at91_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
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)
|
||||
(tcyc_tdvs<<8 | tdvs));
|
||||
ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss));
|
||||
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)
|
||||
ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td));
|
||||
ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw));
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -1153,15 +1141,11 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
|
||||
{
|
||||
unsigned char host_stat = 0;
|
||||
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;
|
||||
if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT|
|
||||
ATAPI_DEV_INT))
|
||||
if (ATAPI_GET_INT_STATUS(base) & ATAPI_DEV_INT)
|
||||
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);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* pata_cs5536.c - CS5536 PATA for new ATA layer
|
||||
* (C) 2007 Martin K. Petersen <mkp@mkp.net>
|
||||
* (C) 2011 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* 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
|
||||
@ -55,24 +56,16 @@ MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
|
||||
#define DRV_VERSION "0.0.8"
|
||||
|
||||
enum {
|
||||
CFG = 0,
|
||||
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),
|
||||
|
||||
MSR_IDE_CFG = 0x51300010,
|
||||
PCI_IDE_CFG = 0x40,
|
||||
PCI_IDE_DTC = 0x48,
|
||||
PCI_IDE_CAST = 0x4c,
|
||||
PCI_IDE_ETC = 0x50,
|
||||
|
||||
IDE_CFG_CHANEN = 0x2,
|
||||
IDE_CFG_CABLE = 0x10000,
|
||||
CFG = 0,
|
||||
DTC = 2,
|
||||
CAST = 3,
|
||||
ETC = 4,
|
||||
|
||||
IDE_CFG_CHANEN = (1 << 1),
|
||||
IDE_CFG_CABLE = (1 << 17) | (1 << 16),
|
||||
|
||||
IDE_D0_SHIFT = 24,
|
||||
IDE_D1_SHIFT = 16,
|
||||
@ -84,45 +77,50 @@ enum {
|
||||
IDE_CAST_CMD_MASK = 0xff,
|
||||
IDE_CAST_CMD_SHIFT = 24,
|
||||
|
||||
IDE_ETC_NODMA = 0x03,
|
||||
IDE_ETC_UDMA_MASK = 0xc0,
|
||||
};
|
||||
|
||||
static const u32 msr_reg[4] = {
|
||||
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)
|
||||
static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
|
||||
{
|
||||
if (unlikely(use_msr)) {
|
||||
u32 dummy __maybe_unused;
|
||||
|
||||
rdmsr(msr_reg[reg], *val, dummy);
|
||||
rdmsr(MSR_IDE_CFG + reg, *val, dummy);
|
||||
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)) {
|
||||
wrmsr(msr_reg[reg], val, 0);
|
||||
wrmsr(MSR_IDE_CFG + reg, val, 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
|
||||
* @ap: Port to detect on
|
||||
*
|
||||
* Perform cable detection for ATA66 capable cable. Return a libata
|
||||
* cable type.
|
||||
* Perform cable detection for ATA66 capable cable.
|
||||
*
|
||||
* Returns a cable type.
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
if (cfg & (IDE_CFG_CABLE << ap->port_no))
|
||||
if (cfg & IDE_CFG_CABLE)
|
||||
return ATA_CBL_PATA80;
|
||||
else
|
||||
return ATA_CBL_PATA40;
|
||||
@ -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);
|
||||
int mode = adev->pio_mode - XFER_PIO_0;
|
||||
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;
|
||||
u32 dtc, cast, etc;
|
||||
u32 cast;
|
||||
|
||||
if (pair)
|
||||
cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
|
||||
|
||||
cs5536_read(pdev, DTC, &dtc);
|
||||
cs5536_read(pdev, CAST, &cast);
|
||||
cs5536_read(pdev, ETC, &etc);
|
||||
cs5536_program_dtc(adev, drv_timings[mode]);
|
||||
|
||||
dtc &= ~(IDE_DRV_MASK << dshift);
|
||||
dtc |= drv_timings[mode] << dshift;
|
||||
cs5536_read(pdev, CAST, &cast);
|
||||
|
||||
cast &= ~(IDE_CAST_DRV_MASK << cshift);
|
||||
cast |= addr_timings[mode] << cshift;
|
||||
@ -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 |= 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, ETC, etc);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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);
|
||||
u32 dtc, etc;
|
||||
u32 etc;
|
||||
int mode = adev->dma_mode;
|
||||
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 |= udma_timings[mode - XFER_UDMA_0] << dshift;
|
||||
|
||||
cs5536_write(pdev, ETC, etc);
|
||||
} else { /* MWDMA */
|
||||
cs5536_read(pdev, DTC, &dtc);
|
||||
|
||||
dtc &= ~(IDE_DRV_MASK << dshift);
|
||||
dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift;
|
||||
|
||||
cs5536_write(pdev, DTC, dtc);
|
||||
etc &= ~(IDE_ETC_UDMA_MASK << dshift);
|
||||
cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]);
|
||||
}
|
||||
|
||||
cs5536_write(pdev, ETC, etc);
|
||||
}
|
||||
|
||||
static struct scsi_host_template cs5536_sht = {
|
||||
|
@ -235,17 +235,7 @@ static struct platform_driver pata_imx_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_imx_init(void)
|
||||
{
|
||||
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_platform_driver(pata_imx_driver);
|
||||
|
||||
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
|
||||
MODULE_DESCRIPTION("low-level driver for iMX PATA");
|
||||
|
@ -205,21 +205,10 @@ static struct platform_driver ixp4xx_pata_platform_driver = {
|
||||
.remove = __devexit_p(ixp4xx_pata_remove),
|
||||
};
|
||||
|
||||
static int __init ixp4xx_pata_init(void)
|
||||
{
|
||||
return platform_driver_register(&ixp4xx_pata_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit ixp4xx_pata_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ixp4xx_pata_platform_driver);
|
||||
}
|
||||
module_platform_driver(ixp4xx_pata_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
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 = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* 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_platform_driver(mpc52xx_ata_of_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
|
||||
MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ata_platform.h>
|
||||
|
||||
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 resource io_res;
|
||||
struct resource ctl_res;
|
||||
struct resource irq_res;
|
||||
struct resource *irq_res;
|
||||
unsigned int reg_shift = 0;
|
||||
int pio_mode = 0;
|
||||
int pio_mask;
|
||||
@ -51,11 +50,9 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_irq_to_resource(dn, 0, &irq_res);
|
||||
if (!ret)
|
||||
irq_res.start = irq_res.end = 0;
|
||||
else
|
||||
irq_res.flags = 0;
|
||||
irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
|
||||
if (irq_res)
|
||||
irq_res->flags = 0;
|
||||
|
||||
prop = of_get_property(dn, "reg-shift", NULL);
|
||||
if (prop)
|
||||
@ -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) - 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);
|
||||
}
|
||||
|
||||
@ -101,17 +98,7 @@ static struct platform_driver pata_of_platform_driver = {
|
||||
.remove = __devexit_p(pata_of_platform_remove),
|
||||
};
|
||||
|
||||
static int __init pata_of_platform_init(void)
|
||||
{
|
||||
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_platform_driver(pata_of_platform_driver);
|
||||
|
||||
MODULE_DESCRIPTION("OF-platform PATA driver");
|
||||
MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
|
||||
|
@ -132,20 +132,9 @@ static struct platform_driver palmld_pata_platform_driver = {
|
||||
.remove = __devexit_p(palmld_pata_remove),
|
||||
};
|
||||
|
||||
static int __init palmld_pata_init(void)
|
||||
{
|
||||
return platform_driver_register(&palmld_pata_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit palmld_pata_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&palmld_pata_platform_driver);
|
||||
}
|
||||
module_platform_driver(palmld_pata_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
|
||||
MODULE_DESCRIPTION("PalmLD PATA driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
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 = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_platform_init(void)
|
||||
{
|
||||
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_platform_driver(pata_platform_driver);
|
||||
|
||||
module_param(pio_mask, int, 0);
|
||||
|
||||
|
@ -390,18 +390,7 @@ static struct platform_driver pxa_ata_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pxa_ata_init(void)
|
||||
{
|
||||
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_platform_driver(pxa_ata_driver);
|
||||
|
||||
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
|
||||
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)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
||||
static struct platform_driver rb532_pata_platform_driver = {
|
||||
.probe = rb532_pata_driver_probe,
|
||||
.remove = __devexit_p(rb532_pata_driver_remove),
|
||||
@ -200,27 +197,13 @@ static struct platform_driver rb532_pata_platform_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define DRV_INFO DRV_DESC " version " DRV_VERSION
|
||||
|
||||
static int __init rb532_pata_module_init(void)
|
||||
{
|
||||
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_platform_driver(rb532_pata_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
|
||||
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
|
||||
MODULE_DESCRIPTION(DRV_DESC);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(rb532_pata_module_init);
|
||||
module_exit(rb532_pata_module_exit);
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
@ -1777,18 +1777,7 @@ static struct platform_driver sata_dwc_driver = {
|
||||
.remove = sata_dwc_remove,
|
||||
};
|
||||
|
||||
static int __init sata_dwc_init(void)
|
||||
{
|
||||
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_platform_driver(sata_dwc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>");
|
||||
|
@ -1452,21 +1452,9 @@ static struct platform_driver fsl_sata_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init sata_fsl_init(void)
|
||||
{
|
||||
platform_driver_register(&fsl_sata_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sata_fsl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&fsl_sata_driver);
|
||||
}
|
||||
module_platform_driver(fsl_sata_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor");
|
||||
MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver");
|
||||
MODULE_VERSION("1.10");
|
||||
|
||||
module_init(sata_fsl_init);
|
||||
module_exit(sata_fsl_exit);
|
||||
|
@ -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).
|
||||
* 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,
|
||||
printk(KERN_ERR "Error handler scsi_eh_%d "
|
||||
"unable to autoresume\n",
|
||||
@ -1833,7 +1833,8 @@ int scsi_error_handler(void *data)
|
||||
* which are still online.
|
||||
*/
|
||||
scsi_restart_operations(shost);
|
||||
scsi_autopm_put_host(shost);
|
||||
if (!shost->eh_noresume)
|
||||
scsi_autopm_put_host(shost);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
@ -49,8 +49,22 @@ static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
|
||||
{
|
||||
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);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -58,8 +72,17 @@ static int scsi_bus_resume_common(struct device *dev)
|
||||
{
|
||||
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);
|
||||
pm_runtime_put_sync(dev->parent);
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
pm_runtime_disable(dev);
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
@ -2741,6 +2742,9 @@ static void sd_shutdown(struct device *dev)
|
||||
if (!sdkp)
|
||||
return; /* this can happen */
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
goto exit;
|
||||
|
||||
if (sdkp->WCE) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
|
||||
sd_sync_cache(sdkp);
|
||||
@ -2751,6 +2755,7 @@ static void sd_shutdown(struct device *dev)
|
||||
sd_start_stop_device(sdkp, 0);
|
||||
}
|
||||
|
||||
exit:
|
||||
scsi_disk_put(sdkp);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ struct ata_port_info;
|
||||
struct ahci_platform_data {
|
||||
int (*init)(struct device *dev, void __iomem *addr);
|
||||
void (*exit)(struct device *dev);
|
||||
int (*suspend)(struct device *dev);
|
||||
int (*resume)(struct device *dev);
|
||||
const struct ata_port_info *ata_port_info;
|
||||
unsigned int force_port_map;
|
||||
unsigned int mask_port_map;
|
||||
|
@ -669,6 +669,9 @@ struct Scsi_Host {
|
||||
/* Asynchronous scan in progress */
|
||||
unsigned async_scan:1;
|
||||
|
||||
/* Don't resume host in EH */
|
||||
unsigned eh_noresume:1;
|
||||
|
||||
/*
|
||||
* Optional work queue to be utilized by the transport
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user