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:
parent
6a55617ed5
commit
05944bdf6f
4 changed files with 38 additions and 16 deletions
|
@ -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 {
|
||||||
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;
|
||||||
|
|
|
@ -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 {
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in a new issue