Commit 487350e4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: Don't fail device revalidation for bad _GTF methods
  libata: port and host should be stopped before hardware resources are released
  libata: skip 0xff polling for PATA controllers
  libata: pata_platform: Support polling-mode configuration.
  libata: Support PIO polling-only hosts.
  libata sata_qstor conversion to new error handling (EH).
  libata sata_qstor workaround for spurious interrupts
  libata sata_qstor nuke idle state
  nv_hardreset: update dangling reference to bugzilla entry
  ata_piix: add SATELLITE PRO U200 to broken suspend list
parents 1da63a21 037f6bb7
...@@ -959,6 +959,13 @@ static int piix_broken_suspend(void) ...@@ -959,6 +959,13 @@ static int piix_broken_suspend(void)
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"), DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"),
}, },
}, },
{
.ident = "Satellite Pro U200",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"),
},
},
{ {
.ident = "Satellite U205", .ident = "Satellite U205",
.matches = { .matches = {
......
...@@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); ...@@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm);
* *
* RETURNS: * RETURNS:
* Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
* contain valid data. -errno on other errors. * contain valid data.
*/ */
static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
void **ptr_to_free) void **ptr_to_free)
...@@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ...@@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
"_GTF evaluation failed (AE 0x%x)\n", "_GTF evaluation failed (AE 0x%x)\n",
status); status);
rc = -EIO;
} }
goto out_free; goto out_free;
} }
...@@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ...@@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
"_GTF unexpected object type 0x%x\n", "_GTF unexpected object type 0x%x\n",
out_obj->type); out_obj->type);
rc = -EINVAL;
goto out_free; goto out_free;
} }
...@@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ...@@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
"unexpected _GTF length (%d)\n", "unexpected _GTF length (%d)\n",
out_obj->buffer.length); out_obj->buffer.length);
rc = -EINVAL;
goto out_free; goto out_free;
} }
...@@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) ...@@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev)
int gtf_count, i, rc; int gtf_count, i, rc;
/* get taskfiles */ /* get taskfiles */
rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free); gtf_count = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
if (rc < 0)
return rc;
gtf_count = rc;
/* execute them */ /* execute them */
for (i = 0, rc = 0; i < gtf_count; i++) { for (i = 0, rc = 0; i < gtf_count; i++) {
......
...@@ -3373,14 +3373,20 @@ void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) ...@@ -3373,14 +3373,20 @@ void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
* to clear 0xff after reset. For example, HHD424020F7SV00 * to clear 0xff after reset. For example, HHD424020F7SV00
* iVDR needs >= 800ms while. Quantum GoVault needs even more * iVDR needs >= 800ms while. Quantum GoVault needs even more
* than that. * than that.
*
* Note that some PATA controllers (pata_ali) explode if
* status register is read more than once when there's no
* device attached.
*/ */
while (1) { if (ap->flags & ATA_FLAG_SATA) {
u8 status = ata_chk_status(ap); while (1) {
u8 status = ata_chk_status(ap);
if (status != 0xff || time_after(jiffies, deadline)) if (status != 0xff || time_after(jiffies, deadline))
return; return;
msleep(50); msleep(50);
}
} }
} }
...@@ -6815,19 +6821,6 @@ static void ata_host_release(struct device *gendev, void *res) ...@@ -6815,19 +6821,6 @@ static void ata_host_release(struct device *gendev, void *res)
struct ata_host *host = dev_get_drvdata(gendev); struct ata_host *host = dev_get_drvdata(gendev);
int i; int i;
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
if (!ap)
continue;
if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
ap->ops->port_stop(ap);
}
if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
host->ops->host_stop(host);
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];
...@@ -6960,6 +6953,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, ...@@ -6960,6 +6953,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
return host; return host;
} }
static void ata_host_stop(struct device *gendev, void *res)
{
struct ata_host *host = dev_get_drvdata(gendev);
int i;
WARN_ON(!(host->flags & ATA_HOST_STARTED));
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
if (ap->ops->port_stop)
ap->ops->port_stop(ap);
}
if (host->ops->host_stop)
host->ops->host_stop(host);
}
/** /**
* ata_host_start - start and freeze ports of an ATA host * ata_host_start - start and freeze ports of an ATA host
* @host: ATA host to start ports for * @host: ATA host to start ports for
...@@ -6978,6 +6989,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, ...@@ -6978,6 +6989,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
*/ */
int ata_host_start(struct ata_host *host) int ata_host_start(struct ata_host *host)
{ {
int have_stop = 0;
void *start_dr = NULL;
int i, rc; int i, rc;
if (host->flags & ATA_HOST_STARTED) if (host->flags & ATA_HOST_STARTED)
...@@ -6989,6 +7002,22 @@ int ata_host_start(struct ata_host *host) ...@@ -6989,6 +7002,22 @@ int ata_host_start(struct ata_host *host)
if (!host->ops && !ata_port_is_dummy(ap)) if (!host->ops && !ata_port_is_dummy(ap))
host->ops = ap->ops; host->ops = ap->ops;
if (ap->ops->port_stop)
have_stop = 1;
}
if (host->ops->host_stop)
have_stop = 1;
if (have_stop) {
start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL);
if (!start_dr)
return -ENOMEM;
}
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
if (ap->ops->port_start) { if (ap->ops->port_start) {
rc = ap->ops->port_start(ap); rc = ap->ops->port_start(ap);
if (rc) { if (rc) {
...@@ -7001,6 +7030,8 @@ int ata_host_start(struct ata_host *host) ...@@ -7001,6 +7030,8 @@ int ata_host_start(struct ata_host *host)
ata_eh_freeze_port(ap); ata_eh_freeze_port(ap);
} }
if (start_dr)
devres_add(host->dev, start_dr);
host->flags |= ATA_HOST_STARTED; host->flags |= ATA_HOST_STARTED;
return 0; return 0;
...@@ -7011,6 +7042,7 @@ int ata_host_start(struct ata_host *host) ...@@ -7011,6 +7042,7 @@ int ata_host_start(struct ata_host *host)
if (ap->ops->port_stop) if (ap->ops->port_stop)
ap->ops->port_stop(ap); ap->ops->port_stop(ap);
} }
devres_free(start_dr);
return rc; return rc;
} }
...@@ -7178,6 +7210,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ...@@ -7178,6 +7210,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
* request IRQ and register it. This helper takes necessasry * request IRQ and register it. This helper takes necessasry
* arguments and performs the three steps in one go. * arguments and performs the three steps in one go.
* *
* An invalid IRQ skips the IRQ registration and expects the host to
* have set polling mode on the port. In this case, @irq_handler
* should be NULL.
*
* LOCKING: * LOCKING:
* Inherited from calling layer (may sleep). * Inherited from calling layer (may sleep).
* *
...@@ -7194,6 +7230,12 @@ int ata_host_activate(struct ata_host *host, int irq, ...@@ -7194,6 +7230,12 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc) if (rc)
return rc; return rc;
/* Special case for polling mode */
if (!irq) {
WARN_ON(irq_handler);
return ata_host_register(host, sht);
}
rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags, rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags,
dev_driver_string(host->dev), host); dev_driver_string(host->dev), host);
if (rc) if (rc)
......
/* /*
* Generic platform device PATA driver * Generic platform device PATA driver
* *
* Copyright (C) 2006 Paul Mundt * Copyright (C) 2006 - 2007 Paul Mundt
* *
* Based on pata_pcmcia: * Based on pata_pcmcia:
* *
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/pata_platform.h> #include <linux/pata_platform.h>
#define DRV_NAME "pata_platform" #define DRV_NAME "pata_platform"
#define DRV_VERSION "1.1" #define DRV_VERSION "1.2"
static int pio_mask = 1; static int pio_mask = 1;
...@@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, ...@@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
* Register a platform bus IDE interface. Such interfaces are PIO and we * Register a platform bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing. * assume do not support IRQ sharing.
* *
* Platform devices are expected to contain 3 resources per port: * Platform devices are expected to contain at least 2 resources per port:
* *
* - I/O Base (IORESOURCE_IO or IORESOURCE_MEM) * - I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
* - CTL Base (IORESOURCE_IO or IORESOURCE_MEM) * - CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
*
* and optionally:
*
* - IRQ (IORESOURCE_IRQ) * - IRQ (IORESOURCE_IRQ)
* *
* If the base resources are both mem types, the ioremap() is handled * If the base resources are both mem types, the ioremap() is handled
* here. For IORESOURCE_IO, it's assumed that there's no remapping * here. For IORESOURCE_IO, it's assumed that there's no remapping
* necessary. * necessary.
*
* If no IRQ resource is present, PIO polling mode is used instead.
*/ */
static int __devinit pata_platform_probe(struct platform_device *pdev) static int __devinit pata_platform_probe(struct platform_device *pdev)
{ {
...@@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ...@@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
struct ata_port *ap; struct ata_port *ap;
struct pata_platform_info *pp_info; struct pata_platform_info *pp_info;
unsigned int mmio; unsigned int mmio;
int irq;
/* /*
* Simple resource validation .. * Simple resource validation ..
*/ */
if (unlikely(pdev->num_resources != 3)) { if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
dev_err(&pdev->dev, "invalid number of resources\n"); dev_err(&pdev->dev, "invalid number of resources\n");
return -EINVAL; return -EINVAL;
} }
...@@ -172,6 +178,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ...@@ -172,6 +178,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
mmio = (( io_res->flags == IORESOURCE_MEM) && mmio = (( io_res->flags == IORESOURCE_MEM) &&
(ctl_res->flags == IORESOURCE_MEM)); (ctl_res->flags == IORESOURCE_MEM));
/*
* And the IRQ
*/
irq = platform_get_irq(pdev, 0);
if (irq < 0)
irq = 0; /* no irq */
/* /*
* Now that that's out of the way, wire up the port.. * Now that that's out of the way, wire up the port..
*/ */
...@@ -184,6 +197,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ...@@ -184,6 +197,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->pio_mask = pio_mask; ap->pio_mask = pio_mask;
ap->flags |= ATA_FLAG_SLAVE_POSS; ap->flags |= ATA_FLAG_SLAVE_POSS;
/*
* Use polling mode if there's no IRQ
*/
if (!irq) {
ap->flags |= ATA_FLAG_PIO_POLLING;
ata_port_desc(ap, "no IRQ, using PIO polling");
}
/* /*
* Handle the MMIO case * Handle the MMIO case
*/ */
...@@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ...@@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
(unsigned long long)ctl_res->start); (unsigned long long)ctl_res->start);
/* activate */ /* activate */
return ata_host_activate(host, platform_get_irq(pdev, 0), return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
ata_interrupt, pp_info ? pp_info->irq_flags pp_info ? pp_info->irq_flags : 0,
: 0, &pata_platform_sht); &pata_platform_sht);
} }
/** /**
......
...@@ -1629,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class, ...@@ -1629,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
/* SATA hardreset fails to retrieve proper device signature on /* SATA hardreset fails to retrieve proper device signature on
* some controllers. Don't classify on hardreset. For more * some controllers. Don't classify on hardreset. For more
* info, see http://bugme.osdl.org/show_bug.cgi?id=3352 * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
*/ */
return sata_std_hardreset(link, &dummy, deadline); return sata_std_hardreset(link, &dummy, deadline);
} }
......
...@@ -103,7 +103,7 @@ enum { ...@@ -103,7 +103,7 @@ enum {
QS_DMA_BOUNDARY = ~0UL QS_DMA_BOUNDARY = ~0UL
}; };
typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t; typedef enum { qs_state_mmio, qs_state_pkt } qs_state_t;
struct qs_port_priv { struct qs_port_priv {
u8 *pkt; u8 *pkt;
...@@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); ...@@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int qs_port_start(struct ata_port *ap); static int qs_port_start(struct ata_port *ap);
static void qs_host_stop(struct ata_host *host); static void qs_host_stop(struct ata_host *host);
static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc); static void qs_qc_prep(struct ata_queued_cmd *qc);
static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
static void qs_bmdma_stop(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap); static u8 qs_bmdma_status(struct ata_port *ap);
static void qs_irq_clear(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap);
static void qs_eng_timeout(struct ata_port *ap); static void qs_freeze(struct ata_port *ap);
static void qs_thaw(struct ata_port *ap);
static void qs_error_handler(struct ata_port *ap);
static struct scsi_host_template qs_ata_sht = { static struct scsi_host_template qs_ata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
...@@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = { ...@@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = {
.check_atapi_dma = qs_check_atapi_dma, .check_atapi_dma = qs_check_atapi_dma,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = qs_phy_reset,
.qc_prep = qs_qc_prep, .qc_prep = qs_qc_prep,
.qc_issue = qs_qc_issue, .qc_issue = qs_qc_issue,
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.eng_timeout = qs_eng_timeout, .freeze = qs_freeze,
.thaw = qs_thaw,
.error_handler = qs_error_handler,
.irq_clear = qs_irq_clear, .irq_clear = qs_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.scr_read = qs_scr_read, .scr_read = qs_scr_read,
...@@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = { ...@@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = {
/* board_2068_idx */ /* board_2068_idx */
{ {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET |
//FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */ .pio_mask = 0x10, /* pio4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
...@@ -219,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap) ...@@ -219,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap)
static inline void qs_enter_reg_mode(struct ata_port *ap) static inline void qs_enter_reg_mode(struct ata_port *ap)
{ {
u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
struct qs_port_priv *pp = ap->private_data;
pp->state = qs_state_mmio;
writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
readb(chan + QS_CCT_CTR0); /* flush */ readb(chan + QS_CCT_CTR0); /* flush */
} }
...@@ -233,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap) ...@@ -233,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap)
qs_enter_reg_mode(ap); qs_enter_reg_mode(ap);
} }
static void qs_phy_reset(struct ata_port *ap) static void qs_freeze(struct ata_port *ap)
{ {
struct qs_port_priv *pp = ap->private_data; u8 __iomem *mmio_base = qs_mmio_base(ap->host);
pp->state = qs_state_idle; writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
qs_reset_channel_logic(ap); qs_enter_reg_mode(ap);
sata_phy_reset(ap);
} }
static void qs_eng_timeout(struct ata_port *ap) static void qs_thaw(struct ata_port *ap)
{ {
struct qs_port_priv *pp = ap->private_data; u8 __iomem *mmio_base = qs_mmio_base(ap->host);
qs_enter_reg_mode(ap);
writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
}
static int qs_prereset(struct ata_link *link, unsigned long deadline)
{
struct ata_port *ap = link->ap;
if (pp->state != qs_state_idle) /* healthy paranoia */
pp->state = qs_state_mmio;
qs_reset_channel_logic(ap); qs_reset_channel_logic(ap);
ata_eng_timeout(ap); return ata_std_prereset(link, deadline);
} }
static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
...@@ -260,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) ...@@ -260,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0; return 0;
} }
static void qs_error_handler(struct ata_port *ap)
{
qs_enter_reg_mode(ap);
ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL,
ata_std_postreset);
}
static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{ {
if (sc_reg > SCR_CONTROL) if (sc_reg > SCR_CONTROL)
...@@ -358,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) ...@@ -358,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
pp->state = qs_state_pkt; pp->state = qs_state_pkt;
qs_packet_start(qc); qs_packet_start(qc);
return 0; return 0;
...@@ -375,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) ...@@ -375,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc); return ata_qc_issue_prot(qc);
} }
static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status)
{
qc->err_mask |= ac_err_mask(status);
if (!qc->err_mask) {
ata_qc_complete(qc);
} else {
struct ata_port *ap = qc->ap;
struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "status 0x%02X", status);
if (qc->err_mask == AC_ERR_DEV)
ata_port_abort(ap);
else
ata_port_freeze(ap);
}
}
static inline unsigned int qs_intr_pkt(struct ata_host *host) static inline unsigned int qs_intr_pkt(struct ata_host *host)
{ {
unsigned int handled = 0; unsigned int handled = 0;
...@@ -406,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host) ...@@ -406,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host)
switch (sHST) { switch (sHST) {
case 0: /* successful CPB */ case 0: /* successful CPB */
case 3: /* device error */ case 3: /* device error */
pp->state = qs_state_idle;
qs_enter_reg_mode(qc->ap); qs_enter_reg_mode(qc->ap);
qc->err_mask |= ac_err_mask(sDST); qs_do_or_die(qc, sDST);
ata_qc_complete(qc);
break; break;
default: default:
break; break;
...@@ -431,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host) ...@@ -431,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
if (ap && if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data; struct qs_port_priv *pp;
if (!pp || pp->state != qs_state_mmio)
continue;
qc = ata_qc_from_tag(ap, ap->link.active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) {
/*
/* check main status, clearing INTRQ */ * The qstor hardware generates spurious
u8 status = ata_check_status(ap); * interrupts from time to time when switching
if ((status & ATA_BUSY)) * in and out of packet mode.
continue; * There's no obvious way to know if we're
DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", * here now due to that, so just ack the irq
ap->print_id, qc->tf.protocol, status); * and pretend we knew it was ours.. (ugh).
* This does not affect packet mode.
/* complete taskfile transaction */ */
pp->state = qs_state_idle; ata_check_status(ap);
qc->err_mask |= ac_err_mask(status);
ata_qc_complete(qc);
handled = 1; handled = 1;
continue;
} }
pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio)
continue;
if (!(qc->tf.flags & ATA_TFLAG_POLLING))
handled |= ata_host_intr(ap, qc);
} }
} }
return handled; return handled;
...@@ -459,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance) ...@@ -459,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance)
{ {
struct ata_host *host = dev_instance; struct ata_host *host = dev_instance;
unsigned int handled = 0; unsigned int handled = 0;
unsigned long flags;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
spin_lock(&host->lock); spin_lock_irqsave(&host->lock, flags);
handled = qs_intr_pkt(host) | qs_intr_mmio(host); handled = qs_intr_pkt(host) | qs_intr_mmio(host);
spin_unlock(&host->lock); spin_unlock_irqrestore(&host->lock, flags);
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
...@@ -501,7 +535,6 @@ static int qs_port_start(struct ata_port *ap) ...@@ -501,7 +535,6 @@ static int qs_port_start(struct ata_port *ap)
rc = ata_port_start(ap); rc = ata_port_start(ap);
if (rc) if (rc)
return rc; return rc;
qs_enter_reg_mode(ap);
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp) if (!pp)
return -ENOMEM; return -ENOMEM;
...@@ -512,6 +545,7 @@ static int qs_port_start(struct ata_port *ap) ...@@ -512,6 +545,7 @@ static int qs_port_start(struct ata_port *ap)
memset(pp->pkt, 0, QS_PKT_BYTES); memset(pp->pkt, 0, QS_PKT_BYTES);
ap->private_data = pp; ap->private_data = pp;
qs_enter_reg_mode(ap);
addr = (u64)pp->pkt_dma; addr = (u64)pp->pkt_dma;
writel((u32) addr, chan + QS_CCF_CPBA); writel((u32) addr, chan + QS_CCF_CPBA);
writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
......
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