libata: add @spd_limit to sata_down_spd_limit()

Add @spd_limit to sata_down_spd_limit() so that the caller can specify
the SPD limit it wants.  This parameter doesn't get in the way even
when it's too low.  The closest possible limit is applied.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Tejun Heo
2009-01-29 20:31:33 +09:00
committed by Jeff Garzik
parent 99cf610aa4
commit a07d499b47
4 changed files with 27 additions and 12 deletions

View File

@ -2777,7 +2777,7 @@ int ata_bus_probe(struct ata_port *ap)
/* This is the last chance, better to slow
* down than lose it.
*/
sata_down_spd_limit(&ap->link);
sata_down_spd_limit(&ap->link, 0);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
@ -2873,21 +2873,27 @@ void ata_port_disable(struct ata_port *ap)
/**
* sata_down_spd_limit - adjust SATA spd limit downward
* @link: Link to adjust SATA spd limit for
* @spd_limit: Additional limit
*
* Adjust SATA spd limit of @link downward. Note that this
* function only adjusts the limit. The change must be applied
* using sata_set_spd().
*
* If @spd_limit is non-zero, the speed is limited to equal to or
* lower than @spd_limit if such speed is supported. If
* @spd_limit is slower than any supported speed, only the lowest
* supported speed is allowed.
*
* LOCKING:
* Inherited from caller.
*
* RETURNS:
* 0 on success, negative errno on failure
*/
int sata_down_spd_limit(struct ata_link *link)
int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
{
u32 sstatus, spd, mask;
int rc, highbit;
int rc, bit;
if (!sata_scr_valid(link))
return -EOPNOTSUPP;
@ -2906,8 +2912,8 @@ int sata_down_spd_limit(struct ata_link *link)
return -EINVAL;
/* unconditionally mask off the highest bit */
highbit = fls(mask) - 1;
mask &= ~(1 << highbit);
bit = fls(mask) - 1;
mask &= ~(1 << bit);
/* Mask off all speeds higher than or equal to the current
* one. Force 1.5Gbps if current SPD is not available.
@ -2921,6 +2927,15 @@ int sata_down_spd_limit(struct ata_link *link)
if (!mask)
return -EINVAL;
if (spd_limit) {
if (mask & ((1 << spd_limit) - 1))
mask &= (1 << spd_limit) - 1;
else {
bit = ffs(mask) - 1;
mask = 1 << bit;
}
}
link->sata_spd_limit = mask;
ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",