Commit f1bbfb90 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

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: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent bf1bff6f
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment