diff options
-rw-r--r-- | drivers/ata/sata_highbank.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index b20aa96b958d..c846fd3c5c09 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c | |||
@@ -196,10 +196,26 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr) | |||
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | 198 | ||
199 | /* | ||
200 | * The Calxeda SATA phy intermittently fails to bring up a link with Gen3 | ||
201 | * Retrying the phy hard reset can work around the issue, but the drive | ||
202 | * may fail again. In less than 150 out of 15000 test runs, it took more | ||
203 | * than 10 tries for the link to be established (but never more than 35). | ||
204 | * Triple the maximum observed retry count to provide plenty of margin for | ||
205 | * rare events and to guarantee that the link is established. | ||
206 | * | ||
207 | * Also, the default 2 second time-out on a failed drive is too long in | ||
208 | * this situation. The uboot implementation of the same driver function | ||
209 | * uses a much shorter time-out period and never experiences a time out | ||
210 | * issue. Reducing the time-out to 500ms improves the responsiveness. | ||
211 | * The other timing constants were kept the same as the stock AHCI driver. | ||
212 | * This change was also tested 15000 times on 24 drives and none of them | ||
213 | * experienced a time out. | ||
214 | */ | ||
199 | static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, | 215 | static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, |
200 | unsigned long deadline) | 216 | unsigned long deadline) |
201 | { | 217 | { |
202 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | 218 | static const unsigned long timing[] = { 5, 100, 500}; |
203 | struct ata_port *ap = link->ap; | 219 | struct ata_port *ap = link->ap; |
204 | struct ahci_port_priv *pp = ap->private_data; | 220 | struct ahci_port_priv *pp = ap->private_data; |
205 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 221 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; |
@@ -207,7 +223,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, | |||
207 | bool online; | 223 | bool online; |
208 | u32 sstatus; | 224 | u32 sstatus; |
209 | int rc; | 225 | int rc; |
210 | int retry = 10; | 226 | int retry = 100; |
211 | 227 | ||
212 | ahci_stop_engine(ap); | 228 | ahci_stop_engine(ap); |
213 | 229 | ||