Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 55131
b: refs/heads/master
c: 31daabd
h: refs/heads/master
i:
  55129: 00448d2
  55127: 0943c55
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed May 1, 2007
1 parent aaabc38 commit 097009a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 68 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b8cffc6ad8c000410186815b7bcc6b76ef1bbb13
refs/heads/master: 31daabda16063b64a99a526242add727601e43c3
35 changes: 1 addition & 34 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3304,35 +3304,6 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params,
return sata_phy_debounce(ap, params, deadline);
}

static void ata_wait_spinup(struct ata_port *ap, unsigned long deadline)
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned long end, secs;
int rc;

/* first, debounce phy if SATA */
if (ap->cbl == ATA_CBL_SATA) {
rc = sata_phy_debounce(ap, sata_deb_timing_hotplug, deadline);

/* if debounced successfully and offline, no need to wait */
if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
return;
}

/* okay, let's give the drive time to spin up */
end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
secs = ((end - jiffies) + HZ - 1) / HZ;

if (time_after(jiffies, end))
return;

if (secs > 5)
ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
"(%lu secs)\n", secs);

schedule_timeout_uninterruptible(end - jiffies);
}

/**
* ata_std_prereset - prepare for reset
* @ap: ATA port to be reset
Expand All @@ -3356,15 +3327,11 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
const unsigned long *timing = sata_ehc_deb_timing(ehc);
int rc;

/* handle link resume & hotplug spinup */
/* handle link resume */
if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
(ap->flags & ATA_FLAG_HRST_TO_RESUME))
ehc->i.action |= ATA_EH_HARDRESET;

if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
(ap->flags & ATA_FLAG_SKIP_D2H_BSY))
ata_wait_spinup(ap, deadline);

/* if we're about to do hardreset, nothing more to do */
if (ehc->i.action & ATA_EH_HARDRESET)
return 0;
Expand Down
58 changes: 41 additions & 17 deletions trunk/drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ enum {
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2),
};

/* Waiting in ->prereset can never be reliable. It's sometimes nice
* to wait there but it can't be depended upon; otherwise, we wouldn't
* be resetting. Just give it enough time for most drives to spin up.
*/
enum {
ATA_EH_PRERESET_TIMEOUT = 10 * HZ,
};

/* The following table determines how we sequence resets. Each entry
* represents timeout for that try. The first try can be soft or
* hardreset. All others are hardreset if available. In most cases
* the first reset w/ 10sec timeout should succeed. Following entries
* are mostly for error handling, hotplug and retarded devices.
*/
static const unsigned long ata_eh_reset_timeouts[] = {
10 * HZ, /* most drives spin up by 10sec */
10 * HZ, /* > 99% working drives spin up before 20sec */
35 * HZ, /* give > 30 secs of idleness for retarded devices */
5 * HZ, /* and sweet one last chance */
/* > 1 min has elapsed, give up */
};

static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
#ifdef CONFIG_PM
Expand Down Expand Up @@ -1603,8 +1625,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
int try = 0;
unsigned long deadline;
unsigned int action;
ata_reset_fn_t reset;
int i, did_followup_srst, rc;
Expand All @@ -1624,7 +1647,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
ehc->i.action |= ATA_EH_HARDRESET;

if (prereset) {
rc = prereset(ap, jiffies + 40 * HZ);
rc = prereset(ap, jiffies + ATA_EH_PRERESET_TIMEOUT);
if (rc) {
if (rc == -ENOENT) {
ata_port_printk(ap, KERN_DEBUG,
Expand Down Expand Up @@ -1665,6 +1688,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}

retry:
deadline = jiffies + ata_eh_reset_timeouts[try++];

/* shut up during boot probing */
if (verbose)
ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
Expand All @@ -1676,7 +1701,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
else
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;

rc = ata_do_reset(ap, reset, classes, jiffies + 40 * HZ);
rc = ata_do_reset(ap, reset, classes, deadline);

did_followup_srst = 0;
if (reset == hardreset &&
Expand All @@ -1693,7 +1718,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}

ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(ap, reset, classes, jiffies + 40 * HZ);
rc = ata_do_reset(ap, reset, classes, deadline);

if (rc == 0 && classify &&
classes[0] == ATA_DEV_UNKNOWN) {
Expand All @@ -1703,22 +1728,21 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}
}

if (rc && --tries) {
const char *type;
if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
unsigned long now = jiffies;

if (reset == softreset) {
if (did_followup_srst)
type = "follow-up soft";
else
type = "soft";
} else
type = "hard";
if (time_before(now, deadline)) {
unsigned long delta = deadline - jiffies;

ata_port_printk(ap, KERN_WARNING,
"%sreset failed, retrying in 5 secs\n", type);
ssleep(5);
ata_port_printk(ap, KERN_WARNING, "reset failed "
"(errno=%d), retrying in %u secs\n",
rc, (jiffies_to_msecs(delta) + 999) / 1000);

schedule_timeout_uninterruptible(delta);
}

if (reset == hardreset)
if (reset == hardreset &&
try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
sata_down_spd_limit(ap);
if (hardreset)
reset = hardreset;
Expand Down
16 changes: 0 additions & 16 deletions trunk/include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,18 +296,8 @@ enum {

/* how hard are we gonna try to probe/recover devices */
ATA_PROBE_MAX_TRIES = 3,
ATA_EH_RESET_TRIES = 3,
ATA_EH_DEV_TRIES = 3,

/* Drive spinup time (time from power-on to the first D2H FIS)
* in msecs - 8s currently. Failing to get ready in this time
* isn't critical. It will result in reset failure for
* controllers which can't wait for the first D2H FIS. libata
* will retry, so it just has to be long enough to spin up
* most devices.
*/
ATA_SPINUP_WAIT = 8000,

/* Horkage types. May be set by libata or controller on drives
(some horkage may be drive/controller pair dependant */

Expand Down Expand Up @@ -495,7 +485,6 @@ struct ata_eh_info {
unsigned int dev_action[ATA_MAX_DEVICES]; /* dev EH action */
unsigned int flags; /* ATA_EHI_* flags */

unsigned long hotplug_timestamp;
unsigned int probe_mask;

char desc[ATA_EH_DESC_LEN];
Expand Down Expand Up @@ -925,12 +914,7 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,

static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi)
{
if (ehi->flags & ATA_EHI_HOTPLUGGED)
return;

ehi->flags |= ATA_EHI_HOTPLUGGED | ATA_EHI_RESUME_LINK;
ehi->hotplug_timestamp = jiffies;

ehi->action |= ATA_EH_SOFTRESET;
ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
}
Expand Down

0 comments on commit 097009a

Please sign in to comment.