From dc98c32cbe80750ae2d9d9fbdae305d38f005de7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 May 2008 01:15:07 +0900 Subject: libata: move reset freeze/thaw handling into ata_eh_reset() Previously reset freeze/thaw handling lived outside of ata_eh_reset() mainly because the original PMP reset code needed the port frozen while resetting all the fan-out ports, which is no longer the case. This patch moves freeze/thaw handling into ata_eh_reset(). @prereset() and @postreset() are now called w/o freezing the port although @prereset() an be called frozen if the port is frozen prior to entering ata_eh_reset(). This makes code simpler and will help removing hotplug event related races. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-pmp.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/ata/libata-pmp.c') diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index ff1822a7da38..f3ad024394c2 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -700,8 +700,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, if (ehc->i.action & ATA_EH_RESET) { struct ata_link *tlink; - ata_eh_freeze_port(ap); - /* reset */ rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, postreset); @@ -711,8 +709,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, goto fail; } - ata_eh_thaw_port(ap); - /* PMP is reset, SErrors cannot be trusted, scan all */ ata_port_for_each_link(tlink, ap) { struct ata_eh_context *ehc = &tlink->eh_context; -- cgit v1.2.3 From bf1bff6fa9fdd4e92e57d80a5434fd5201c051fc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 May 2008 01:15:10 +0900 Subject: libata: increase PMP register access timeout to 3s This timeout was set low because previously PMP register access was done via polling and register access timeouts could stack up. This is no longer the case. One timeout will make all following accesses fail immediately. In rare cases both marvell and SIMG PMPs need almost a second. Bump it to 3s. While at it, rename it to SATA_PMP_RW_TIMEOUT. It's not specific to SCR access. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-pmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-pmp.c') diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index f3ad024394c2..04a486a3e7b8 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -48,7 +48,7 @@ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val) tf.device = link->pmp; err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, - SATA_PMP_SCR_TIMEOUT); + SATA_PMP_RW_TIMEOUT); if (err_mask) return err_mask; @@ -88,7 +88,7 @@ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val) tf.lbah = (val >> 24) & 0xff; return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, - SATA_PMP_SCR_TIMEOUT); + SATA_PMP_RW_TIMEOUT); } /** -- cgit v1.2.3 From f1bbfb90e81dd84d59de6370689ee6fe6a71fee0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 May 2008 01:15:11 +0900 Subject: libata: make sure PMP notification is turned off during recovery PMP notification during reset can make some controllers fail reset processing and needs to be turned off during resets. PMP attach and full-revalidation path did this via sata_pmp_configure() but the quick revalidation wasn't. Move the notification disable code right above fan-out port recovery so that it's always turned off. This fixes obscure reset failures. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-pmp.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/ata/libata-pmp.c') diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 04a486a3e7b8..0f9386d4a5a0 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -257,19 +257,6 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) goto fail; } - /* turn off notification till fan-out ports are reset and configured */ - if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) { - gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY; - - err_mask = sata_pmp_write(dev->link, SATA_PMP_GSCR_FEAT_EN, - gscr[SATA_PMP_GSCR_FEAT_EN]); - if (err_mask) { - rc = -EIO; - reason = "failed to write GSCR_FEAT_EN"; - goto fail; - } - } - if (print_info) { ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", @@ -860,6 +847,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) struct ata_link *pmp_link = &ap->link; struct ata_device *pmp_dev = pmp_link->device; struct ata_eh_context *pmp_ehc = &pmp_link->eh_context; + u32 *gscr = pmp_dev->gscr; struct ata_link *link; struct ata_device *dev; unsigned int err_mask; @@ -897,6 +885,22 @@ static int sata_pmp_eh_recover(struct ata_port *ap) if (rc) goto pmp_fail; + /* PHY event notification can disturb reset and other recovery + * operations. Turn it off. + */ + if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) { + gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY; + + err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN, + gscr[SATA_PMP_GSCR_FEAT_EN]); + if (err_mask) { + ata_link_printk(pmp_link, KERN_WARNING, + "failed to disable NOTIFY (err_mask=0x%x)\n", + err_mask); + goto pmp_fail; + } + } + /* handle disabled links */ rc = sata_pmp_eh_handle_disabled_links(ap); if (rc) @@ -919,10 +923,10 @@ static int sata_pmp_eh_recover(struct ata_port *ap) /* enable notification */ if (pmp_dev->flags & ATA_DFLAG_AN) { - pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; + gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; - err_mask = sata_pmp_write(pmp_dev->link, SATA_PMP_GSCR_FEAT_EN, - pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN]); + err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN, + gscr[SATA_PMP_GSCR_FEAT_EN]); if (err_mask) { ata_dev_printk(pmp_dev, KERN_ERR, "failed to write " "PMP_FEAT_EN (Emask=0x%x)\n", err_mask); -- cgit v1.2.3 From 19ef9d5e45ce805700f34c248a71a511877b8a5d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 May 2008 14:11:24 +0900 Subject: libata: SRST can't be trusted on PMP sil3726 As in sil4726, SRST can't be trusted on sil3726 causing detection problems under certain configuraitons. I thought it was from the Config Disk device but apparently not. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-pmp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-pmp.c') diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 0f9386d4a5a0..7daf4c0f6216 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -322,9 +322,12 @@ static void sata_pmp_quirks(struct ata_port *ap) if (vendor == 0x1095 && devid == 0x3726) { /* sil3726 quirks */ ata_port_for_each_link(link, ap) { - /* class code report is unreliable */ + /* Class code report is unreliable and SRST + * times out under certain configurations. + */ if (link->pmp < 5) - link->flags |= ATA_LFLAG_ASSUME_ATA; + link->flags |= ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; /* port 5 is for SEMB device and it doesn't like SRST */ if (link->pmp == 5) -- cgit v1.2.3