aboutsummaryrefslogtreecommitdiff
path: root/drivers/ata
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2010-08-15 01:06:31 -0400
committerLen Brown <len.brown@intel.com>2010-08-15 01:06:31 -0400
commit95ee46aa8698f2000647dfb362400fadbb5807cf (patch)
treee5a05c7297f997e191c73091934e42e3195c0e40 /drivers/ata
parentcfa806f059801dbe7e435745eb2e187c8bfe1e7f (diff)
parent92fa5bd9a946b6e7aab6764e7312e4e3d9bed295 (diff)
Merge branch 'linus' into release
Conflicts: drivers/acpi/debug.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/Kconfig29
-rw-r--r--drivers/ata/Makefile4
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/ata/ahci_platform.c26
-rw-r--r--drivers/ata/ata_generic.c4
-rw-r--r--drivers/ata/ata_piix.c8
-rw-r--r--drivers/ata/libata-core.c181
-rw-r--r--drivers/ata/libata-eh.c5
-rw-r--r--drivers/ata/libata-scsi.c14
-rw-r--r--drivers/ata/libata-sff.c9
-rw-r--r--drivers/ata/libata.h1
-rw-r--r--drivers/ata/pata_mpc52xx.c8
-rw-r--r--drivers/ata/pata_of_platform.c4
-rw-r--r--drivers/ata/pata_pcmcia.c38
-rw-r--r--drivers/ata/pata_pxa.c411
-rw-r--r--drivers/ata/pata_samsung_cf.c683
-rw-r--r--drivers/ata/pata_scc.c3
-rw-r--r--drivers/ata/sata_dwc_460ex.c1756
-rw-r--r--drivers/ata/sata_fsl.c28
-rw-r--r--drivers/ata/sata_mv.c47
-rw-r--r--drivers/ata/sata_nv.c32
21 files changed, 3074 insertions, 219 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index aa85a98d3a4..65e3e270837 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -187,6 +187,15 @@ config ATA_PIIX
If unsure, say N.
+config SATA_DWC
+ tristate "DesignWare Cores SATA support"
+ depends on 460EX
+ help
+ This option enables support for the on-chip SATA controller of the
+ AppliedMicro processor 460EX.
+
+ If unsure, say N.
+
config SATA_MV
tristate "Marvell SATA support"
help
@@ -642,6 +651,17 @@ config PATA_VIA
If unsure, say N.
+config PATA_PXA
+ tristate "PXA DMA-capable PATA support"
+ depends on ARCH_PXA
+ help
+ This option enables support for harddrive attached to PXA CPU's bus.
+
+ NOTE: This driver utilizes PXA DMA controller, in case your hardware
+ is not capable of doing MWDMA, use pata_platform instead.
+
+ If unsure, say N.
+
config PATA_WINBOND
tristate "Winbond SL82C105 PATA support"
depends on PCI
@@ -796,6 +816,15 @@ config PATA_RZ1000
If unsure, say N.
+config PATA_SAMSUNG_CF
+ tristate "Samsung SoC PATA support"
+ depends on SAMSUNG_DEV_IDE
+ help
+ This option enables basic support for Samsung's S3C/S5P board
+ PATA controllers via the new ATA layer
+
+ If unsure, say N.
+
config PATA_WINBOND_VLB
tristate "Winbond W83759A VLB PATA support (Experimental)"
depends on ISA && EXPERIMENTAL
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 7ef89d73df6..158eaa961b1 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
obj-$(CONFIG_SATA_FSL) += sata_fsl.o
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
+obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
# SFF w/ custom DMA
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
@@ -87,8 +88,11 @@ obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
+obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o
obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
+obj-$(CONFIG_PATA_PXA) += pata_pxa.o
+
# Should be last but two libata driver
obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
# Should be last but one libata driver
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index f2522534ae6..fe75d8befc3 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1042,7 +1042,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
VPRINTK("ENTER\n");
- WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+ WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 5e11b160f24..4e97f33cca4 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -54,19 +54,13 @@ static int __init ahci_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (pdata && pdata->init) {
- rc = pdata->init(dev);
- if (rc)
- return rc;
- }
-
if (pdata && pdata->ata_port_info)
pi = *pdata->ata_port_info;
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv) {
- rc = -ENOMEM;
- goto err0;
+ dev_err(dev, "can't alloc ahci_host_priv\n");
+ return -ENOMEM;
}
hpriv->flags |= (unsigned long)pi.private_data;
@@ -74,8 +68,19 @@ static int __init ahci_probe(struct platform_device *pdev)
hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
if (!hpriv->mmio) {
dev_err(dev, "can't map %pR\n", mem);
- rc = -ENOMEM;
- goto err0;
+ return -ENOMEM;
+ }
+
+ /*
+ * Some platforms might need to prepare for mmio region access,
+ * which could be done in the following init call. So, the mmio
+ * region shouldn't be accessed before init (if provided) has
+ * returned successfully.
+ */
+ if (pdata && pdata->init) {
+ rc = pdata->init(dev, hpriv->mmio);
+ if (rc)
+ return rc;
}
ahci_save_initial_config(dev, hpriv,
@@ -166,7 +171,6 @@ static int __devexit ahci_remove(struct platform_device *pdev)
}
static struct platform_driver ahci_driver = {
- .probe = ahci_probe,
.remove = __devexit_p(ahci_remove),
.driver = {
.name = "ahci",
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 7107a6929de..cc5f7726bde 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -54,7 +54,6 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
const struct pci_device_id *id = ap->host->private_data;
int dma_enabled = 0;
struct ata_device *dev;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (id->driver_data & ATA_GEN_FORCE_DMA) {
dma_enabled = 0xff;
@@ -63,9 +62,6 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
- if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
- dma_enabled = 0xFF;
-
ata_for_each_dev(dev, link, ENABLED) {
/* We don't really care */
dev->pio_mode = XFER_PIO_0;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 7409f98d2ae..3971bc0a483 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -158,6 +158,7 @@ struct piix_map_db {
struct piix_host_priv {
const int *map;
u32 saved_iocfg;
+ spinlock_t sidpr_lock; /* FIXME: remove once locking in EH is fixed */
void __iomem *sidpr;
};
@@ -951,12 +952,15 @@ static int piix_sidpr_scr_read(struct ata_link *link,
unsigned int reg, u32 *val)
{
struct piix_host_priv *hpriv = link->ap->host->private_data;
+ unsigned long flags;
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
+ spin_lock_irqsave(&hpriv->sidpr_lock, flags);
piix_sidpr_sel(link, reg);
*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
+ spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
return 0;
}
@@ -964,12 +968,15 @@ static int piix_sidpr_scr_write(struct ata_link *link,
unsigned int reg, u32 val)
{
struct piix_host_priv *hpriv = link->ap->host->private_data;
+ unsigned long flags;
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
+ spin_lock_irqsave(&hpriv->sidpr_lock, flags);
piix_sidpr_sel(link, reg);
iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
+ spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
return 0;
}
@@ -1566,6 +1573,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
+ spin_lock_init(&hpriv->sidpr_lock);
/* Save IOCFG, this will be used for cable detection, quirk
* detection and restoration on detach. This is necessary
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ddf8e486278..7ef7c4f216f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -98,8 +98,6 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
unsigned int ata_print_id = 1;
-struct workqueue_struct *ata_aux_wq;
-
struct ata_force_param {
const char *name;
unsigned int cbl;
@@ -4167,15 +4165,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA },
{ "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA },
{ "CRD-8400B", NULL, ATA_HORKAGE_NODMA },
- { "CRD-8480B", NULL, ATA_HORKAGE_NODMA },
- { "CRD-8482B", NULL, ATA_HORKAGE_NODMA },
+ { "CRD-848[02]B", NULL, ATA_HORKAGE_NODMA },
{ "CRD-84", NULL, ATA_HORKAGE_NODMA },
{ "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA },
{ "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA },
{ "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA },
{ "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA },
- { "HITACHI CDR-8335", NULL, ATA_HORKAGE_NODMA },
- { "HITACHI CDR-8435", NULL, ATA_HORKAGE_NODMA },
+ { "HITACHI CDR-8[34]35",NULL, ATA_HORKAGE_NODMA },
{ "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA },
{ "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA },
{ "CD-532E-A", NULL, ATA_HORKAGE_NODMA },
@@ -4211,70 +4207,16 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "OCZ CORE_SSD", "02.10104", ATA_HORKAGE_NONCQ },
/* Seagate NCQ + FLUSH CACHE firmware bug */
- { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31500341AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31500341AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31500341AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31500341AS", "SD19", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
-
- { "ST31000333AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31000333AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31000333AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31000333AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST31000333AS", "SD19", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
-
- { "ST3640623AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640623AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640623AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640623AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640623AS", "SD19", ATA_HORKAGE_NONCQ |
+ { "ST31500341AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640323AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640323AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640323AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640323AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3640323AS", "SD19", ATA_HORKAGE_NONCQ |
+ { "ST31000333AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320813AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320813AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320813AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320813AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320813AS", "SD19", ATA_HORKAGE_NONCQ |
+ { "ST3640[36]23AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320613AS", "SD15", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320613AS", "SD16", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320613AS", "SD17", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320613AS", "SD18", ATA_HORKAGE_NONCQ |
- ATA_HORKAGE_FIRMWARE_WARN },
- { "ST3320613AS", "SD19", ATA_HORKAGE_NONCQ |
+ { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
/* Blacklist entries taken from Silicon Image 3124/3132
@@ -4303,12 +4245,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices which get the IVB wrong */
{ "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
/* Maybe we should just blacklist TSSTcorp... */
- { "TSSTcorp CDDVDW SH-S202H", "SB00", ATA_HORKAGE_IVB, },
- { "TSSTcorp CDDVDW SH-S202H", "SB01", ATA_HORKAGE_IVB, },
- { "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, },
- { "TSSTcorp CDDVDW SH-S202J", "SB01", ATA_HORKAGE_IVB, },
- { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, },
- { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202[HJN]", "SB0[01]", ATA_HORKAGE_IVB, },
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
@@ -4326,29 +4263,73 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ }
};
-static int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
+/**
+ * glob_match - match a text string against a glob-style pattern
+ * @text: the string to be examined
+ * @pattern: the glob-style pattern to be matched against
+ *
+ * Either/both of text and pattern can be empty strings.
+ *
+ * Match text against a glob-style pattern, with wildcards and simple sets:
+ *
+ * ? matches any single character.
+ * * matches any run of characters.
+ * [xyz] matches a single character from the set: x, y, or z.
+ * [a-d] matches a single character from the range: a, b, c, or d.
+ * [a-d0-9] matches a single character from either range.
+ *
+ * The special characters ?, [, -, or *, can be matched using a set, eg. [*]
+ * Behaviour with malformed patterns is undefined, though generally reasonable.
+ *
+ * Sample patterns: "SD1?", "SD1[0-5]", "*R0", "SD*1?[012]*xx"
+ *
+ * This function uses one level of recursion per '*' in pattern.
+ * Since it calls _nothing_ else, and has _no_ explicit local variables,
+ * this will not cause stack problems for any reasonable use here.
+ *
+ * RETURNS:
+ * 0 on match, 1 otherwise.
+ */
+static int glob_match (const char *text, const char *pattern)
{
- const char *p;
- int len;
-
- /*
- * check for trailing wildcard: *\0
- */
- p = strchr(patt, wildchar);
- if (p && ((*(p + 1)) == 0))
- len = p - patt;
- else {
- len = strlen(name);
- if (!len) {
- if (!*patt)
- return 0;
- return -1;
+ do {
+ /* Match single character or a '?' wildcard */
+ if (*text == *pattern || *pattern == '?') {
+ if (!*pattern++)
+ return 0; /* End of both strings: match */
+ } else {
+ /* Match single char against a '[' bracketed ']' pattern set */
+ if (!*text || *pattern != '[')
+ break; /* Not a pattern set */
+ while (*++pattern && *pattern != ']' && *text != *pattern) {
+ if (*pattern == '-' && *(pattern - 1) != '[')
+ if (*text > *(pattern - 1) && *text < *(pattern + 1)) {
+ ++pattern;
+ break;
+ }
+ }
+ if (!*pattern || *pattern == ']')
+ return 1; /* No match */
+ while (*pattern && *pattern++ != ']');
+ }
+ } while (*++text && *pattern);
+
+ /* Match any run of chars against a '*' wildcard */
+ if (*pattern == '*') {
+ if (!*++pattern)
+ return 0; /* Match: avoid recursion at end of pattern */
+ /* Loop to handle additional pattern chars after the wildcard */
+ while (*text) {
+ if (glob_match(text, pattern) == 0)
+ return 0; /* Remainder matched */
+ ++text; /* Absorb (match) this char and try again */
}
}
-
- return strncmp(patt, name, len);
+ if (!*text && !*pattern)
+ return 0; /* End of both strings: match */
+ return 1; /* No match */
}
-
+
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -4359,10 +4340,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
while (ad->model_num) {
- if (!strn_pattern_cmp(ad->model_num, model_num, '*')) {
+ if (!glob_match(model_num, ad->model_num)) {
if (ad->model_rev == NULL)
return ad->horkage;
- if (!strn_pattern_cmp(ad->model_rev, model_rev, '*'))
+ if (!glob_match(model_rev, ad->model_rev))
return ad->horkage;
}
ad++;
@@ -5611,6 +5592,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
#endif
+ mutex_init(&ap->scsi_scan_mutex);
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_LIST_HEAD(&ap->eh_done_q);
@@ -6549,29 +6531,20 @@ static int __init ata_init(void)
ata_parse_force_param();
- ata_aux_wq = create_singlethread_workqueue("ata_aux");
- if (!ata_aux_wq)
- goto fail;
-
rc = ata_sff_init();
- if (rc)
- goto fail;
+ if (rc) {
+ kfree(ata_force_tbl);
+ return rc;
+ }
printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
return 0;
-
-fail:
- kfree(ata_force_tbl);
- if (ata_aux_wq)
- destroy_workqueue(ata_aux_wq);
- return rc;
}
static void __exit ata_exit(void)
{
ata_sff_exit();
kfree(ata_force_tbl);
- destroy_workqueue(ata_aux_wq);
}
subsys_initcall(ata_init);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index f77a67303f8..c9ae299b834 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -727,7 +727,7 @@ void ata_scsi_error(struct Scsi_Host *host)
if (ap->pflags & ATA_PFLAG_LOADING)
ap->pflags &= ~ATA_PFLAG_LOADING;
else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
- queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0);
+ schedule_delayed_work(&ap->hotplug_task, 0);
if (ap->pflags & ATA_PFLAG_RECOVERED)
ata_port_printk(ap, KERN_INFO, "EH complete\n");
@@ -2214,6 +2214,7 @@ const char *ata_get_cmd_descript(u8 command)
{ ATA_CMD_SMART, "SMART" },
{ ATA_CMD_MEDIA_LOCK, "DOOR LOCK" },
{ ATA_CMD_MEDIA_UNLOCK, "DOOR UNLOCK" },
+ { ATA_CMD_DSM, "DATA SET MANAGEMENT" },
{ ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" },
{ ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" },
{ ATA_CMD_CFA_WRITE_NE, "CFA WRITE SECTORS WITHOUT ERASE" },
@@ -2944,7 +2945,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
ehc->i.flags |= ATA_EHI_SETMODE;
/* schedule the scsi_rescan_device() here */
- queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
+ schedule_work(&(ap->scsi_rescan_task));
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a54273d2c3c..a89172c100f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1111,10 +1111,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
*/
static int atapi_drain_needed(struct request *rq)
{
- if (likely(!blk_pc_request(rq)))
+ if (likely(rq->cmd_type != REQ_TYPE_BLOCK_PC))
return 0;
- if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW))
+ if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_WRITE))
return 0;
return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC;
@@ -3435,7 +3435,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
" switching to async\n");
}
- queue_delayed_work(ata_aux_wq, &ap->hotplug_task,
+ queue_delayed_work(system_long_wq, &ap->hotplug_task,
round_jiffies_relative(HZ));
}
@@ -3582,6 +3582,7 @@ void ata_scsi_hotplug(struct work_struct *work)
}
DPRINTK("ENTER\n");
+ mutex_lock(&ap->scsi_scan_mutex);
/* Unplug detached devices. We cannot use link iterator here
* because PMP links have to be scanned even if PMP is
@@ -3595,6 +3596,7 @@ void ata_scsi_hotplug(struct work_struct *work)
/* scan for new ones */
ata_scsi_scan_host(ap, 0);
+ mutex_unlock(&ap->scsi_scan_mutex);
DPRINTK("EXIT\n");
}
@@ -3673,9 +3675,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
* @work: Pointer to ATA port to perform scsi_rescan_device()
*
* After ATA pass thru (SAT) commands are executed successfully,
- * libata need to propagate the changes to SCSI layer. This
- * function must be executed from ata_aux_wq such that sdev
- * attach/detach don't race with rescan.
+ * libata need to propagate the changes to SCSI layer.
*
* LOCKING:
* Kernel thread context (may sleep).
@@ -3688,6 +3688,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
struct ata_device *dev;
unsigned long flags;
+ mutex_lock(&ap->scsi_scan_mutex);
spin_lock_irqsave(ap->lock, flags);
ata_for_each_link(link, ap, EDGE) {
@@ -3707,6 +3708,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
}
spin_unlock_irqrestore(ap->lock, flags);
+ mutex_unlock(&ap->scsi_scan_mutex);
}
/**
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index efa4a18cfb9..674c1436491 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -3318,14 +3318,7 @@ void ata_sff_port_init(struct ata_port *ap)
int __init ata_sff_init(void)
{
- /*
- * FIXME: In UP case, there is only one workqueue thread and if you
- * have more than one PIO device, latency is bloody awful, with
- * occasional multi-second "hiccups" as one PIO device waits for
- * another. It's an ugly wart that users DO occasionally complain
- * about; luckily most users have at most one PIO polled device.
- */
- ata_sff_wq = create_workqueue("ata_sff");
+ ata_sff_wq = alloc_workqueue("ata_sff", WQ_RESCUER, WQ_MAX_ACTIVE);
if (!ata_sff_wq)
return -ENOMEM;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 4b84ed60324..9ce1ecc63e3 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -54,7 +54,6 @@ enum {
};
extern unsigned int ata_print_id;
-extern struct workqueue_struct *ata_aux_wq;
extern int atapi_passthru16;
extern int libata_fua;
extern int libata_noacpi;
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index f087ab55b1d..8cc536e49a0 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev)
/* ======================================================================== */
static int __devinit
-mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
+mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)
{
unsigned int ipb_freq;
struct resource res_mem;
@@ -821,7 +821,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
}
static int
-mpc52xx_ata_remove(struct of_device *op)
+mpc52xx_ata_remove(struct platform_device *op)
{
struct mpc52xx_ata_priv *priv;
int task_irq;
@@ -848,7 +848,7 @@ mpc52xx_ata_remove(struct of_device *op)
#ifdef CONFIG_PM
static int
-mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
+mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state)
{
struct ata_host *host = dev_get_drvdata(&op->dev);
@@ -856,7 +856,7 @@ mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
}
static int
-mpc52xx_ata_resume(struct of_device *op)
+mpc52xx_ata_resume(struct platform_device *op)
{
struct ata_host *host = dev_get_drvdata(&op->dev);
struct mpc52xx_ata_priv *priv = host->private_data;
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 5a1b82c08be..480e043ce6b 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -14,7 +14,7 @@
#include <linux/of_platform.h>
#include <linux/ata_platform.h>
-static int __devinit pata_of_platform_probe(struct of_device *ofdev,
+static int __devinit pata_of_platform_probe(struct platform_device *ofdev,
const struct of_device_id *match)
{
int ret;
@@ -78,7 +78,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
reg_shift, pio_mask);
}
-static int __devexit pata_of_platform_remove(struct of_device *ofdev)
+static int __devexit pata_of_platform_remove(struct platform_device *ofdev)
{
return __pata_platform_remove(&ofdev->dev);
}
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 118c28e8aba..e944aa0c551 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -34,7 +34,6 @@
#include <linux/ata.h>
#include <linux/libata.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -201,23 +200,25 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- pdev->io.BasePort1 = io->win[0].base;
- pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (!(io->flags & CISTPL_IO_16BIT))
- pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+ pdev->resource[0]->start = io->win[0].base;
+ if (!(io->flags & CISTPL_IO_16BIT)) {
+ pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ }
if (io->nwin == 2) {
- pdev->io.NumPorts1 = 8;
- pdev->io.BasePort2 = io->win[1].base;
- pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
- if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ pdev->resource[0]->end = 8;
+ pdev->resource[1]->start = io->win[1].base;
+ pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
+ if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
- stk->ctl_base = pdev->io.BasePort2;
+ stk->ctl_base = pdev->resource[1]->start;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- pdev->io.NumPorts1 = io->win[0].len;
- pdev->io.NumPorts2 = 0;
- if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ pdev->resource[0]->end = io->win[0].len;
+ pdev->resource[1]->end = 0;
+ if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
- stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+ stk->ctl_base = pdev->resource[0]->start + 0x0e;
} else
return -ENODEV;
/* If we've got this far, we're done */
@@ -246,9 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
struct ata_port_operations *ops = &pcmcia_port_ops;
/* Set up attributes in order to probe card and get resources */
- pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
- pdev->io.IOAddrLines = 3;
+ pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+ pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
pdev->conf.Attributes = CONF_ENABLE_IRQ;
pdev->conf.IntType = INT_MEMORY_AND_IO;
@@ -271,7 +271,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
goto failed; /* No suitable config found */
}
- io_base = pdev->io.BasePort1;
+ io_base = pdev->resource[0]->start;
ctl_base = stk->ctl_base;
if (!pdev->irq)
goto failed;
@@ -294,7 +294,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
/* FIXME: Could be more ports at base + 0x10 but we only deal with
one right now */
- if (pdev->io.NumPorts1 >= 0x20)
+ if (resource_size(pdev->resource[0]) >= 0x20)
n_ports = 2;
if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
new file mode 100644
index 00000000000..1898c6ed4b4
--- /dev/null
+++ b/drivers/ata/pata_pxa.c
@@ -0,0 +1,411 @@
+/*
+ * Generic PXA PATA driver
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/ata.h>
+#include <linux/libata.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/completion.h>
+
+#include <scsi/scsi_host.h>
+
+#include <mach/pxa2xx-regs.h>
+#include <mach/pata_pxa.h>
+#include <mach/dma.h>
+
+#define DRV_NAME "pata_pxa"
+#define DRV_VERSION "0.1"
+
+struct pata_pxa_data {
+ uint32_t dma_channel;
+ struct pxa_dma_desc *dma_desc;
+ dma_addr_t dma_desc_addr;
+ uint32_t dma_desc_id;
+
+ /* DMA IO physical address */
+ uint32_t dma_io_addr;
+ /* PXA DREQ<0:2> pin selector */
+ uint32_t dma_dreq;
+ /* DMA DCSR register value */
+ uint32_t dma_dcsr;
+
+ struct completion dma_done;
+};
+
+/*
+ * Setup the DMA descriptors. The size is transfer capped at 4k per descriptor,
+ * if the transfer is longer, it is split into multiple chained descriptors.
+ */
+static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc)
+{
+ struct pata_pxa_data *pd = qc->ap->private_data;
+
+ uint32_t cpu_len, seg_len;
+ dma_addr_t cpu_addr;
+
+ cpu_addr = sg_dma_address(sg);
+ cpu_len = sg_dma_len(sg);
+
+ do {
+ seg_len = (cpu_len > 0x1000) ? 0x1000 : cpu_len;
+<