|
@@ -3790,21 +3790,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
|
|
|
int sata_link_resume(struct ata_link *link, const unsigned long *params,
|
|
|
unsigned long deadline)
|
|
|
{
|
|
|
+ int tries = ATA_LINK_RESUME_TRIES;
|
|
|
u32 scontrol, serror;
|
|
|
int rc;
|
|
|
|
|
|
if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
|
|
|
return rc;
|
|
|
|
|
|
- scontrol = (scontrol & 0x0f0) | 0x300;
|
|
|
+ /*
|
|
|
+ * Writes to SControl sometimes get ignored under certain
|
|
|
+ * controllers (ata_piix SIDPR). Make sure DET actually is
|
|
|
+ * cleared.
|
|
|
+ */
|
|
|
+ do {
|
|
|
+ scontrol = (scontrol & 0x0f0) | 0x300;
|
|
|
+ if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
|
|
|
+ return rc;
|
|
|
+ /*
|
|
|
+ * Some PHYs react badly if SStatus is pounded
|
|
|
+ * immediately after resuming. Delay 200ms before
|
|
|
+ * debouncing.
|
|
|
+ */
|
|
|
+ msleep(200);
|
|
|
|
|
|
- if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
|
|
|
- return rc;
|
|
|
+ /* is SControl restored correctly? */
|
|
|
+ if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
|
|
|
+ return rc;
|
|
|
+ } while ((scontrol & 0xf0f) != 0x300 && --tries);
|
|
|
|
|
|
- /* Some PHYs react badly if SStatus is pounded immediately
|
|
|
- * after resuming. Delay 200ms before debouncing.
|
|
|
- */
|
|
|
- msleep(200);
|
|
|
+ if ((scontrol & 0xf0f) != 0x300) {
|
|
|
+ ata_link_printk(link, KERN_ERR,
|
|
|
+ "failed to resume link (SControl %X)\n",
|
|
|
+ scontrol);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tries < ATA_LINK_RESUME_TRIES)
|
|
|
+ ata_link_printk(link, KERN_WARNING,
|
|
|
+ "link resume succeeded after %d retries\n",
|
|
|
+ ATA_LINK_RESUME_TRIES - tries);
|
|
|
|
|
|
if ((rc = sata_link_debounce(link, params, deadline)))
|
|
|
return rc;
|