forked from Minki/linux
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 <htejun@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
bf1bff6fa9
commit
f1bbfb90e8
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user