Commit 05944bdf authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

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: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 6a55617e
...@@ -1074,6 +1074,9 @@ and is between 256 and 4096 characters. It is defined in the 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.
......
...@@ -104,6 +104,7 @@ struct ata_force_param { ...@@ -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) ...@@ -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) ...@@ -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; link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
ata_link_printk(link, KERN_NOTICE, ata_link_printk(link, KERN_NOTICE,
"FORCE: PHY spd limit set to %s\n", fe->param.name); "FORCE: PHY spd limit set to %s\n",
return; fe->param.name);
did_spd = true;
}
/* let lflags stack */
if (fe->param.lflags) {
link->flags |= fe->param.lflags;
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) ...@@ -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, ...@@ -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;
......
...@@ -2210,6 +2210,10 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -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);
......
...@@ -163,6 +163,7 @@ enum { ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment