From af64371ada9452632c349563d688d30d94e918ba Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 2 Apr 2006 20:41:36 -0400 Subject: [libata] bump versions --- drivers/scsi/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1bd82c4e52a0..0c5f0c844d21 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -48,7 +48,7 @@ #include #define DRV_NAME "ahci" -#define DRV_VERSION "1.2" +#define DRV_VERSION "1.3" enum { -- cgit v1.2.3 From c2a6585296009379e0f4eff39cdcb108b457ebf2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Apr 2006 01:58:06 +0900 Subject: [PATCH] ahci: do not fail softreset if PHY reports no device All softreset methods are responsible for detecting device presence and succeed softreset in such cases. AHCI didn't use to check for device presence before proceeding with softreset and this caused unnecessary reset retrials during probing. This patch adds presence detection to AHCI softreset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0c5f0c844d21..ff48066d4c4f 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -549,6 +549,12 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) DPRINTK("ENTER\n"); + if (!sata_dev_present(ap)) { + DPRINTK("PHY reports no device\n"); + *class = ATA_DEV_NONE; + return 0; + } + /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_stop_engine(ap); if (rc) { -- cgit v1.2.3 From 2bf2cb26b2512c6a609bb152982c388329bedff6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:16:45 +0900 Subject: [PATCH] libata: kill @verbose from ata_reset_fn_t @verbose was added to ata_reset_fn_t because AHCI complained during probing if no device was attached to the port. However, muting failure message isn't the correct approach. Reset methods are responsible for detecting no device condition and finishing successfully. Now that AHCI softreset is fixed, kill @verbose. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 13 +++++-------- drivers/scsi/libata-core.c | 36 ++++++++++++------------------------ drivers/scsi/libata.h | 6 ++---- drivers/scsi/sata_sil24.c | 8 +++----- include/linux/libata.h | 8 +++----- 5 files changed, 25 insertions(+), 46 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 20fc0846e0be..0e7fb9bf2cd1 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -534,7 +534,7 @@ static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, return -1; } -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp = ap->private_data; @@ -646,22 +646,19 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + printk(KERN_ERR "ata%u: softreset failed (%s)\n", + ap->id, reason); return rc; } -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); - rc = sata_std_hardreset(ap, verbose, class); + rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); if (rc == 0) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f37179623efa..92b5077ac052 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2387,7 +2387,6 @@ void ata_std_probeinit(struct ata_port *ap) /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset - * @verbose: fail verbosely * @classes: resulting classes of attached devices * * Reset host port using ATA SRST. This function is to be used @@ -2399,7 +2398,7 @@ void ata_std_probeinit(struct ata_port *ap) * RETURNS: * 0 on success, -errno otherwise. */ -int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +int ata_std_softreset(struct ata_port *ap, unsigned int *classes) { unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; unsigned int devmask = 0, err_mask; @@ -2425,12 +2424,8 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - if (verbose) - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); - else - DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n", - err_mask); + printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", + ap->id, err_mask); return -EIO; } @@ -2447,7 +2442,6 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) /** * sata_std_hardreset - reset host port via SATA phy reset * @ap: port to reset - * @verbose: fail verbosely * @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. @@ -2460,7 +2454,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) * RETURNS: * 0 on success, -errno otherwise. */ -int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { u32 scontrol; @@ -2500,11 +2494,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - if (verbose) - printk(KERN_ERR "ata%u: COMRESET failed " - "(device not ready)\n", ap->id); - else - DPRINTK("EXIT, device not ready\n"); + printk(KERN_ERR "ata%u: COMRESET failed " + "(device not ready)\n", ap->id); return -EIO; } @@ -2592,16 +2583,15 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, ata_postreset_fn_t postreset, - int verbose, unsigned int *classes) +int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes) { int i, rc; for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; - rc = reset(ap, verbose, classes); + rc = reset(ap, classes); if (rc) return rc; @@ -2645,8 +2635,6 @@ int ata_do_reset(struct ata_port *ap, * - If classification is supported, fill classes[] with * recognized class codes. * - If classification is not supported, leave classes[] alone. - * - If verbose is non-zero, print error message on failure; - * otherwise, shut up. * * LOCKING: * Kernel thread context (may sleep) @@ -2666,7 +2654,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, probeinit(ap); if (softreset && !ata_set_sata_spd_needed(ap)) { - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; printk(KERN_INFO "ata%u: softreset failed, will try " @@ -2678,7 +2666,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, goto done; while (1) { - rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + rc = ata_do_reset(ap, hardreset, postreset, classes); if (rc == 0) { if (classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2699,7 +2687,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ap->id); ssleep(5); - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); } done: diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index b18d377588dc..3f8b0a863781 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -56,10 +56,8 @@ extern int ata_set_sata_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); -extern int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, - ata_postreset_fn_t postreset, - int verbose, unsigned int *classes); +extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 9aa7493ea146..26d84e094b1d 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -426,8 +426,7 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } -static int sil24_softreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_softreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; @@ -489,13 +488,12 @@ static int sil24_softreset(struct ata_port *ap, int verbose, return 0; } -static int sil24_hardreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { unsigned int dummy_class; /* sil24 doesn't report device signature after hard reset */ - return sata_std_hardreset(ap, verbose, &dummy_class); + return sata_std_hardreset(ap, &dummy_class); } static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) diff --git a/include/linux/libata.h b/include/linux/libata.h index fe0a1dcc76c2..d5fd5c06e755 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -252,7 +252,7 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); typedef void (*ata_probeinit_fn_t)(struct ata_port *); -typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); +typedef int (*ata_reset_fn_t)(struct ata_port *, unsigned int *); typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); struct ata_ioports { @@ -509,10 +509,8 @@ extern int ata_drive_probe_reset(struct ata_port *ap, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_std_probeinit(struct ata_port *ap); -extern int ata_std_softreset(struct ata_port *ap, int verbose, - unsigned int *classes); -extern int sata_std_hardreset(struct ata_port *ap, int verbose, - unsigned int *class); +extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); +extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, int post_reset); -- cgit v1.2.3 From 75fe18069a55c78f553643b4e3a24c6864d71d87 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] ahci: use ata_wait_register() Replace ahci_poll_register() with ata_wait_register(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0e7fb9bf2cd1..1b8429cb3c96 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -516,24 +516,6 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) -{ - unsigned long timeout; - u32 tmp; - - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); - - return -1; -} - static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; @@ -543,6 +525,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; + u32 tmp; u8 *fis; int rc; @@ -564,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; - if (!(hpriv->cap & HOST_CAP_CLO)) { rc = -EIO; reason = "port busy but no CLO"; @@ -575,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_CLO; writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) { rc = -EIO; reason = "CLO failed"; goto fail_restart; @@ -599,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); + if (tmp & 0x1) { rc = -EIO; reason = "1st FIS failed"; goto fail; -- cgit v1.2.3 From bf2af2a2027e52b653882fbca840620e896ae081 Mon Sep 17 00:00:00 2001 From: Bastiaan Jacques Date: Mon, 17 Apr 2006 14:17:59 +0200 Subject: [PATCH] ahci: add support for VIA VT8251 Adds AHCI support for the VIA VT8251. Includes a workaround for a hardware bug which requires a Command List Override before softreset. Signed-off-by: Bastiaan Jacques Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 64 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1b8429cb3c96..d23f00230a76 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -73,6 +73,7 @@ enum { RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ board_ahci = 0, + board_ahci_vt8251 = 1, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -153,6 +154,9 @@ enum { /* hpriv->flags bits */ AHCI_FLAG_MSI = (1 << 0), + + /* ap->flags bits */ + AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), }; struct ahci_cmd_hdr { @@ -255,6 +259,16 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_vt8251 */ + { + .sht = &ahci_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + AHCI_FLAG_RESET_NEEDS_CLO, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -296,6 +310,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* ATI SB600 non-raid */ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 raid */ + { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci_vt8251 }, /* VIA VT8251 */ { } /* terminate list */ }; @@ -516,9 +532,29 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_softreset(struct ata_port *ap, unsigned int *class) +static int ahci_clo(struct ata_port *ap) { + void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; struct ahci_host_priv *hpriv = ap->host_set->private_data; + u32 tmp; + + if (!(hpriv->cap & HOST_CAP_CLO)) + return -EOPNOTSUPP; + + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_CLO; + writel(tmp, port_mmio + PORT_CMD); + + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) + return -EIO; + + return 0; +} + +static int ahci_softreset(struct ata_port *ap, unsigned int *class) +{ struct ahci_port_priv *pp = ap->private_data; void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); @@ -547,21 +583,13 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - if (!(hpriv->cap & HOST_CAP_CLO)) { - rc = -EIO; - reason = "port busy but no CLO"; - goto fail_restart; - } - - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_CLO; - writel(tmp, port_mmio + PORT_CMD); + rc = ahci_clo(ap); - tmp = ata_wait_register(port_mmio + PORT_CMD, - PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); - if (tmp & PORT_CMD_CLO) { - rc = -EIO; - reason = "CLO failed"; + if (rc == -EOPNOTSUPP) { + reason = "port busy but CLO unavailable"; + goto fail_restart; + } else if (rc) { + reason = "port busy but CLO failed"; goto fail_restart; } } @@ -672,6 +700,12 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) { + if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && + (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { + /* ATA_BUSY hasn't cleared, so send a CLO */ + ahci_clo(ap); + } + return ata_drive_probe_reset(ap, ata_std_probeinit, ahci_softreset, ahci_hardreset, ahci_postreset, classes); -- cgit v1.2.3 From e4fac92ae744cd5d5c3c1774825788e6b91a5965 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:25 +0900 Subject: [PATCH] ahci: hardreset classification fix AHCI calls ata_dev_classify() even when no device is attached which results in false class code. Fix it. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index d23f00230a76..c33255404ee5 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -670,7 +670,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); - if (rc == 0) + if (rc == 0 && sata_dev_present(ap)) *class = ahci_dev_classify(ap); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; -- cgit v1.2.3 From 81952c5497b40ae56835bd0d6537f8c6bdea07e7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:47 +0900 Subject: [PATCH] libata: use new SCR and on/offline functions Use new SCR and on/offline functions. Note that for LLDD which know it implements SCR callbacks, SCR functions are guaranteed to succeed and ata_port_online() == !ata_port_offline(). Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 6 +-- drivers/scsi/libata-core.c | 107 +++++++++++++++++++++++++-------------------- drivers/scsi/sata_mv.c | 16 ++++--- drivers/scsi/sata_sil24.c | 6 +-- 4 files changed, 75 insertions(+), 60 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c33255404ee5..c2298fb131d8 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -567,7 +567,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) DPRINTK("ENTER\n"); - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { DPRINTK("PHY reports no device\n"); *class = ATA_DEV_NONE; return 0; @@ -640,7 +640,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) msleep(150); *class = ATA_DEV_NONE; - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { rc = -EIO; reason = "device not ready"; @@ -670,7 +670,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); - if (rc == 0 && sata_dev_present(ap)) + if (rc == 0 && ata_port_online(ap)) *class = ahci_dev_classify(ap); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b9c5cbf0b786..56f0af208345 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1494,13 +1494,11 @@ static void sata_print_link_status(struct ata_port *ap) { u32 sstatus, scontrol, tmp; - if (!ap->ops->scr_read) + if (sata_scr_read(ap, SCR_STATUS, &sstatus)) return; + sata_scr_read(ap, SCR_CONTROL, &scontrol); - sstatus = scr_read(ap, SCR_STATUS); - scontrol = scr_read(ap, SCR_CONTROL); - - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { tmp = (sstatus >> 4) & 0xf; printk(KERN_INFO "ata%u: SATA link up %s (SStatus %X SControl %X)\n", @@ -1531,17 +1529,18 @@ void __sata_phy_reset(struct ata_port *ap) if (ap->flags & ATA_FLAG_SATA_RESET) { /* issue phy wake/reset */ - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); /* Couldn't find anything in SATA I/II specs, but * AHCI-1.1 10.4.2 says at least 1 ms. */ mdelay(1); } - scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */ + /* phy wake/clear reset */ + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); /* wait for phy to become ready, if necessary */ do { msleep(200); - sstatus = scr_read(ap, SCR_STATUS); + sata_scr_read(ap, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); @@ -1550,7 +1549,7 @@ void __sata_phy_reset(struct ata_port *ap) sata_print_link_status(ap); /* TODO: phy layer with polling, timeouts, etc. */ - if (sata_dev_present(ap)) + if (!ata_port_offline(ap)) ata_port_probe(ap); else ata_port_disable(ap); @@ -1638,11 +1637,12 @@ void ata_port_disable(struct ata_port *ap) */ int sata_down_spd_limit(struct ata_port *ap) { - u32 spd, mask; - int highbit; + u32 sstatus, spd, mask; + int rc, highbit; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) - return -EOPNOTSUPP; + rc = sata_scr_read(ap, SCR_STATUS, &sstatus); + if (rc) + return rc; mask = ap->sata_spd_limit; if (mask <= 1) @@ -1650,7 +1650,7 @@ int sata_down_spd_limit(struct ata_port *ap) highbit = fls(mask) - 1; mask &= ~(1 << highbit); - spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf; + spd = (sstatus >> 4) & 0xf; if (spd <= 1) return -EINVAL; spd--; @@ -1700,11 +1700,9 @@ int sata_set_spd_needed(struct ata_port *ap) { u32 scontrol; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + if (sata_scr_read(ap, SCR_CONTROL, &scontrol)) return 0; - scontrol = scr_read(ap, SCR_CONTROL); - return __sata_set_spd_needed(ap, &scontrol); } @@ -1719,20 +1717,22 @@ int sata_set_spd_needed(struct ata_port *ap) * * RETURNS: * 0 if spd doesn't need to be changed, 1 if spd has been - * changed. -EOPNOTSUPP if SCR registers are inaccessible. + * changed. Negative errno if SCR registers are inaccessible. */ int sata_set_spd(struct ata_port *ap) { u32 scontrol; + int rc; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) - return -EOPNOTSUPP; + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; - scontrol = scr_read(ap, SCR_CONTROL); if (!__sata_set_spd_needed(ap, &scontrol)) return 0; - scr_write(ap, SCR_CONTROL, scontrol); + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; + return 1; } @@ -2336,20 +2336,26 @@ static int sata_phy_resume(struct ata_port *ap) { unsigned long timeout = jiffies + (HZ * 5); u32 scontrol, sstatus; + int rc; + + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; - scontrol = scr_read(ap, SCR_CONTROL); scontrol = (scontrol & 0x0f0) | 0x300; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; /* Wait for phy to become ready, if necessary. */ do { msleep(200); - sstatus = scr_read(ap, SCR_STATUS); + if ((rc = sata_scr_read(ap, SCR_STATUS, &sstatus))) + return rc; if ((sstatus & 0xf) != 1) return 0; } while (time_before(jiffies, timeout)); - return -1; + return -EBUSY; } /** @@ -2367,21 +2373,20 @@ static int sata_phy_resume(struct ata_port *ap) */ void ata_std_probeinit(struct ata_port *ap) { - if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { - u32 spd; - - /* resume link */ - sata_phy_resume(ap); + u32 scontrol; - /* init sata_spd_limit to the current value */ - spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; - if (spd) - ap->sata_spd_limit &= (1 << spd) - 1; + /* resume link */ + sata_phy_resume(ap); - /* wait for device */ - if (sata_dev_present(ap)) - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + /* init sata_spd_limit to the current value */ + if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { + int spd = (scontrol >> 4) & 0xf; + ap->sata_spd_limit &= (1 << spd) - 1; } + + /* wait for device */ + if (ata_port_online(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } /** @@ -2406,7 +2411,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) DPRINTK("ENTER\n"); - if (ap->ops->scr_read && !sata_dev_present(ap)) { + if (ata_port_offline(ap)) { classes[0] = ATA_DEV_NONE; goto out; } @@ -2457,6 +2462,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { u32 scontrol; + int rc; DPRINTK("ENTER\n"); @@ -2466,17 +2472,25 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) * reconfiguration. This works for at least ICH7 AHCI * and Sil3124. */ - scontrol = scr_read(ap, SCR_CONTROL); + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + scontrol = (scontrol & 0x0f0) | 0x302; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; sata_set_spd(ap); } /* issue phy wake/reset */ - scontrol = scr_read(ap, SCR_CONTROL); + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + scontrol = (scontrol & 0x0f0) | 0x301; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) + return rc; /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. @@ -2487,7 +2501,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) sata_phy_resume(ap); /* TODO: phy layer with polling, timeouts, etc. */ - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { *class = ATA_DEV_NONE; DPRINTK("EXIT, link offline\n"); return 0; @@ -2527,8 +2541,7 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) DPRINTK("ENTER\n"); /* print link status */ - if (ap->cbl == ATA_CBL_SATA) - sata_print_link_status(ap); + sata_print_link_status(ap); /* re-enable interrupts */ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ @@ -2575,7 +2588,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_reset_fn_t hardreset; hardreset = NULL; - if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) + if (sata_scr_valid(ap)) hardreset = sata_std_hardreset; return ata_drive_probe_reset(ap, ata_std_probeinit, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 181917ac0426..748569b615fc 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1309,8 +1309,8 @@ static void mv_err_intr(struct ata_port *ap) edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); if (EDMA_ERR_SERR & edma_err_cause) { - serr = scr_read(ap, SCR_ERROR); - scr_write_flush(ap, SCR_ERROR, serr); + sata_scr_read(ap, SCR_ERROR, &serr); + sata_scr_write_flush(ap, SCR_ERROR, serr); } if (EDMA_ERR_SELF_DIS & edma_err_cause) { struct mv_port_priv *pp = ap->private_data; @@ -1934,15 +1934,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) /* Issue COMRESET via SControl */ comreset_retry: - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); __msleep(1, can_sleep); - scr_write_flush(ap, SCR_CONTROL, 0x300); + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); __msleep(20, can_sleep); timeout = jiffies + msecs_to_jiffies(200); do { - sstatus = scr_read(ap, SCR_STATUS) & 0x3; + sata_scr_read(ap, SCR_STATUS, &sstatus); + sstatus &= 0x3; if ((sstatus == 3) || (sstatus == 0)) break; @@ -1959,11 +1960,12 @@ comreset_retry: "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { ata_port_probe(ap); } else { + sata_scr_read(ap, SCR_STATUS, &sstatus); printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", - ap->id, scr_read(ap, SCR_STATUS)); + ap->id, sstatus); ata_port_disable(ap); return; } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 45b9e37c191e..bedc787dafd1 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -464,7 +464,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) DPRINTK("ENTER\n"); - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { DPRINTK("PHY reports no device\n"); *class = ATA_DEV_NONE; goto out; @@ -531,7 +531,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) sata_set_spd(ap); tout_msec = 100; - if (sata_dev_present(ap)) + if (ata_port_online(ap)) tout_msec = 5000; writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); @@ -544,7 +544,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) msleep(100); if (tmp & PORT_CS_DEV_RST) { - if (!sata_dev_present(ap)) + if (ata_port_offline(ap)) return 0; reason = "link not ready"; goto err; -- cgit v1.2.3 From 3373efd89dead4ce7818d685729e0431448357c9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:53 +0900 Subject: [PATCH] libata: use dev->ap Use dev->ap where possible and eliminate superflous @ap from functions and structures. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 2 +- drivers/scsi/libata-core.c | 160 +++++++++++++++++++++------------------------ drivers/scsi/libata-scsi.c | 40 +++++------- drivers/scsi/libata.h | 11 ++-- include/linux/libata.h | 21 +++--- 5 files changed, 106 insertions(+), 128 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c2298fb131d8..f6e4c8ea74e3 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -597,7 +597,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* restart engine */ ahci_start_engine(ap); - ata_tf_init(ap, &tf, 0); + ata_tf_init(ap->device, &tf); fis = pp->cmd_tbl; /* issue the first D2H Register FIS */ diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 31b65e0da0b1..4ced962db812 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,13 +61,10 @@ #include "libata.h" -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors); -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev); -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors); +static unsigned int ata_dev_set_xfermode(struct ata_device *dev); +static void ata_dev_xfermask(struct ata_device *dev); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -412,11 +409,11 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +void ata_dev_disable(struct ata_device *dev) { if (ata_dev_enabled(dev)) { printk(KERN_WARNING "ata%u: dev %u disabled\n", - ap->id, dev->devno); + dev->ap->id, dev->devno); dev->class++; } } @@ -960,7 +957,6 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) /** * ata_exec_internal - execute libata internal command - * @ap: Port to which the command is sent * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command @@ -978,10 +974,11 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * None. Should be called with kernel context, might sleep. */ -unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, +unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { + struct ata_port *ap = dev->ap; u8 command = tf->command; struct ata_queued_cmd *qc; DECLARE_COMPLETION(wait); @@ -990,7 +987,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_new_init(ap, dev); + qc = ata_qc_new_init(dev); BUG_ON(qc == NULL); qc->tf = *tf; @@ -1095,7 +1092,6 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) /** * ata_dev_read_id - Read ID data from the specified device - * @ap: port on which target device resides * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? @@ -1112,9 +1108,10 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * RETURNS: * 0 on success, -errno otherwise. */ -static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 *id) +static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id) { + struct ata_port *ap = dev->ap; unsigned int class = *p_class; struct ata_taskfile tf; unsigned int err_mask = 0; @@ -1126,7 +1123,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ retry: - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); switch (class) { case ATA_DEV_ATA: @@ -1143,7 +1140,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, tf.protocol = ATA_PROT_PIO; - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_FROM_DEVICE, + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { rc = -EIO; @@ -1170,7 +1167,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, * Some drives were very specific about that exact sequence. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { - err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); + err_mask = ata_dev_init_params(dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -1195,15 +1192,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, return rc; } -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) +static inline u8 ata_dev_knobble(struct ata_device *dev) { - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); + return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } /** * ata_dev_configure - Configure the specified ATA/ATAPI device - * @ap: Port on which target device resides * @dev: Target device to configure * @print_info: Enable device info printout * @@ -1216,9 +1211,9 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap, * RETURNS: * 0 on success, -errno otherwise */ -static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, - int print_info) +static int ata_dev_configure(struct ata_device *dev, int print_info) { + struct ata_port *ap = dev->ap; const u16 *id = dev->id; unsigned int xfer_mask; int i, rc; @@ -1331,7 +1326,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, ap->device[i].cdb_len); /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, dev)) { + if (ata_dev_knobble(dev)) { if (print_info) printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, dev->devno); @@ -1416,11 +1411,11 @@ static int ata_bus_probe(struct ata_port *ap) if (!ata_dev_enabled(dev)) continue; - rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); if (rc) goto fail; - rc = ata_dev_configure(ap, dev, 1); + rc = ata_dev_configure(dev, 1); if (rc) goto fail; } @@ -1453,13 +1448,13 @@ static int ata_bus_probe(struct ata_port *ap) default: tries[dev->devno]--; if (down_xfermask && - ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1)) + ata_down_xfermask_limit(dev, tries[dev->devno] == 1)) tries[dev->devno] = 0; } if (!tries[dev->devno]) { - ata_down_xfermask_limit(ap, dev, 1); - ata_dev_disable(ap, dev); + ata_down_xfermask_limit(dev, 1); + ata_dev_disable(dev); } goto retry; @@ -1586,15 +1581,15 @@ void sata_phy_reset(struct ata_port *ap) /** * ata_dev_pair - return other device on cable - * @ap: port * @adev: device * * Obtain the other device on the same cable, or if none is * present NULL is returned */ -struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) +struct ata_device *ata_dev_pair(struct ata_device *adev) { + struct ata_port *ap = adev->ap; struct ata_device *pair = &ap->device[1 - adev->devno]; if (!ata_dev_enabled(pair)) return NULL; @@ -1886,7 +1881,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, /** * ata_down_xfermask_limit - adjust dev xfer masks downward - * @ap: Port associated with device @dev * @dev: Device to adjust xfer masks * @force_pio0: Force PIO0 * @@ -1900,9 +1894,9 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, * RETURNS: * 0 on success, negative errno on failure */ -int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0) +int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) { + struct ata_port *ap = dev->ap; unsigned long xfer_mask; int highbit; @@ -1934,8 +1928,9 @@ int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, return -EINVAL; } -static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +static int ata_dev_set_mode(struct ata_device *dev) { + struct ata_port *ap = dev->ap; unsigned int err_mask; int rc; @@ -1943,7 +1938,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; - err_mask = ata_dev_set_xfermode(ap, dev); + err_mask = ata_dev_set_xfermode(dev); if (err_mask) { printk(KERN_ERR "ata%u: failed to set xfermode (err_mask=0x%x)\n", @@ -1951,7 +1946,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) return -EIO; } - rc = ata_dev_revalidate(ap, dev, 0); + rc = ata_dev_revalidate(dev, 0); if (rc) return rc; @@ -2007,7 +2002,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) if (!ata_dev_enabled(dev)) continue; - ata_dev_xfermask(ap, dev); + ata_dev_xfermask(dev); pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); @@ -2060,7 +2055,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) if (!ata_dev_enabled(dev)) continue; - rc = ata_dev_set_mode(ap, dev); + rc = ata_dev_set_mode(dev); if (rc) goto out; } @@ -2712,7 +2707,6 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, /** * ata_dev_same_device - Determine whether new ID matches configured device - * @ap: port on which the device to compare against resides * @dev: device to compare against * @new_class: class of the new device * @new_id: IDENTIFY page of the new device @@ -2727,9 +2721,10 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, * RETURNS: * 1 if @dev matches @new_class and @new_id, 0 otherwise. */ -static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, - unsigned int new_class, const u16 *new_id) +static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, + const u16 *new_id) { + struct ata_port *ap = dev->ap; const u16 *old_id = dev->id; unsigned char model[2][41], serial[2][21]; u64 new_n_sectors; @@ -2774,7 +2769,6 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, /** * ata_dev_revalidate - Revalidate ATA device - * @ap: port on which the device to revalidate resides * @dev: device to revalidate * @post_reset: is this revalidation after reset? * @@ -2787,9 +2781,9 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, * RETURNS: * 0 on success, negative errno otherwise */ -int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, - int post_reset) +int ata_dev_revalidate(struct ata_device *dev, int post_reset) { + struct ata_port *ap = dev->ap; unsigned int class = dev->class; u16 *id = (void *)ap->sector_buf; int rc; @@ -2800,12 +2794,12 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, } /* read ID data */ - rc = ata_dev_read_id(ap, dev, &class, post_reset, id); + rc = ata_dev_read_id(dev, &class, post_reset, id); if (rc) goto fail; /* is the device still there? */ - if (!ata_dev_same_device(ap, dev, class, id)) { + if (!ata_dev_same_device(dev, class, id)) { rc = -ENODEV; goto fail; } @@ -2813,7 +2807,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); /* configure device according to the new ID */ - rc = ata_dev_configure(ap, dev, 0); + rc = ata_dev_configure(dev, 0); if (rc == 0) return 0; @@ -2895,7 +2889,6 @@ static int ata_dma_blacklisted(const struct ata_device *dev) /** * ata_dev_xfermask - Compute supported xfermask of the given device - * @ap: Port on which the device to compute xfermask for resides * @dev: Device to compute xfermask for * * Compute supported xfermask of @dev and store it in @@ -2910,8 +2903,9 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * LOCKING: * None. */ -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) +static void ata_dev_xfermask(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; @@ -2964,7 +2958,6 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) /** * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent * * Issue SET FEATURES - XFER MODE command to device @dev @@ -2977,8 +2970,7 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) * 0 on success, AC_ERR_* mask otherwise. */ -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev) +static unsigned int ata_dev_set_xfermode(struct ata_device *dev) { struct ata_taskfile tf; unsigned int err_mask; @@ -2986,14 +2978,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_SET_FEATURES; tf.feature = SETFEATURES_XFER; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -3001,8 +2993,9 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, /** * ata_dev_init_params - Issue INIT DEV PARAMS command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent + * @heads: Number of heads + * @sectors: Number of sectors * * LOCKING: * Kernel thread context (may sleep) @@ -3010,11 +3003,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, * RETURNS: * 0 on success, AC_ERR_* mask otherwise. */ - -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors) +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; @@ -3026,14 +3016,14 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, /* set up init dev params taskfile */ DPRINTK("init dev params \n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_INIT_DEV_PARAMS; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -4045,16 +4035,15 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /** * ata_qc_new_init - Request an available ATA command, and initialize it - * @ap: Port associated with device @dev * @dev: Device from whom we request an available command structure * * LOCKING: * None. */ -struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_queued_cmd *qc; qc = ata_qc_new(ap); @@ -4520,19 +4509,18 @@ int ata_port_offline(struct ata_port *ap) * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, * without filling any other registers */ -static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, - u8 cmd) +static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) { struct ata_taskfile tf; int err; - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = cmd; tf.flags |= ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - err = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) printk(KERN_ERR "%s: ata command failed: %d\n", __FUNCTION__, err); @@ -4540,7 +4528,7 @@ static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, return err; } -static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) +static int ata_flush_cache(struct ata_device *dev) { u8 cmd; @@ -4552,22 +4540,21 @@ static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) else cmd = ATA_CMD_FLUSH; - return ata_do_simple_cmd(ap, dev, cmd); + return ata_do_simple_cmd(dev, cmd); } -static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_standby_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); + return ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); } -static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_start_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); + return ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE); } /** * ata_device_resume - wakeup a previously suspended devices - * @ap: port the device is connected to * @dev: the device to resume * * Kick the drive back into action, by sending it an idle immediate @@ -4575,39 +4562,42 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) * and host. * */ -int ata_device_resume(struct ata_port *ap, struct ata_device *dev) +int ata_device_resume(struct ata_device *dev) { + struct ata_port *ap = dev->ap; + if (ap->flags & ATA_FLAG_SUSPENDED) { struct ata_device *failed_dev; ap->flags &= ~ATA_FLAG_SUSPENDED; while (ata_set_mode(ap, &failed_dev)) - ata_dev_disable(ap, failed_dev); + ata_dev_disable(failed_dev); } if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_start_drive(ap, dev); + ata_start_drive(dev); return 0; } /** * ata_device_suspend - prepare a device for suspend - * @ap: port the device is connected to * @dev: the device to suspend * * Flush the cache on the drive, if appropriate, then issue a * standbynow command. */ -int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) +int ata_device_suspend(struct ata_device *dev, pm_message_t state) { + struct ata_port *ap = dev->ap; + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_flush_cache(ap, dev); + ata_flush_cache(dev); if (state.event != PM_EVENT_FREEZE) - ata_standby_drive(ap, dev); + ata_standby_drive(dev); ap->flags |= ATA_FLAG_SUSPENDED; return 0; } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ce90b6352a81..fcbf64e741bb 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -302,7 +302,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) /** * ata_scsi_qc_new - acquire new ata_queued_cmd reference - * @ap: ATA port to which the new command is attached * @dev: ATA device to which the new command is attached * @cmd: SCSI command that originated this ATA command * @done: SCSI command completion function @@ -321,14 +320,13 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) * RETURNS: * Command allocated, or %NULL if none available. */ -struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, - struct ata_device *dev, +struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; - qc = ata_qc_new_init(ap, dev); + qc = ata_qc_new_init(dev); if (qc) { qc->scsicmd = cmd; qc->scsidone = done; @@ -398,7 +396,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; - return ata_device_resume(ap, dev); + return ata_device_resume(dev); } int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) @@ -406,7 +404,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; - return ata_device_suspend(ap, dev, state); + return ata_device_suspend(dev, state); } /** @@ -1224,7 +1222,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) /** * ata_scsi_translate - Translate then issue SCSI command to ATA device - * @ap: ATA port to which the command is addressed * @dev: ATA device to which the command is addressed * @cmd: SCSI command to execute * @done: SCSI command completion function @@ -1247,17 +1244,16 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ -static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *), - ata_xlat_func_t xlat_func) +static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + ata_xlat_func_t xlat_func) { struct ata_queued_cmd *qc; u8 *scsicmd = cmd->cmnd; VPRINTK("ENTER\n"); - qc = ata_scsi_qc_new(ap, dev, cmd, done); + qc = ata_scsi_qc_new(dev, cmd, done); if (!qc) goto err_mem; @@ -1266,7 +1262,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", - ap->id, dev->devno); + dev->ap->id, dev->devno); goto err_did; } @@ -2433,19 +2429,20 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, #endif } -static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), - struct ata_port *ap, struct ata_device *dev) +static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + struct ata_device *dev) { if (dev->class == ATA_DEV_ATA) { ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, cmd->cmnd[0]); if (xlat_func) - ata_scsi_translate(ap, dev, cmd, done, xlat_func); + ata_scsi_translate(dev, cmd, done, xlat_func); else - ata_scsi_simulate(ap, dev, cmd, done); + ata_scsi_simulate(dev, cmd, done); } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); + ata_scsi_translate(dev, cmd, done, atapi_xlat); } /** @@ -2483,7 +2480,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) dev = ata_scsi_find_dev(ap, scsidev); if (likely(dev)) - __ata_scsi_queuecmd(cmd, done, ap, dev); + __ata_scsi_queuecmd(cmd, done, dev); else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); @@ -2496,7 +2493,6 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @ap: port the device is connected to * @dev: the target device * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. @@ -2508,14 +2504,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) * spin_lock_irqsave(host_set lock) */ -void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_scsi_args args; const u8 *scsicmd = cmd->cmnd; - args.ap = ap; args.dev = dev; args.id = dev->id; args.cmd = cmd; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 6442c2f1a80c..c9ff83bbcfae 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -32,7 +32,6 @@ #define DRV_VERSION "1.30" /* must be exactly four chars */ struct ata_scsi_args { - struct ata_port *ap; struct ata_device *dev; u16 *id; struct scsi_cmnd *cmd; @@ -43,18 +42,16 @@ struct ata_scsi_args { extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; -extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); -extern void ata_dev_disable(struct ata_port *ap, struct ata_device *dev); +extern void ata_dev_disable(struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); -extern unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, +extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); -extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0); +extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, unsigned int *classes); diff --git a/include/linux/libata.h b/include/linux/libata.h index ac2d2cc78b10..8154b366bbd1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -518,8 +518,7 @@ extern void ata_std_probeinit(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); -extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, - int post_reset); +extern int ata_dev_revalidate(struct ata_device *dev, int post_reset); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI @@ -545,8 +544,8 @@ extern int ata_port_online(struct ata_port *ap); extern int ata_port_offline(struct ata_port *ap); extern int ata_scsi_device_resume(struct scsi_device *); extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); -extern int ata_device_resume(struct ata_port *, struct ata_device *); -extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state); +extern int ata_device_resume(struct ata_device *); +extern int ata_device_suspend(struct ata_device *, pm_message_t state); extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, @@ -592,15 +591,13 @@ extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void __ata_qc_complete(struct ata_queued_cmd *qc); -extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); -extern struct ata_device *ata_dev_pair(struct ata_port *ap, - struct ata_device *adev); +extern struct ata_device *ata_dev_pair(struct ata_device *adev); /* * Timing helpers @@ -812,12 +809,12 @@ static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap, return NULL; } -static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, unsigned int device) +static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) { memset(tf, 0, sizeof(*tf)); - tf->ctl = ap->ctl; - if (device == 0) + tf->ctl = dev->ap->ctl; + if (dev->devno == 0) tf->device = ATA_DEVICE_OBS; else tf->device = ATA_DEVICE_OBS | ATA_DEV1; @@ -832,7 +829,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->nbytes = qc->curbytes = 0; qc->err_mask = 0; - ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); + ata_tf_init(qc->dev, &qc->tf); /* init result_tf such that it indicates normal completion */ qc->result_tf.command = ATA_DRDY; -- cgit v1.2.3 From f15a1dafed22d5037e0feea7528e1eeb28a1a7a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:56 +0900 Subject: [PATCH] libata: use ATA printk helpers Use ATA printk helpers. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 8 +- drivers/scsi/ata_piix.c | 4 +- drivers/scsi/libata-core.c | 199 ++++++++++++++++++++------------------------ drivers/scsi/libata-eh.c | 5 +- drivers/scsi/libata-scsi.c | 9 +- drivers/scsi/sata_mv.c | 8 +- drivers/scsi/sata_promise.c | 7 +- drivers/scsi/sata_sil.c | 8 +- drivers/scsi/sata_sil24.c | 6 +- drivers/scsi/sata_sx4.c | 7 +- 10 files changed, 124 insertions(+), 137 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index f6e4c8ea74e3..a4fb8d0a6c08 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -655,8 +655,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return rc; } @@ -798,9 +797,8 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) if ((ap->device[0].class != ATA_DEV_ATAPI) || ((irq_stat & PORT_IRQ_TF_ERR) == 0)) - printk(KERN_WARNING "ata%u: port reset, " + ata_port_printk(ap, KERN_WARNING, "port reset, " "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", - ap->id, irq_stat, readl(mmio + HOST_IRQ_STAT), readl(port_mmio + PORT_IRQ_STAT), @@ -840,7 +838,7 @@ static void ahci_eng_timeout(struct ata_port *ap) struct ata_queued_cmd *qc; unsigned long flags; - printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id); + ata_port_printk(ap, KERN_WARNING, "handling error/timeout\n"); spin_lock_irqsave(&host_set->lock, flags); diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 62dabf74188e..af1d46e36107 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -484,7 +484,7 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); return 0; } @@ -565,7 +565,7 @@ static unsigned int piix_sata_probe (struct ata_port *ap) static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes) { if (!piix_sata_probe(ap)) { - printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); + ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); return 0; } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4ced962db812..9a97ebd59209 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -412,8 +412,7 @@ static const char *sata_spd_string(unsigned int spd) void ata_dev_disable(struct ata_device *dev) { if (ata_dev_enabled(dev)) { - printk(KERN_WARNING "ata%u: dev %u disabled\n", - dev->ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, "disabled\n"); dev->class++; } } @@ -1021,8 +1020,9 @@ unsigned ata_exec_internal(struct ata_device *dev, if (qc->flags & ATA_QCFLAG_ACTIVE) { qc->err_mask = AC_ERR_TIMEOUT; ata_qc_complete(qc); - printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", - ap->id, command); + + ata_dev_printk(dev, KERN_WARNING, + "qc timeout (cmd 0x%x)\n", command); } spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -1187,8 +1187,8 @@ static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, return 0; err_out: - printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", - ap->id, dev->devno, reason); + ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " + "(%s, err_mask=0x%x)\n", reason, err_mask); return rc; } @@ -1228,10 +1228,10 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device capabilities */ if (print_info) - printk(KERN_DEBUG "ata%u: dev %u cfg 49:%04x 82:%04x 83:%04x " - "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", - ap->id, dev->devno, id[49], id[82], id[83], - id[84], id[85], id[86], id[87], id[88]); + ata_dev_printk(dev, KERN_DEBUG, "cfg 49:%04x 82:%04x 83:%04x " + "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", + id[49], id[82], id[83], id[84], + id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ dev->flags &= ~ATA_DFLAG_CFG_MASK; @@ -1267,13 +1267,12 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: %s\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - lba_desc); + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: %s\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + lba_desc); } else { /* CHS */ @@ -1291,13 +1290,12 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: CHS %u/%u/%u\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - dev->cylinders, dev->heads, dev->sectors); + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: CHS %u/%u/%u\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + dev->cylinders, dev->heads, dev->sectors); } dev->cdb_len = 16; @@ -1307,7 +1305,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) else if (dev->class == ATA_DEV_ATAPI) { rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { - printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + ata_dev_printk(dev, KERN_WARNING, + "unsupported CDB len\n"); rc = -EINVAL; goto err_out_nosup; } @@ -1315,8 +1314,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s\n", + ata_mode_string(xfer_mask)); } ap->host->max_cmd_len = 0; @@ -1328,8 +1327,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(dev)) { if (print_info) - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, + "applying bridge limits\n"); dev->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } @@ -1382,7 +1381,8 @@ static int ata_bus_probe(struct ata_port *ap) if (ap->ops->probe_reset) { rc = ap->ops->probe_reset(ap, classes); if (rc) { - printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); + ata_port_printk(ap, KERN_ERR, + "reset failed (errno=%d)\n", rc); return rc; } } else { @@ -1495,13 +1495,13 @@ static void sata_print_link_status(struct ata_port *ap) if (ata_port_online(ap)) { tmp = (sstatus >> 4) & 0xf; - printk(KERN_INFO - "ata%u: SATA link up %s (SStatus %X SControl %X)\n", - ap->id, sata_spd_string(tmp), sstatus, scontrol); + ata_port_printk(ap, KERN_INFO, + "SATA link up %s (SStatus %X SControl %X)\n", + sata_spd_string(tmp), sstatus, scontrol); } else { - printk(KERN_INFO - "ata%u: SATA link down (SStatus %X SControl %X)\n", - ap->id, sstatus, scontrol); + ata_port_printk(ap, KERN_INFO, + "SATA link down (SStatus %X SControl %X)\n", + sstatus, scontrol); } } @@ -1655,8 +1655,8 @@ int sata_down_spd_limit(struct ata_port *ap) ap->sata_spd_limit = mask; - printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n", - ap->id, sata_spd_string(fls(mask))); + ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n", + sata_spd_string(fls(mask))); return 0; } @@ -1896,7 +1896,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, */ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) { - struct ata_port *ap = dev->ap; unsigned long xfer_mask; int highbit; @@ -1919,8 +1918,8 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, &dev->udma_mask); - printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n", + ata_mode_string(xfer_mask)); return 0; @@ -1930,7 +1929,6 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) static int ata_dev_set_mode(struct ata_device *dev) { - struct ata_port *ap = dev->ap; unsigned int err_mask; int rc; @@ -1940,9 +1938,8 @@ static int ata_dev_set_mode(struct ata_device *dev) err_mask = ata_dev_set_xfermode(dev); if (err_mask) { - printk(KERN_ERR - "ata%u: failed to set xfermode (err_mask=0x%x)\n", - ap->id, err_mask); + ata_dev_printk(dev, KERN_ERR, "failed to set xfermode " + "(err_mask=0x%x)\n", err_mask); return -EIO; } @@ -1953,9 +1950,8 @@ static int ata_dev_set_mode(struct ata_device *dev) DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", dev->xfer_shift, (int)dev->xfer_mode); - printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, dev->devno, - ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); + ata_dev_printk(dev, KERN_INFO, "configured for %s\n", + ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); return 0; } @@ -2023,8 +2019,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) continue; if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: dev %u no PIO support\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); rc = -EINVAL; goto out; } @@ -2123,8 +2118,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap, } if (status & ATA_BUSY) - printk(KERN_WARNING "ata%u is slow to respond, " - "please be patient\n", ap->id); + ata_port_printk(ap, KERN_WARNING, + "port is slow to respond, please be patient\n"); timeout = timer_start + tmout; while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { @@ -2133,8 +2128,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap, } if (status & ATA_BUSY) { - printk(KERN_ERR "ata%u failed to respond (%lu secs)\n", - ap->id, tmout / HZ); + ata_port_printk(ap, KERN_ERR, "port failed to respond " + "(%lu secs)\n", tmout / HZ); return 1; } @@ -2227,7 +2222,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * pulldown resistor. */ if (ata_check_status(ap) == 0xFF) { - printk(KERN_ERR "ata%u: SRST failed (status 0xFF)\n", ap->id); + ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); return AC_ERR_OTHER; } @@ -2321,7 +2316,7 @@ void ata_bus_reset(struct ata_port *ap) return; err_out: - printk(KERN_ERR "ata%u: disabling port\n", ap->id); + ata_port_printk(ap, KERN_ERR, "disabling port\n"); ap->ops->port_disable(ap); DPRINTK("EXIT\n"); @@ -2424,8 +2419,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); + ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n", + err_mask); return -EIO; } @@ -2503,8 +2498,8 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - printk(KERN_ERR - "ata%u: COMRESET failed (device not ready)\n", ap->id); + ata_port_printk(ap, KERN_ERR, + "COMRESET failed (device not ready)\n"); return -EIO; } @@ -2662,8 +2657,8 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, rc = ata_do_reset(ap, softreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; - printk(KERN_INFO "ata%u: softreset failed, will try " - "hardreset in 5 secs\n", ap->id); + ata_port_printk(ap, KERN_INFO, "softreset failed, " + "will try hardreset in 5 secs\n"); ssleep(5); } @@ -2681,15 +2676,15 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (sata_down_spd_limit(ap)) goto done; - printk(KERN_INFO "ata%u: hardreset failed, will retry " - "in 5 secs\n", ap->id); + ata_port_printk(ap, KERN_INFO, "hardreset failed, " + "will retry in 5 secs\n"); ssleep(5); } if (softreset) { - printk(KERN_INFO "ata%u: hardreset succeeded without " - "classification, will retry softreset in 5 secs\n", - ap->id); + ata_port_printk(ap, KERN_INFO, + "hardreset succeeded without classification, " + "will retry softreset in 5 secs\n"); ssleep(5); rc = ata_do_reset(ap, softreset, classes); @@ -2724,15 +2719,13 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, const u16 *new_id) { - struct ata_port *ap = dev->ap; const u16 *old_id = dev->id; unsigned char model[2][41], serial[2][21]; u64 new_n_sectors; if (dev->class != new_class) { - printk(KERN_INFO - "ata%u: dev %u class mismatch %d != %d\n", - ap->id, dev->devno, dev->class, new_class); + ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n", + dev->class, new_class); return 0; } @@ -2743,24 +2736,22 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, new_n_sectors = ata_id_n_sectors(new_id); if (strcmp(model[0], model[1])) { - printk(KERN_INFO - "ata%u: dev %u model number mismatch '%s' != '%s'\n", - ap->id, dev->devno, model[0], model[1]); + ata_dev_printk(dev, KERN_INFO, "model number mismatch " + "'%s' != '%s'\n", model[0], model[1]); return 0; } if (strcmp(serial[0], serial[1])) { - printk(KERN_INFO - "ata%u: dev %u serial number mismatch '%s' != '%s'\n", - ap->id, dev->devno, serial[0], serial[1]); + ata_dev_printk(dev, KERN_INFO, "serial number mismatch " + "'%s' != '%s'\n", serial[0], serial[1]); return 0; } if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) { - printk(KERN_INFO - "ata%u: dev %u n_sectors mismatch %llu != %llu\n", - ap->id, dev->devno, (unsigned long long)dev->n_sectors, - (unsigned long long)new_n_sectors); + ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " + "%llu != %llu\n", + (unsigned long long)dev->n_sectors, + (unsigned long long)new_n_sectors); return 0; } @@ -2783,9 +2774,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, */ int ata_dev_revalidate(struct ata_device *dev, int post_reset) { - struct ata_port *ap = dev->ap; unsigned int class = dev->class; - u16 *id = (void *)ap->sector_buf; + u16 *id = (void *)dev->ap->sector_buf; int rc; if (!ata_dev_enabled(dev)) { @@ -2812,8 +2802,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) return 0; fail: - printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", - ap->id, dev->devno, rc); + ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); return rc; } @@ -2941,8 +2930,8 @@ static void ata_dev_xfermask(struct ata_device *dev) } if (ata_dma_blacklisted(dev)) - printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " - "disabling DMA\n", ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "device is on DMA blacklist, disabling DMA\n"); if (hs->flags & ATA_HOST_SIMPLEX) { if (hs->simplex_claimed) @@ -3733,8 +3722,8 @@ next_sg: unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", - ap->id, bytes); + ata_dev_printk(qc->dev, KERN_WARNING, + "%u bytes trailing data\n", bytes); for (i = 0; i < words; i++) ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); @@ -3817,8 +3806,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) return; err_out: - printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n"); qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } @@ -3887,8 +3875,7 @@ static void ata_pio_error(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: dev %u PIO error\n", - ap->id, qc->dev->devno); + ata_dev_printk(qc->dev, KERN_WARNING, "PIO error\n"); /* make sure qc->err_mask is available to * know what's wrong and recover @@ -4314,7 +4301,7 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + ata_port_printk(ap, KERN_WARNING, "irq trap\n"); return 1; } #endif @@ -4522,8 +4509,8 @@ static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) - printk(KERN_ERR "%s: ata command failed: %d\n", - __FUNCTION__, err); + ata_dev_printk(dev, KERN_ERR, "%s: ata command failed: %d\n", + __FUNCTION__, err); return err; } @@ -4863,15 +4850,14 @@ int ata_device_add(const struct ata_probe_ent *ent) (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ - printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " - "bmdma 0x%lX irq %lu\n", - ap->id, - ap->flags & ATA_FLAG_SATA ? 'S' : 'P', - ata_mode_string(xfer_mode_mask), - ap->ioaddr.cmd_addr, - ap->ioaddr.ctl_addr, - ap->ioaddr.bmdma_addr, - ent->irq); + ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " + "ctl 0x%lX bmdma 0x%lX irq %lu\n", + ap->flags & ATA_FLAG_SATA ? 'S' : 'P', + ata_mode_string(xfer_mode_mask), + ap->ioaddr.cmd_addr, + ap->ioaddr.ctl_addr, + ap->ioaddr.bmdma_addr, + ent->irq); ata_chk_status(ap); host_set->ops->irq_clear(ap); @@ -4909,8 +4895,7 @@ int ata_device_add(const struct ata_probe_ent *ent) rc = scsi_add_host(ap->host, dev); if (rc) { - printk(KERN_ERR "ata%u: scsi_add_host failed\n", - ap->id); + ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); /* FIXME: do something useful here */ /* FIXME: handle unconditional calls to * scsi_scan_host and ata_host_remove, below, diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index c31b13fd5307..959a1cdffac2 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -167,8 +167,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* ack bmdma irq events */ ap->ops->irq_clear(ap); - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); + ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " + "stat 0x%x host_stat 0x%x\n", + qc->tf.command, drv_stat, host_stat); /* complete taskfile transaction */ qc->err_mask |= ac_err_mask(drv_stat); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index fcbf64e741bb..a9b4083a4f67 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1261,8 +1261,8 @@ static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, if (cmd->sc_data_direction == DMA_FROM_DEVICE || cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { - printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", - dev->ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "WARNING: zero len r/w req\n"); goto err_did; } @@ -2200,8 +2200,9 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { if (unlikely(dev->class == ATA_DEV_ATAPI)) { - printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n", - ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled"); + ata_dev_printk(dev, KERN_WARNING, + "WARNING: ATAPI is %s, device ignored.\n", + atapi_enabled ? "not supported with this driver" : "disabled"); return NULL; } } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 748569b615fc..e8d00f0efdf2 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -680,7 +680,7 @@ static void mv_stop_dma(struct ata_port *ap) } if (EDMA_EN & reg) { - printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id); + ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); /* FIXME: Consider doing a reset here to recover */ } } @@ -1964,8 +1964,8 @@ comreset_retry: ata_port_probe(ap); } else { sata_scr_read(ap, SCR_STATUS, &sstatus); - printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", - ap->id, sstatus); + ata_port_printk(ap, KERN_INFO, + "no device found (phy stat %08x)\n", sstatus); ata_port_disable(ap); return; } @@ -2023,7 +2023,7 @@ static void mv_eng_timeout(struct ata_port *ap) { struct ata_queued_cmd *qc; - printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); + ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n"); DPRINTK("All regs @ start of eng_timeout\n"); mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, to_pci_dev(ap->host_set->dev)); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index ddbc0c6dd9fe..e9d61bc2b247 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -435,7 +435,7 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); drv_stat = ata_wait_idle(ap); qc->err_mask |= __ac_err_mask(drv_stat); break; @@ -443,8 +443,9 @@ static void pdc_eng_timeout(struct ata_port *ap) default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index c9333577330e..bfcece18a7cb 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -360,16 +360,16 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) if (slow_down || ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE))) { - printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix " + "(mod15write workaround)\n"); dev->max_sectors = 15; return; } /* limit to udma5 */ if (quirks & SIL_QUIRK_UDMA5MAX) { - printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", - ap->id, dev->devno, model_num); + ata_dev_printk(dev, KERN_INFO, + "applying Maxtor errata fix %s\n", model_num); dev->udma_mask &= ATA_UDMA5; return; } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index bedc787dafd1..ff96724b1e38 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -516,7 +516,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) return 0; err: - printk(KERN_ERR "ata%u: softreset failed (%s)\n", ap->id, reason); + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return -EIO; } @@ -561,7 +561,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) return 0; err: - printk(KERN_ERR "ata%u: hardreset failed (%s)\n", ap->id, reason); + ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); return -EIO; } @@ -721,7 +721,7 @@ static void sil24_eng_timeout(struct ata_port *ap) qc = ata_qc_from_tag(ap, ap->active_tag); - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= AC_ERR_TIMEOUT; ata_eh_qc_complete(qc); diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index a669d0589889..96d7b73f5fdc 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -868,15 +868,16 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); break; default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; -- cgit v1.2.3 From 78cd52d02fa0735949a9fa30a6b79bf02c94c250 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:29 +0900 Subject: [PATCH] ahci: convert to new EH Convert AHCI to new EH. Unfortunately, ICH7 AHCI reacts badly if IRQ mask is diddled during operation. So, freezing is implemented by unconditionally clearing interrupt conditions while frozen. * Interrupts are categorized according to required action. e.g. Connection status or unknown FIS error requires freezing the port while TF or HBUS_DATA don't. * Only CONNECT (reflects SErr.X) interrupt is taken into account not PHYRDY (SErr.N), as CONNECT is better cue for starting EH. * AHCI may be invoked without any active command. e.g. CONNECT irq occuring while no qc in progress still triggers EH and will reset the port and revalidate attached device. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 237 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 100 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a4fb8d0a6c08..d6894bd67980 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -71,6 +71,7 @@ enum { AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ + RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ board_ahci = 0, board_ahci_vt8251 = 1, @@ -128,15 +129,16 @@ enum { PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ - PORT_IRQ_FATAL = PORT_IRQ_TF_ERR | - PORT_IRQ_HBUS_ERR | - PORT_IRQ_HBUS_DATA_ERR | - PORT_IRQ_IF_ERR, - DEF_PORT_IRQ = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | - PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | - PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | - PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | - PORT_IRQ_D2H_REG_FIS, + PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | + PORT_IRQ_IF_ERR | + PORT_IRQ_CONNECT | + PORT_IRQ_UNK_FIS, + PORT_IRQ_ERROR = PORT_IRQ_FREEZE | + PORT_IRQ_TF_ERR | + PORT_IRQ_HBUS_DATA_ERR, + DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, /* PORT_CMD bits */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ @@ -197,13 +199,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); static void ahci_irq_clear(struct ata_port *ap); -static void ahci_eng_timeout(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); +static void ahci_freeze(struct ata_port *ap); +static void ahci_thaw(struct ata_port *ap); +static void ahci_error_handler(struct ata_port *ap); +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); static struct scsi_host_template ahci_sht = { @@ -237,14 +241,18 @@ static const struct ata_port_operations ahci_ops = { .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, - .eng_timeout = ahci_eng_timeout, - .irq_handler = ahci_interrupt, .irq_clear = ahci_irq_clear, .scr_read = ahci_scr_read, .scr_write = ahci_scr_write, + .freeze = ahci_freeze, + .thaw = ahci_thaw, + + .error_handler = ahci_error_handler, + .post_internal_cmd = ahci_post_internal_cmd, + .port_start = ahci_port_start, .port_stop = ahci_port_stop, }; @@ -789,108 +797,97 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ahci_fill_cmd_slot(pp, opts); } -static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) +static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) { - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 tmp; + struct ahci_port_priv *pp = ap->private_data; + struct ata_eh_info *ehi = &ap->eh_info; + unsigned int err_mask = 0, action = 0; + struct ata_queued_cmd *qc; + u32 serror; - if ((ap->device[0].class != ATA_DEV_ATAPI) || - ((irq_stat & PORT_IRQ_TF_ERR) == 0)) - ata_port_printk(ap, KERN_WARNING, "port reset, " - "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", - irq_stat, - readl(mmio + HOST_IRQ_STAT), - readl(port_mmio + PORT_IRQ_STAT), - readl(port_mmio + PORT_CMD), - readl(port_mmio + PORT_TFDATA), - readl(port_mmio + PORT_SCR_STAT), - readl(port_mmio + PORT_SCR_ERR)); - - /* stop DMA */ - ahci_stop_engine(ap); + ata_ehi_clear_desc(ehi); - /* clear SATA phy error, if any */ - tmp = readl(port_mmio + PORT_SCR_ERR); - writel(tmp, port_mmio + PORT_SCR_ERR); + /* AHCI needs SError cleared; otherwise, it might lock up */ + serror = ahci_scr_read(ap, SCR_ERROR); + ahci_scr_write(ap, SCR_ERROR, serror); - /* if DRQ/BSY is set, device needs to be reset. - * if so, issue COMRESET - */ - tmp = readl(port_mmio + PORT_TFDATA); - if (tmp & (ATA_BUSY | ATA_DRQ)) { - writel(0x301, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ - udelay(10); - writel(0x300, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ + /* analyze @irq_stat */ + ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); + + if (irq_stat & PORT_IRQ_TF_ERR) + err_mask |= AC_ERR_DEV; + + if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { + err_mask |= AC_ERR_HOST_BUS; + action |= ATA_EH_SOFTRESET; } - /* re-start DMA */ - ahci_start_engine(ap); -} + if (irq_stat & PORT_IRQ_IF_ERR) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", interface fatal error"); + } -static void ahci_eng_timeout(struct ata_port *ap) -{ - struct ata_host_set *host_set = ap->host_set; - void __iomem *mmio = host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ata_queued_cmd *qc; - unsigned long flags; + if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? + "connection status changed" : "PHY RDY changed"); + } + + if (irq_stat & PORT_IRQ_UNK_FIS) { + u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); - ata_port_printk(ap, KERN_WARNING, "handling error/timeout\n"); + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x", + unk[0], unk[1], unk[2], unk[3]); + } - spin_lock_irqsave(&host_set->lock, flags); + /* okay, let's hand over to EH */ + ehi->serror |= serror; + ehi->action |= action; - ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); qc = ata_qc_from_tag(ap, ap->active_tag); - qc->err_mask |= AC_ERR_TIMEOUT; - - spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + qc->err_mask |= err_mask; + else + ehi->err_mask |= err_mask; - ata_eh_qc_complete(qc); + if (irq_stat & PORT_IRQ_FREEZE) + ata_port_freeze(ap); + else + ata_port_abort(ap); } -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) +static void ahci_host_intr(struct ata_port *ap) { void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 status, serr, ci; - - serr = readl(port_mmio + PORT_SCR_ERR); - writel(serr, port_mmio + PORT_SCR_ERR); + struct ata_queued_cmd *qc; + u32 status, ci; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); - ci = readl(port_mmio + PORT_CMD_ISSUE); - if (likely((ci & 0x1) == 0)) { - if (qc) { - WARN_ON(qc->err_mask); - ata_qc_complete(qc); - qc = NULL; - } + if (unlikely(status & PORT_IRQ_ERROR)) { + ahci_error_intr(ap, status); + return; } - if (status & PORT_IRQ_FATAL) { - unsigned int err_mask; - if (status & PORT_IRQ_TF_ERR) - err_mask = AC_ERR_DEV; - else if (status & PORT_IRQ_IF_ERR) - err_mask = AC_ERR_ATA_BUS; - else - err_mask = AC_ERR_HOST_BUS; - - /* command processing has stopped due to error; restart */ - ahci_restart_port(ap, status); - - if (qc) { - qc->err_mask |= err_mask; + if ((qc = ata_qc_from_tag(ap, ap->active_tag))) { + ci = readl(port_mmio + PORT_CMD_ISSUE); + if ((ci & 0x1) == 0) { ata_qc_complete(qc); + return; } } - return 1; + /* spurious interrupt */ + if (ata_ratelimit()) + ata_port_printk(ap, KERN_INFO, "spurious interrupt " + "(irq_stat 0x%x active_tag %d)\n", + status, ap->active_tag); } static void ahci_irq_clear(struct ata_port *ap) @@ -927,14 +924,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * ap = host_set->ports[i]; if (ap) { - struct ata_queued_cmd *qc; - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!ahci_host_intr(ap, qc)) - if (ata_ratelimit()) - dev_printk(KERN_WARNING, host_set->dev, - "unhandled interrupt on port %u\n", - i); - + ahci_host_intr(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -951,7 +941,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * handled = 1; } - spin_unlock(&host_set->lock); + spin_unlock(&host_set->lock); VPRINTK("EXIT\n"); @@ -969,6 +959,56 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) return 0; } +static void ahci_freeze(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + + /* turn IRQ off */ + writel(0, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_thaw(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + u32 tmp; + + /* clear IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + writel(tmp, port_mmio + PORT_IRQ_STAT); + writel(1 << ap->id, mmio + HOST_IRQ_STAT); + + /* turn IRQ back on */ + writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_error_handler(struct ata_port *ap) +{ + if (!(ap->flags & ATA_FLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } + + /* perform recovery */ + ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset); +} + +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + if (qc->err_mask) { + /* make DMA engine forget about the failed command */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } +} + static void ahci_setup_port(struct ata_ioports *port, unsigned long base, unsigned int port_idx) { @@ -1113,9 +1153,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) writel(tmp, port_mmio + PORT_IRQ_STAT); writel(1 << i, mmio + HOST_IRQ_STAT); - - /* set irq mask (enables interrupts) */ - writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); } tmp = readl(mmio + HOST_CTL); -- cgit v1.2.3 From 2a3917a8bb40a2cb75b458da9c356e8557e8fbed Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:30 +0900 Subject: [PATCH] ahci: add PIOS interim interrupt handling During multiblock PIO, multiple PIOS interrupts are generated before qc compltion. Current code prints unnecessary message for such cases. This is exposed when new EH slows down attached device into PIO mode. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index d6894bd67980..35487e30b0ff 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -883,7 +883,18 @@ static void ahci_host_intr(struct ata_port *ap) } } - /* spurious interrupt */ + /* hmmm... a spurious interupt */ + + /* ignore interim PIO setup fis interrupts */ + if (ata_tag_valid(ap->active_tag)) { + struct ata_queued_cmd *qc = + ata_qc_from_tag(ap, ap->active_tag); + + if (qc && qc->tf.protocol == ATA_PROT_PIO && + (status & PORT_IRQ_PIOS_FIS)) + return; + } + if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " "(irq_stat 0x%x active_tag %d)\n", -- cgit v1.2.3 From dd410ff12925fc49df3174b18e43598b2b2b621f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:50 +0900 Subject: [PATCH] ahci: clean up AHCI constants in preparation for NCQ * Rename CMD_TBL_HDR to CMD_TBL_HDR_SZ as it's size not offset. * Define MAX_CMDS and CMD_SZ and use them in calculation of other constants. * Define CMD_TBL_AR_SZ as product of CMD_TBL_SZ and MAX_CMDS, and use it when calculating PRIV_DMA_SZ. * CMD_SLOT_SZ is also dependent on MAX_CMDS but hasn't been changed because I didn't want to change the value used by the original code (32 commands). Later NCQ change will bump MAX_CMDS to 32 anyway and the hard coded 32 can be changed to MAX_CMDS then. * Reorder HOST_CAP_* flags. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 35487e30b0ff..b25373f530ac 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -56,12 +56,15 @@ enum { AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, - AHCI_CMD_SLOT_SZ = 32 * 32, + AHCI_MAX_CMDS = 1, + AHCI_CMD_SZ = 32, + AHCI_CMD_SLOT_SZ = 32 * AHCI_CMD_SZ, AHCI_RX_FIS_SZ = 256, - AHCI_CMD_TBL_HDR = 0x80, AHCI_CMD_TBL_CDB = 0x40, - AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16), - AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ + + AHCI_CMD_TBL_HDR_SZ = 0x80, + AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16), + AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, + AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ, AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), @@ -89,8 +92,8 @@ enum { HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ - HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ @@ -398,7 +401,7 @@ static int ahci_port_start(struct ata_port *ap) pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR; + pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR_SZ; ap->private_data = pp; -- cgit v1.2.3 From 979db803b8fd120d4ed5216520e9d1815e18bc38 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:52 +0900 Subject: [PATCH] ahci: add HOST_CAP_NCQ constant Add HOST_CAP_NCQ. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index b25373f530ac..740e7d86d5f8 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -93,6 +93,7 @@ enum { /* HOST_CAP bits */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ -- cgit v1.2.3 From a9764c2bb5b6d3c9df91f2977a2a640f55de0dc2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:53 +0900 Subject: [PATCH] ahci: kill pp->cmd_tbl_sg With NCQ, there are multiple sg tables, so pp->cmd_tbl_sg doesn't cut it. Directly calculate sg table address from pp->cmd_tbl. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 740e7d86d5f8..9f974dbcd7ed 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -191,7 +191,6 @@ struct ahci_port_priv { dma_addr_t cmd_slot_dma; void *cmd_tbl; dma_addr_t cmd_tbl_dma; - struct ahci_sg *cmd_tbl_sg; void *rx_fis; dma_addr_t rx_fis_dma; }; @@ -402,8 +401,6 @@ static int ahci_port_start(struct ata_port *ap) pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR_SZ; - ap->private_data = pp; if (hpriv->cap & HOST_CAP_64) @@ -749,7 +746,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) /* * Next, the S/G list. */ - ahci_sg = pp->cmd_tbl_sg; + ahci_sg = pp->cmd_tbl + AHCI_CMD_TBL_HDR_SZ; ata_for_each_sg(sg, qc) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); -- cgit v1.2.3 From 12fad3f965830d71f6454f02b2af002a64cec4d3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:55 +0900 Subject: [PATCH] ahci: implement NCQ suppport Implement NCQ support. Original implementation is from Jens Axboe. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 89 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 31 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 9f974dbcd7ed..45fd71d80128 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -56,9 +56,9 @@ enum { AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, - AHCI_MAX_CMDS = 1, + AHCI_MAX_CMDS = 32, AHCI_CMD_SZ = 32, - AHCI_CMD_SLOT_SZ = 32 * AHCI_CMD_SZ, + AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ, AHCI_RX_FIS_SZ = 256, AHCI_CMD_TBL_CDB = 0x40, AHCI_CMD_TBL_HDR_SZ = 0x80, @@ -218,7 +218,8 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = AHCI_MAX_CMDS - 1, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, @@ -533,12 +534,17 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) +static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, + u32 opts) { - pp->cmd_slot[0].opts = cpu_to_le32(opts); - pp->cmd_slot[0].status = 0; - pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); - pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); + dma_addr_t cmd_tbl_dma; + + cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ; + + pp->cmd_slot[tag].opts = cpu_to_le32(opts); + pp->cmd_slot[tag].status = 0; + pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff); + pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); } static int ahci_clo(struct ata_port *ap) @@ -610,7 +616,8 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fis = pp->cmd_tbl; /* issue the first D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); + ahci_fill_cmd_slot(pp, 0, + cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); tf.ctl |= ATA_SRST; ata_tf_to_fis(&tf, fis, 0); @@ -629,7 +636,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) msleep(1); /* issue the second D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len); + ahci_fill_cmd_slot(pp, 0, cmd_fis_len); tf.ctl &= ~ATA_SRST; ata_tf_to_fis(&tf, fis, 0); @@ -734,9 +741,8 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ata_tf_from_fis(d2h_fis, tf); } -static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) +static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) { - struct ahci_port_priv *pp = qc->ap->private_data; struct scatterlist *sg; struct ahci_sg *ahci_sg; unsigned int n_sg = 0; @@ -746,7 +752,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) /* * Next, the S/G list. */ - ahci_sg = pp->cmd_tbl + AHCI_CMD_TBL_HDR_SZ; + ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; ata_for_each_sg(sg, qc) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); @@ -767,6 +773,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct ahci_port_priv *pp = ap->private_data; int is_atapi = is_atapi_taskfile(&qc->tf); + void *cmd_tbl; u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ unsigned int n_elem; @@ -775,16 +782,17 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS. */ - ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); + cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; + + ata_tf_to_fis(&qc->tf, cmd_tbl, 0); if (is_atapi) { - memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); - memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, - qc->dev->cdb_len); + memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); + memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); } n_elem = 0; if (qc->flags & ATA_QCFLAG_DMAMAP) - n_elem = ahci_fill_sg(qc); + n_elem = ahci_fill_sg(qc, cmd_tbl); /* * Fill in command slot information. @@ -795,7 +803,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) if (is_atapi) opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; - ahci_fill_cmd_slot(pp, opts); + ahci_fill_cmd_slot(pp, qc->tag, opts); } static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) @@ -865,8 +873,9 @@ static void ahci_host_intr(struct ata_port *ap) { void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ata_queued_cmd *qc; - u32 status, ci; + struct ata_eh_info *ehi = &ap->eh_info; + u32 status, qc_active; + int rc; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); @@ -876,16 +885,27 @@ static void ahci_host_intr(struct ata_port *ap) return; } - if ((qc = ata_qc_from_tag(ap, ap->active_tag))) { - ci = readl(port_mmio + PORT_CMD_ISSUE); - if ((ci & 0x1) == 0) { - ata_qc_complete(qc); - return; - } + if (ap->sactive) + qc_active = readl(port_mmio + PORT_SCR_ACT); + else + qc_active = readl(port_mmio + PORT_CMD_ISSUE); + + rc = ata_qc_complete_multiple(ap, qc_active, NULL); + if (rc > 0) + return; + if (rc < 0) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + return; } /* hmmm... a spurious interupt */ + /* some devices send D2H reg with I bit set during NCQ command phase */ + if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS) + return; + /* ignore interim PIO setup fis interrupts */ if (ata_tag_valid(ap->active_tag)) { struct ata_queued_cmd *qc = @@ -898,8 +918,8 @@ static void ahci_host_intr(struct ata_port *ap) if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " - "(irq_stat 0x%x active_tag %d)\n", - status, ap->active_tag); + "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", + status, ap->active_tag, ap->sactive); } static void ahci_irq_clear(struct ata_port *ap) @@ -907,7 +927,7 @@ static void ahci_irq_clear(struct ata_port *ap) /* TODO */ } -static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; struct ahci_host_priv *hpriv; @@ -965,7 +985,9 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; - writel(1, port_mmio + PORT_CMD_ISSUE); + if (qc->tf.protocol == ATA_PROT_NCQ) + writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); + writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); readl(port_mmio + PORT_CMD_ISSUE); /* flush */ return 0; @@ -1262,6 +1284,8 @@ 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); + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -1329,6 +1353,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_hpriv; + if (hpriv->cap & HOST_CAP_NCQ) + probe_ent->host_flags |= ATA_FLAG_NCQ; + ahci_print_info(probe_ent); /* FIXME: check ata_device_add return value */ -- cgit v1.2.3 From f5914a461eb9703773226a0813f6ffcae10c0861 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:48 +0900 Subject: [PATCH] libata-hp-prep: add prereset() method and implement ata_std_prereset() With hotplug, every reset might be a probing reset and thus something similar to probe_init() is needed. prereset() method is called before a series of resets to a port and is the counterpart of postreset(). prereset() can tell EH to use different type of reset or skip reset by modifying ehc->i.action. This patch also implements ata_std_prereset(). Most controllers should be able to use this function directly or with some wrapping. After hotplug, different controllers need different actions to resume the PHY and detect the newly attached device. Controllers can be categorized as follows. * Controllers which can wait for the first D2H FIS after hotplug. Note that if the waiting is implemented by polling TF status, there needs to be a way to set BSY on PHY status change. It can be implemented by hardware or with the help of the driver. * Controllers which can wait for the first D2H FIS after sending COMRESET. These controllers need to issue COMRESET to wait for the first FIS. Note that the received D2H FIS could be the first D2H FIS after POR (power-on-reset) or D2H FIS in response to the COMRESET. Some controllers use COMRESET as TF status synchronization point and clear TF automatically (sata_sil). * Controllers which cannot wait for the first D2H FIS reliably. Blindly issuing SRST to spinning-up device often results in command issue failure or timeout, causing extended delay. For these controllers, ata_std_prereset() explicitly waits ATA_SPINUP_WAIT (currently 8s) to give newly attached device time to spin up, then issues reset. Note that failing to getting ready in ATA_SPINUP_WAIT is not critical. libata will retry. So, the timeout needs to be long enough to spin up most devices. LLDDs can tell ata_std_prereset() which of above action is needed with ATA_FLAG_HRST_TO_RESUME and ATA_FLAG_SKIP_D2H_BSY flags. These flags are PHY-specific property and will be moved to ata_link later. While at it, this patch unifies function typedef's such that they all have named arguments. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 3 +- drivers/scsi/libata-bmdma.c | 11 +++--- drivers/scsi/libata-core.c | 85 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-eh.c | 60 +++++++++++++++++++++++++++----- drivers/scsi/sata_sil24.c | 3 +- include/linux/libata.h | 24 +++++++++---- 6 files changed, 165 insertions(+), 21 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 45fd71d80128..8493b021cc07 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -1026,7 +1026,8 @@ static void ahci_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset); + ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, + ahci_postreset); } static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 6d30d2c52960..4bc05371737c 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -695,6 +695,7 @@ void ata_bmdma_thaw(struct ata_port *ap) /** * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller * @ap: port to handle error for + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -710,8 +711,9 @@ void ata_bmdma_thaw(struct ata_port *ap) * LOCKING: * Kernel thread context (may sleep) */ -void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) { struct ata_host_set *host_set = ap->host_set; struct ata_eh_context *ehc = &ap->eh_context; @@ -759,7 +761,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, ata_eh_thaw_port(ap); /* PIO and DMA engines have been stopped, perform recovery */ - ata_do_eh(ap, softreset, hardreset, postreset); + ata_do_eh(ap, prereset, softreset, hardreset, postreset); } /** @@ -779,7 +781,8 @@ void ata_bmdma_error_handler(struct ata_port *ap) if (sata_scr_valid(ap)) hardreset = sata_std_hardreset; - ata_bmdma_drive_eh(ap, ata_std_softreset, hardreset, ata_std_postreset); + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, + ata_std_postreset); } /** diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4823ecefb8a1..2531a701d6e9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2525,6 +2525,90 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params) return sata_phy_debounce(ap, params); } +static void ata_wait_spinup(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned long end, secs; + int rc; + + /* first, debounce phy if SATA */ + if (ap->cbl == ATA_CBL_SATA) { + rc = sata_phy_debounce(ap, sata_deb_timing_eh); + + /* if debounced successfully and offline, no need to wait */ + if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap)) + return; + } + + /* okay, let's give the drive time to spin up */ + end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000; + secs = ((end - jiffies) + HZ - 1) / HZ; + + if (time_after(jiffies, end)) + return; + + if (secs > 5) + ata_port_printk(ap, KERN_INFO, "waiting for device to spin up " + "(%lu secs)\n", secs); + + schedule_timeout_uninterruptible(end - jiffies); +} + +/** + * ata_std_prereset - prepare for reset + * @ap: ATA port to be reset + * + * @ap is about to be reset. Initialize it. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_prereset(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const unsigned long *timing; + int rc; + + /* hotplug? */ + if (ehc->i.flags & ATA_EHI_HOTPLUGGED) { + if (ap->flags & ATA_FLAG_HRST_TO_RESUME) + ehc->i.action |= ATA_EH_HARDRESET; + if (ap->flags & ATA_FLAG_SKIP_D2H_BSY) + ata_wait_spinup(ap); + } + + /* if we're about to do hardreset, nothing more to do */ + if (ehc->i.action & ATA_EH_HARDRESET) + return 0; + + /* if SATA, resume phy */ + if (ap->cbl == ATA_CBL_SATA) { + if (ap->flags & ATA_FLAG_LOADING) + timing = sata_deb_timing_boot; + else + timing = sata_deb_timing_eh; + + rc = sata_phy_resume(ap, timing); + if (rc && rc != -EOPNOTSUPP) { + /* phy resume failed */ + ata_port_printk(ap, KERN_WARNING, "failed to resume " + "link for reset (errno=%d)\n", rc); + return rc; + } + } + + /* Wait for !BSY if the controller can wait for the first D2H + * Reg FIS and we don't know that no device is attached. + */ + if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + return 0; +} + /** * ata_std_probeinit - initialize probing * @ap: port to be probed @@ -5840,6 +5924,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_probeinit); +EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 9173d8f2ce5d..0e66f140e53b 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1318,20 +1318,58 @@ static void ata_eh_report(struct ata_port *ap) } } -static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, +static int ata_eh_reset(struct ata_port *ap, + ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_eh_context *ehc = &ap->eh_context; unsigned int classes[ATA_MAX_DEVICES]; int tries = ATA_EH_RESET_TRIES; + unsigned int action; ata_reset_fn_t reset; int i, rc; + /* Determine which reset to use and record in ehc->i.action. + * prereset() may examine and modify it. + */ + action = ehc->i.action; + ehc->i.action &= ~ATA_EH_RESET_MASK; if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && - !(ehc->i.action & ATA_EH_HARDRESET)))) - reset = softreset; + !(action & ATA_EH_HARDRESET)))) + ehc->i.action |= ATA_EH_SOFTRESET; else + ehc->i.action |= ATA_EH_HARDRESET; + + if (prereset) { + rc = prereset(ap); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "prereset failed (errno=%d)\n", rc); + return rc; + } + } + + /* prereset() might have modified ehc->i.action */ + if (ehc->i.action & ATA_EH_HARDRESET) reset = hardreset; + else if (ehc->i.action & ATA_EH_SOFTRESET) + reset = softreset; + else { + /* prereset told us not to reset, bang classes and return */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_NONE; + return 0; + } + + /* did prereset() screw up? if so, fix up to avoid oopsing */ + if (!reset) { + ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested " + "invalid reset type\n"); + if (softreset) + reset = softreset; + else + reset = hardreset; + } retry: ata_port_printk(ap, KERN_INFO, "%s resetting port\n", @@ -1424,6 +1462,7 @@ static int ata_port_nr_enabled(struct ata_port *ap) /** * ata_eh_recover - recover host port after error * @ap: host port to recover + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -1440,8 +1479,8 @@ static int ata_port_nr_enabled(struct ata_port *ap) * RETURNS: * 0 on success, -errno on failure. */ -static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, +static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_eh_context *ehc = &ap->eh_context; @@ -1469,7 +1508,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, if (ehc->i.action & ATA_EH_RESET_MASK) { ata_eh_freeze_port(ap); - rc = ata_eh_reset(ap, softreset, hardreset, postreset); + rc = ata_eh_reset(ap, prereset, softreset, hardreset, + postreset); if (rc) { ata_port_printk(ap, KERN_ERR, "reset failed, giving up\n"); @@ -1586,6 +1626,7 @@ static void ata_eh_finish(struct ata_port *ap) /** * ata_do_eh - do standard error handling * @ap: host port to handle error for + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -1595,11 +1636,12 @@ static void ata_eh_finish(struct ata_port *ap) * LOCKING: * Kernel thread context (may sleep). */ -void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) { ata_eh_autopsy(ap); ata_eh_report(ap); - ata_eh_recover(ap, softreset, hardreset, postreset); + ata_eh_recover(ap, prereset, softreset, hardreset, postreset); ata_eh_finish(ap); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4c76f05d9b65..26d7c54c175e 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -912,7 +912,8 @@ static void sil24_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset); + ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, + ata_std_postreset); } static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/include/linux/libata.h b/include/linux/libata.h index 1c167f728fb4..fe5f53943c44 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -262,6 +262,15 @@ enum { ATA_PROBE_MAX_TRIES = 3, ATA_EH_RESET_TRIES = 3, ATA_EH_DEV_TRIES = 3, + + /* Drive spinup time (time from power-on to the first D2H FIS) + * in msecs - 8s currently. Failing to get ready in this time + * isn't critical. It will result in reset failure for + * controllers which can't wait for the first D2H FIS. libata + * will retry, so it just has to be long enough to spin up + * most devices. + */ + ATA_SPINUP_WAIT = 8000, }; enum hsm_task_states { @@ -294,9 +303,10 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); -typedef void (*ata_probeinit_fn_t)(struct ata_port *); -typedef int (*ata_reset_fn_t)(struct ata_port *, unsigned int *); -typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); +typedef void (*ata_probeinit_fn_t)(struct ata_port *ap); +typedef int (*ata_prereset_fn_t)(struct ata_port *ap); +typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes); +typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes); struct ata_ioports { unsigned long cmd_addr; @@ -623,6 +633,7 @@ extern int ata_drive_probe_reset(struct ata_port *ap, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_std_probeinit(struct ata_port *ap); +extern int ata_std_prereset(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); @@ -706,7 +717,7 @@ extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_freeze(struct ata_port *ap); extern void ata_bmdma_thaw(struct ata_port *ap); -extern void ata_bmdma_drive_eh(struct ata_port *ap, +extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); @@ -784,8 +795,9 @@ extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -extern void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); +extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset); /* * printk helpers -- cgit v1.2.3 From ccf68c3405fca11386004674377d951b9b18e756 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:09 +0900 Subject: [PATCH] libata-hp: hook warmplug Hook transportt->user_scan() and hostt->slave_destroy(). Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 1 + drivers/scsi/ata_piix.c | 1 + drivers/scsi/libata-scsi.c | 1 + drivers/scsi/pdc_adma.c | 1 + drivers/scsi/sata_mv.c | 1 + drivers/scsi/sata_nv.c | 1 + drivers/scsi/sata_promise.c | 1 + drivers/scsi/sata_qstor.c | 1 + drivers/scsi/sata_sil.c | 1 + drivers/scsi/sata_sil24.c | 1 + drivers/scsi/sata_sis.c | 1 + drivers/scsi/sata_svw.c | 1 + drivers/scsi/sata_sx4.c | 1 + drivers/scsi/sata_uli.c | 1 + drivers/scsi/sata_via.c | 1 + drivers/scsi/sata_vsc.c | 1 + 16 files changed, 16 insertions(+) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 8493b021cc07..afb3805f9e95 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -228,6 +228,7 @@ static struct scsi_host_template ahci_sht = { .proc_name = DRV_NAME, .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index ad41dfd33e06..54c2e52373fd 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -219,6 +219,7 @@ static struct scsi_host_template piix_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 7c1ac58c430a..5f90d8e33546 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { struct scsi_transport_template ata_scsi_transport_template = { .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, + .user_scan = ata_scsi_user_scan, }; diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index a341fa8d3291..eb910e4c7d75 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -152,6 +152,7 @@ static struct scsi_host_template adma_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = ADMA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 624983c2e24b..634bab17a6bb 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht = { .proc_name = DRV_NAME, .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index d93513ef7412..90551246aa46 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -216,6 +216,7 @@ static struct scsi_host_template nv_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 01111594d09c..b2b6ed5216e0 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -121,6 +121,7 @@ static struct scsi_host_template pdc_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 68737cadd2d4..98ddc25655f0 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 03c1d1b1a04c..7d43cd3a50fc 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -174,6 +174,7 @@ static struct scsi_host_template sil_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4a830903393d..d4ca6d6b402c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -370,6 +370,7 @@ static struct scsi_host_template sil24_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 82a07bff7e91..a07e6e525173 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 7a4703bfa12a..d9b516836486 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, #ifdef CONFIG_PPC_OF .proc_info = k2_sata_proc_info, #endif diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index c4db6bf14a25..7f864410f7c2 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 7fae3e06e461..e69ba229adca 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 1c9e2f36805a..c6975c5580ef 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -103,6 +103,7 @@ static struct scsi_host_template svia_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 438e7c6a0f8f..22ca7b848cf6 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -279,6 +279,7 @@ static struct scsi_host_template vsc_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; -- cgit v1.2.3 From 720ba12620ee09dce269adf4ad50958adac7bb54 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:13 +0900 Subject: [PATCH] libata-hp: update unload-unplug Update unload unplug - driver unloading / PCI removal. This is done by ata_port_detach() which short-circuits EH, disables all devices and freezes the port. With this patch, EH and unloading/unplugging are properly synchronized. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 10 +++---- drivers/scsi/libata-core.c | 67 +++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/libata-eh.c | 8 ++++-- include/linux/libata.h | 1 + 4 files changed, 71 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index afb3805f9e95..60f455bf3696 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -1389,21 +1389,17 @@ static void ahci_remove_one (struct pci_dev *pdev) struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host_set->private_data; - struct ata_port *ap; unsigned int i; int have_msi; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); have_msi = hpriv->flags & AHCI_FLAG_MSI; free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); scsi_host_put(ap->host); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a42877e6b865..01f2c59536bc 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5609,6 +5609,63 @@ err_free_ret: return 0; } +/** + * ata_port_detach - Detach ATA port in prepration of device removal + * @ap: ATA port to be detached + * + * Detach all ATA devices and the associated SCSI devices of @ap; + * then, remove the associated SCSI host. @ap is guaranteed to + * be quiescent on return from this function. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_detach(struct ata_port *ap) +{ + unsigned long flags; + int i; + + if (!ap->ops->error_handler) + return; + + /* tell EH we're leaving & flush EH */ + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_UNLOADING; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_port_wait_eh(ap); + + /* EH is now guaranteed to see UNLOADING, so no new device + * will be attached. Disable all existing devices. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* Final freeze & EH. All in-flight commands are aborted. EH + * will be skipped and retrials will be terminated with bad + * target. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + ata_port_freeze(ap); /* won't be thawed */ + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_port_wait_eh(ap); + + /* Flush hotplug task. The sequence is similar to + * ata_port_flush_task(). + */ + flush_workqueue(ata_aux_wq); + cancel_delayed_work(&ap->hotplug_task); + flush_workqueue(ata_aux_wq); + + /* remove the associated SCSI host */ + scsi_remove_host(ap->host); +} + /** * ata_host_set_remove - PCI layer callback for device removal * @host_set: ATA host set that was removed @@ -5622,18 +5679,15 @@ err_free_ret: void ata_host_set_remove(struct ata_host_set *host_set) { - struct ata_port *ap; unsigned int i; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); @@ -5901,6 +5955,7 @@ EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_port_detach); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 70c132bef68e..30a83a57a12f 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -46,6 +46,7 @@ #include "libata.h" static void __ata_port_freeze(struct ata_port *ap); +static void ata_eh_finish(struct ata_port *ap); static void ata_ering_record(struct ata_ering *ering, int is_io, unsigned int err_mask) @@ -242,8 +243,11 @@ void ata_scsi_error(struct Scsi_Host *host) spin_unlock_irqrestore(hs_lock, flags); - /* invoke EH */ - ap->ops->error_handler(ap); + /* invoke EH. if unloading, just finish failed qcs */ + if (!(ap->flags & ATA_FLAG_UNLOADING)) + ap->ops->error_handler(ap); + else + ata_eh_finish(ap); /* Exception might have happend after ->error_handler * recovered the port but before this point. Repeat diff --git a/include/linux/libata.h b/include/linux/libata.h index 74786c33c526..f11ba2715bef 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -649,6 +649,7 @@ extern int ata_pci_device_resume(struct pci_dev *pdev); extern int ata_pci_clear_simplex(struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); +extern void ata_port_detach(struct ata_port *ap); extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); -- cgit v1.2.3 From 4296971dd36e2c2deae0826305f591480223af88 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:18 +0900 Subject: [PATCH] ahci: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY, marking ehi for hotplug and scheduling EH on CONNECT/PHYRDY interrupts. Unfortunately, ahci cannot reliably wait for the first D2H FIS after hotplug. It sometimes succeeds but times out more often than not, so ATA_FLAG_SKIP_D2H_BSY is used. This patch also fixes ahci_hardreset() such that D2H Register FIS RX area is cleared before issuing COMRESET. Without this, ata_busy_sleep() after COMRESET might prematually finish if the previous TF contains DRDY && !BSY. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 60f455bf3696..e261b37c2e48 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -136,6 +136,7 @@ enum { PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_CONNECT | + PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS, PORT_IRQ_ERROR = PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | @@ -200,7 +201,6 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); static void ahci_irq_clear(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); @@ -241,8 +241,6 @@ static const struct ata_port_operations ahci_ops = { .tf_read = ahci_tf_read, - .probe_reset = ahci_probe_reset, - .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, @@ -267,7 +265,8 @@ static const struct ata_port_info ahci_port_info[] = { { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -277,6 +276,7 @@ static const struct ata_port_info ahci_port_info[] = { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_RESET_NEEDS_CLO, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -569,6 +569,17 @@ static int ahci_clo(struct ata_port *ap) return 0; } +static int ahci_prereset(struct ata_port *ap) +{ + if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && + (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { + /* ATA_BUSY hasn't cleared, so send a CLO */ + ahci_clo(ap); + } + + return ata_std_prereset(ap); +} + static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_port_priv *pp = ap->private_data; @@ -678,12 +689,22 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { + struct ahci_port_priv *pp = ap->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(ap->device, &tf); + tf.command = 0xff; + ata_tf_to_fis(&tf, d2h_fis, 0); + rc = sata_std_hardreset(ap, class); + ahci_start_engine(ap); if (rc == 0 && ata_port_online(ap)) @@ -714,19 +735,6 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) } } -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && - (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { - /* ATA_BUSY hasn't cleared, so send a CLO */ - ahci_clo(ap); - } - - return ata_drive_probe_reset(ap, ata_std_probeinit, - ahci_softreset, ahci_hardreset, - ahci_postreset, classes); -} - static u8 ahci_check_status(struct ata_port *ap) { void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -839,8 +847,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) } if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { - err_mask |= AC_ERR_ATA_BUS; - action |= ATA_EH_SOFTRESET; + ata_ehi_hotplugged(ehi); ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? "connection status changed" : "PHY RDY changed"); } @@ -1027,7 +1034,7 @@ static void ahci_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, + ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, ahci_postreset); } -- cgit v1.2.3 From fe7fa31aa0749d7d247d21e1880f0c5aea15b158 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:05:36 -0400 Subject: [libata] ahci: Add NVIDIA PCI IDs. Based on a patch by Andrew Chew @ NVIDIA. Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index e261b37c2e48..82ecdef0c48b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -285,6 +285,7 @@ static const struct ata_port_info ahci_port_info[] = { }; static const struct pci_device_id ahci_pci_tbl[] = { + /* Intel */ { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH6 */ { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -315,16 +316,33 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* ICH8M */ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH8M */ + + /* JMicron */ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB360 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + + /* ATI */ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 non-raid */ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 raid */ + + /* VIA */ { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci_vt8251 }, /* VIA VT8251 */ + + /* NVIDIA */ + { PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { } /* terminate list */ }; -- cgit v1.2.3 From 8fa29b23d9e0ef976dc578aab98297d4f24f70da Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:19:15 -0400 Subject: [libata] ahci: add JMicron PCI IDs Originally contributed by Justin @ JMicron. Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 82ecdef0c48b..df779ba8749d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -320,8 +320,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* JMicron */ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB360 */ + { 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB361 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + { 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB365 */ + { 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB366 */ /* ATI */ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- cgit v1.2.3 From 71f0737b2889b86f774a94afaf1342c2c0d61cb5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jun 2006 23:12:48 +0900 Subject: [PATCH] ahci: disable NCQ support on vt8251 vt8251 chokes on NCQ commands. Two different disks from different vendors are showing the same symptom and it seems that the windows driver from via doesn't support NCQ either. Disable NCQ support on this controller for the time being. Signed-off-by: Tejun Heo Cc: Aalderd Bouwman Cc: Bastiaan Jacques Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/ahci.c') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index df779ba8749d..4bb77f62b3b9 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -164,6 +164,7 @@ enum { /* ap->flags bits */ AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), + AHCI_FLAG_NO_NCQ = (1 << 25), }; struct ahci_cmd_hdr { @@ -277,7 +278,7 @@ static const struct ata_port_info ahci_port_info[] = { .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY | - AHCI_FLAG_RESET_NEEDS_CLO, + AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -1386,7 +1387,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_hpriv; - if (hpriv->cap & HOST_CAP_NCQ) + if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) && + (hpriv->cap & HOST_CAP_NCQ)) probe_ent->host_flags |= ATA_FLAG_NCQ; ahci_print_info(probe_ent); -- cgit v1.2.3