Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 130815
b: refs/heads/master
c: c2c7a89
h: refs/heads/master
i:
  130813: 83e4d2e
  130811: f6cee81
  130807: 2b71bb0
  130799: 684f09e
  130783: 719f019
  130751: 4b63be3
  130687: b1ab60a
  130559: 8813e85
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Feb 3, 2009
1 parent 6f3eb2d commit 2fdfc7c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a07d499b4759881db1359dd8812eecd00b0e0a28
refs/heads/master: c2c7a89c5eabaea8c0c2aa0c1069e510144513ab
38 changes: 38 additions & 0 deletions trunk/drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ enum {
ATA_EH_FASTDRAIN_INTERVAL = 3000,

ATA_EH_UA_TRIES = 5,

/* probe speed down parameters, see ata_eh_schedule_probe() */
ATA_EH_PROBE_TRIAL_INTERVAL = 60000, /* 1 min */
ATA_EH_PROBE_TRIALS = 2,
};

/* The following table determines how we sequence resets. Each entry
Expand Down Expand Up @@ -2975,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
return 1;
}

static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg)
{
u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL);
u64 now = get_jiffies_64();
int *trials = void_arg;

if (ent->timestamp < now - min(now, interval))
return -1;

(*trials)++;
return 0;
}

static int ata_eh_schedule_probe(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
struct ata_link *link = ata_dev_phys_link(dev);
int trials = 0;

if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
(ehc->did_probe_mask & (1 << dev->devno)))
Expand All @@ -2990,6 +3009,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
ehc->saved_xfer_mode[dev->devno] = 0;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);

/* Record and count probe trials on the ering. The specific
* error mask used is irrelevant. Because a successful device
* detection clears the ering, this count accumulates only if
* there are consecutive failed probes.
*
* If the count is equal to or higher than ATA_EH_PROBE_TRIALS
* in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is
* forced to 1.5Gbps.
*
* This is to work around cases where failed link speed
* negotiation results in device misdetection leading to
* infinite DEVXCHG or PHRDY CHG events.
*/
ata_ering_record(&dev->ering, 0, AC_ERR_OTHER);
ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials);

if (trials > ATA_EH_PROBE_TRIALS)
sata_down_spd_limit(link, 1);

return 1;
}

Expand Down

0 comments on commit 2fdfc7c

Please sign in to comment.