diff options
Diffstat (limited to 'drivers/ata/libata-pmp.c')
-rw-r--r-- | drivers/ata/libata-pmp.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index ff1822a7da38..7daf4c0f6216 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) | |||
48 | tf.device = link->pmp; | 48 | tf.device = link->pmp; |
49 | 49 | ||
50 | err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, | 50 | err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, |
51 | SATA_PMP_SCR_TIMEOUT); | 51 | SATA_PMP_RW_TIMEOUT); |
52 | if (err_mask) | 52 | if (err_mask) |
53 | return err_mask; | 53 | return err_mask; |
54 | 54 | ||
@@ -88,7 +88,7 @@ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val) | |||
88 | tf.lbah = (val >> 24) & 0xff; | 88 | tf.lbah = (val >> 24) & 0xff; |
89 | 89 | ||
90 | return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, | 90 | return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, |
91 | SATA_PMP_SCR_TIMEOUT); | 91 | SATA_PMP_RW_TIMEOUT); |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
@@ -257,19 +257,6 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) | |||
257 | goto fail; | 257 | goto fail; |
258 | } | 258 | } |
259 | 259 | ||
260 | /* turn off notification till fan-out ports are reset and configured */ | ||
261 | if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) { | ||
262 | gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY; | ||
263 | |||
264 | err_mask = sata_pmp_write(dev->link, SATA_PMP_GSCR_FEAT_EN, | ||
265 | gscr[SATA_PMP_GSCR_FEAT_EN]); | ||
266 | if (err_mask) { | ||
267 | rc = -EIO; | ||
268 | reason = "failed to write GSCR_FEAT_EN"; | ||
269 | goto fail; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | if (print_info) { | 260 | if (print_info) { |
274 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " | 261 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " |
275 | "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", | 262 | "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", |
@@ -335,9 +322,12 @@ static void sata_pmp_quirks(struct ata_port *ap) | |||
335 | if (vendor == 0x1095 && devid == 0x3726) { | 322 | if (vendor == 0x1095 && devid == 0x3726) { |
336 | /* sil3726 quirks */ | 323 | /* sil3726 quirks */ |
337 | ata_port_for_each_link(link, ap) { | 324 | ata_port_for_each_link(link, ap) { |
338 | /* class code report is unreliable */ | 325 | /* Class code report is unreliable and SRST |
326 | * times out under certain configurations. | ||
327 | */ | ||
339 | if (link->pmp < 5) | 328 | if (link->pmp < 5) |
340 | link->flags |= ATA_LFLAG_ASSUME_ATA; | 329 | link->flags |= ATA_LFLAG_NO_SRST | |
330 | ATA_LFLAG_ASSUME_ATA; | ||
341 | 331 | ||
342 | /* port 5 is for SEMB device and it doesn't like SRST */ | 332 | /* port 5 is for SEMB device and it doesn't like SRST */ |
343 | if (link->pmp == 5) | 333 | if (link->pmp == 5) |
@@ -700,8 +690,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, | |||
700 | if (ehc->i.action & ATA_EH_RESET) { | 690 | if (ehc->i.action & ATA_EH_RESET) { |
701 | struct ata_link *tlink; | 691 | struct ata_link *tlink; |
702 | 692 | ||
703 | ata_eh_freeze_port(ap); | ||
704 | |||
705 | /* reset */ | 693 | /* reset */ |
706 | rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, | 694 | rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, |
707 | postreset); | 695 | postreset); |
@@ -711,8 +699,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, | |||
711 | goto fail; | 699 | goto fail; |
712 | } | 700 | } |
713 | 701 | ||
714 | ata_eh_thaw_port(ap); | ||
715 | |||
716 | /* PMP is reset, SErrors cannot be trusted, scan all */ | 702 | /* PMP is reset, SErrors cannot be trusted, scan all */ |
717 | ata_port_for_each_link(tlink, ap) { | 703 | ata_port_for_each_link(tlink, ap) { |
718 | struct ata_eh_context *ehc = &tlink->eh_context; | 704 | struct ata_eh_context *ehc = &tlink->eh_context; |
@@ -864,6 +850,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) | |||
864 | struct ata_link *pmp_link = &ap->link; | 850 | struct ata_link *pmp_link = &ap->link; |
865 | struct ata_device *pmp_dev = pmp_link->device; | 851 | struct ata_device *pmp_dev = pmp_link->device; |
866 | struct ata_eh_context *pmp_ehc = &pmp_link->eh_context; | 852 | struct ata_eh_context *pmp_ehc = &pmp_link->eh_context; |
853 | u32 *gscr = pmp_dev->gscr; | ||
867 | struct ata_link *link; | 854 | struct ata_link *link; |
868 | struct ata_device *dev; | 855 | struct ata_device *dev; |
869 | unsigned int err_mask; | 856 | unsigned int err_mask; |
@@ -901,6 +888,22 @@ static int sata_pmp_eh_recover(struct ata_port *ap) | |||
901 | if (rc) | 888 | if (rc) |
902 | goto pmp_fail; | 889 | goto pmp_fail; |
903 | 890 | ||
891 | /* PHY event notification can disturb reset and other recovery | ||
892 | * operations. Turn it off. | ||
893 | */ | ||
894 | if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) { | ||
895 | gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY; | ||
896 | |||
897 | err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN, | ||
898 | gscr[SATA_PMP_GSCR_FEAT_EN]); | ||
899 | if (err_mask) { | ||
900 | ata_link_printk(pmp_link, KERN_WARNING, | ||
901 | "failed to disable NOTIFY (err_mask=0x%x)\n", | ||
902 | err_mask); | ||
903 | goto pmp_fail; | ||
904 | } | ||
905 | } | ||
906 | |||
904 | /* handle disabled links */ | 907 | /* handle disabled links */ |
905 | rc = sata_pmp_eh_handle_disabled_links(ap); | 908 | rc = sata_pmp_eh_handle_disabled_links(ap); |
906 | if (rc) | 909 | if (rc) |
@@ -923,10 +926,10 @@ static int sata_pmp_eh_recover(struct ata_port *ap) | |||
923 | 926 | ||
924 | /* enable notification */ | 927 | /* enable notification */ |
925 | if (pmp_dev->flags & ATA_DFLAG_AN) { | 928 | if (pmp_dev->flags & ATA_DFLAG_AN) { |
926 | pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; | 929 | gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; |
927 | 930 | ||
928 | err_mask = sata_pmp_write(pmp_dev->link, SATA_PMP_GSCR_FEAT_EN, | 931 | err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN, |
929 | pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN]); | 932 | gscr[SATA_PMP_GSCR_FEAT_EN]); |
930 | if (err_mask) { | 933 | if (err_mask) { |
931 | ata_dev_printk(pmp_dev, KERN_ERR, "failed to write " | 934 | ata_dev_printk(pmp_dev, KERN_ERR, "failed to write " |
932 | "PMP_FEAT_EN (Emask=0x%x)\n", err_mask); | 935 | "PMP_FEAT_EN (Emask=0x%x)\n", err_mask); |