libata: implement no[hs]rst force params

Implement force params nohrst, nosrst and norst.  This is to work
around reset related problems and ease debugging.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Tejun Heo 2008-08-13 20:19:09 +09:00 committed by Jeff Garzik
parent 6a55617ed5
commit 05944bdf6f
4 changed files with 38 additions and 16 deletions

View file

@ -1074,6 +1074,9 @@ and is between 256 and 4096 characters. It is defined in the file
* [no]ncq: Turn on or off NCQ. * [no]ncq: Turn on or off NCQ.
* nohrst, nosrst, norst: suppress hard, soft
and both resets.
If there are multiple matching configurations changing If there are multiple matching configurations changing
the same attribute, the last one is used. the same attribute, the last one is used.

View file

@ -104,6 +104,7 @@ struct ata_force_param {
unsigned long xfer_mask; unsigned long xfer_mask;
unsigned int horkage_on; unsigned int horkage_on;
unsigned int horkage_off; unsigned int horkage_off;
unsigned int lflags;
}; };
struct ata_force_ent { struct ata_force_ent {
@ -196,22 +197,23 @@ void ata_force_cbl(struct ata_port *ap)
} }
/** /**
* ata_force_spd_limit - force SATA spd limit according to libata.force * ata_force_link_limits - force link limits according to libata.force
* @link: ATA link of interest * @link: ATA link of interest
* *
* Force SATA spd limit according to libata.force and whine about * Force link flags and SATA spd limit according to libata.force
* it. When only the port part is specified (e.g. 1:), the limit * and whine about it. When only the port part is specified
* applies to all links connected to both the host link and all * (e.g. 1:), the limit applies to all links connected to both
* fan-out ports connected via PMP. If the device part is * the host link and all fan-out ports connected via PMP. If the
* specified as 0 (e.g. 1.00:), it specifies the first fan-out * device part is specified as 0 (e.g. 1.00:), it specifies the
* link not the host link. Device number 15 always points to the * first fan-out link not the host link. Device number 15 always
* host link whether PMP is attached or not. * points to the host link whether PMP is attached or not.
* *
* LOCKING: * LOCKING:
* EH context. * EH context.
*/ */
static void ata_force_spd_limit(struct ata_link *link) static void ata_force_link_limits(struct ata_link *link)
{ {
bool did_spd = false;
int linkno, i; int linkno, i;
if (ata_is_host_link(link)) if (ata_is_host_link(link))
@ -228,13 +230,22 @@ static void ata_force_spd_limit(struct ata_link *link)
if (fe->device != -1 && fe->device != linkno) if (fe->device != -1 && fe->device != linkno)
continue; continue;
if (!fe->param.spd_limit) /* only honor the first spd limit */
continue; if (!did_spd && fe->param.spd_limit) {
link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
ata_link_printk(link, KERN_NOTICE,
"FORCE: PHY spd limit set to %s\n",
fe->param.name);
did_spd = true;
}
link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; /* let lflags stack */
ata_link_printk(link, KERN_NOTICE, if (fe->param.lflags) {
"FORCE: PHY spd limit set to %s\n", fe->param.name); link->flags |= fe->param.lflags;
return; ata_link_printk(link, KERN_NOTICE,
"FORCE: link flag 0x%x forced -> 0x%x\n",
fe->param.lflags, link->flags);
}
} }
} }
@ -5200,7 +5211,7 @@ int sata_link_init_spd(struct ata_link *link)
if (spd) if (spd)
link->hw_sata_spd_limit &= (1 << spd) - 1; link->hw_sata_spd_limit &= (1 << spd) - 1;
ata_force_spd_limit(link); ata_force_link_limits(link);
link->sata_spd_limit = link->hw_sata_spd_limit; link->sata_spd_limit = link->hw_sata_spd_limit;
@ -5991,6 +6002,9 @@ static int __init ata_parse_force_one(char **cur,
{ "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
{ "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
{ "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) }, { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) },
{ "nohrst", .lflags = ATA_LFLAG_NO_HRST },
{ "nosrst", .lflags = ATA_LFLAG_NO_SRST },
{ "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
}; };
char *start = *cur, *p = *cur; char *start = *cur, *p = *cur;
char *id, *val, *endp; char *id, *val, *endp;

View file

@ -2210,6 +2210,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
*/ */
while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX) while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX)
max_tries++; max_tries++;
if (link->flags & ATA_LFLAG_NO_HRST)
hardreset = NULL;
if (link->flags & ATA_LFLAG_NO_SRST)
softreset = NULL;
now = jiffies; now = jiffies;
deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN);

View file

@ -163,6 +163,7 @@ enum {
ATA_DEV_NONE = 9, /* no device */ ATA_DEV_NONE = 9, /* no device */
/* struct ata_link flags */ /* struct ata_link flags */
ATA_LFLAG_NO_HRST = (1 << 1), /* avoid hardreset */
ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */ ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */
ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */ ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */
ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */