aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-10-09 02:06:48 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:47 -0400
commitb06ce3e51e3df4394a584c234f11240b1c6f8d5b (patch)
tree6a6f5a1cccdc2972b236d376afeba4fd296d5400 /drivers/ata/ahci.c
parentafaa5c373d2c49ee4865847031b82f1377f609d0 (diff)
libata: use ata_exec_internal() for PMP register access
PMP registers used to be accessed with dedicated accessors ->pmp_read and ->pmp_write. During reset, those callbacks are called with the port frozen so they should be able to run without depending on interrupt delivery. To achieve this, they were implemented polling. However, as resetting the host port makes the PMP to isolate fan-out ports until SError.X is cleared, resetting fan-out ports while port is frozen doesn't buy much additional safety. This patch updates libata PMP support such that PMP registers are accessed using regular ata_exec_internal() mechanism and kills ->pmp_read/write() callbacks. The following changes are made. * PMP access helpers - sata_pmp_read_init_tf(), sata_pmp_read_val(), sata_pmp_write_init_tf() are folded into sata_pmp_read/write() which are now standalone PMP register access functions. * sata_pmp_read/write() returns err_mask instead of rc. This is consistent with other functions which issue internal commands and allows more detailed error reporting. * ahci interrupt handler is modified to ignore BAD_PMP and spurious/illegal completion IRQs while reset is in progress. These conditions are expected during reset. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c48
1 files changed, 12 insertions, 36 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index abfb72aae3de..10bc3f64c453 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -239,8 +239,6 @@ static void ahci_freeze(struct ata_port *ap);
239static void ahci_thaw(struct ata_port *ap); 239static void ahci_thaw(struct ata_port *ap);
240static void ahci_pmp_attach(struct ata_port *ap); 240static void ahci_pmp_attach(struct ata_port *ap);
241static void ahci_pmp_detach(struct ata_port *ap); 241static void ahci_pmp_detach(struct ata_port *ap);
242static int ahci_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val);
243static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val);
244static void ahci_error_handler(struct ata_port *ap); 242static void ahci_error_handler(struct ata_port *ap);
245static void ahci_vt8251_error_handler(struct ata_port *ap); 243static void ahci_vt8251_error_handler(struct ata_port *ap);
246static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); 244static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
@@ -297,8 +295,6 @@ static const struct ata_port_operations ahci_ops = {
297 295
298 .pmp_attach = ahci_pmp_attach, 296 .pmp_attach = ahci_pmp_attach,
299 .pmp_detach = ahci_pmp_detach, 297 .pmp_detach = ahci_pmp_detach,
300 .pmp_read = ahci_pmp_read,
301 .pmp_write = ahci_pmp_write,
302 298
303#ifdef CONFIG_PM 299#ifdef CONFIG_PM
304 .port_suspend = ahci_port_suspend, 300 .port_suspend = ahci_port_suspend,
@@ -333,8 +329,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
333 329
334 .pmp_attach = ahci_pmp_attach, 330 .pmp_attach = ahci_pmp_attach,
335 .pmp_detach = ahci_pmp_detach, 331 .pmp_detach = ahci_pmp_detach,
336 .pmp_read = ahci_pmp_read,
337 .pmp_write = ahci_pmp_write,
338 332
339#ifdef CONFIG_PM 333#ifdef CONFIG_PM
340 .port_suspend = ahci_port_suspend, 334 .port_suspend = ahci_port_suspend,
@@ -1421,12 +1415,17 @@ static void ahci_port_intr(struct ata_port *ap)
1421 struct ata_eh_info *ehi = &ap->link.eh_info; 1415 struct ata_eh_info *ehi = &ap->link.eh_info;
1422 struct ahci_port_priv *pp = ap->private_data; 1416 struct ahci_port_priv *pp = ap->private_data;
1423 struct ahci_host_priv *hpriv = ap->host->private_data; 1417 struct ahci_host_priv *hpriv = ap->host->private_data;
1418 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
1424 u32 status, qc_active; 1419 u32 status, qc_active;
1425 int rc, known_irq = 0; 1420 int rc, known_irq = 0;
1426 1421
1427 status = readl(port_mmio + PORT_IRQ_STAT); 1422 status = readl(port_mmio + PORT_IRQ_STAT);
1428 writel(status, port_mmio + PORT_IRQ_STAT); 1423 writel(status, port_mmio + PORT_IRQ_STAT);
1429 1424
1425 /* ignore BAD_PMP while resetting */
1426 if (unlikely(resetting))
1427 status &= ~PORT_IRQ_BAD_PMP;
1428
1430 if (unlikely(status & PORT_IRQ_ERROR)) { 1429 if (unlikely(status & PORT_IRQ_ERROR)) {
1431 ahci_error_intr(ap, status); 1430 ahci_error_intr(ap, status);
1432 return; 1431 return;
@@ -1464,6 +1463,13 @@ static void ahci_port_intr(struct ata_port *ap)
1464 qc_active = readl(port_mmio + PORT_CMD_ISSUE); 1463 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
1465 1464
1466 rc = ata_qc_complete_multiple(ap, qc_active, NULL); 1465 rc = ata_qc_complete_multiple(ap, qc_active, NULL);
1466
1467 /* If resetting, spurious or invalid completions are expected,
1468 * return unconditionally.
1469 */
1470 if (resetting)
1471 return;
1472
1467 if (rc > 0) 1473 if (rc > 0)
1468 return; 1474 return;
1469 if (rc < 0) { 1475 if (rc < 0) {
@@ -1701,36 +1707,6 @@ static void ahci_pmp_detach(struct ata_port *ap)
1701 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); 1707 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1702} 1708}
1703 1709
1704static int ahci_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val)
1705{
1706 struct ata_port *ap = dev->link->ap;
1707 struct ata_taskfile tf;
1708 int rc;
1709
1710 ahci_kick_engine(ap, 0);
1711
1712 sata_pmp_read_init_tf(&tf, dev, pmp, reg);
1713 rc = ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
1714 SATA_PMP_SCR_TIMEOUT);
1715 if (rc == 0) {
1716 ahci_tf_read(ap, &tf);
1717 *r_val = sata_pmp_read_val(&tf);
1718 }
1719 return rc;
1720}
1721
1722static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val)
1723{
1724 struct ata_port *ap = dev->link->ap;
1725 struct ata_taskfile tf;
1726
1727 ahci_kick_engine(ap, 0);
1728
1729 sata_pmp_write_init_tf(&tf, dev, pmp, reg, val);
1730 return ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
1731 SATA_PMP_SCR_TIMEOUT);
1732}
1733
1734static int ahci_port_resume(struct ata_port *ap) 1710static int ahci_port_resume(struct ata_port *ap)
1735{ 1711{
1736 ahci_power_up(ap); 1712 ahci_power_up(ap);