[PATCH] libata-hp-prep: implement ap->hw_sata_spd_limit
Add ap->hw_sata_spd_limit and initialize it once during the boot initialization (or driver load initialization). ap->sata_spd_limit is reset to ap->hw_sata_spd_limit on hotplug. This prevents spd limits introduced by earlier devices from affecting new devices. Signed-off-by: Tejun Heo <htejun@gmail.com>
This commit is contained in:
@@ -2466,17 +2466,9 @@ static int sata_phy_resume(struct ata_port *ap)
|
|||||||
*/
|
*/
|
||||||
void ata_std_probeinit(struct ata_port *ap)
|
void ata_std_probeinit(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u32 scontrol;
|
|
||||||
|
|
||||||
/* resume link */
|
/* resume link */
|
||||||
sata_phy_resume(ap);
|
sata_phy_resume(ap);
|
||||||
|
|
||||||
/* init sata_spd_limit to the current value */
|
|
||||||
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
|
|
||||||
int spd = (scontrol >> 4) & 0xf;
|
|
||||||
ap->sata_spd_limit &= (1 << spd) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for device */
|
/* wait for device */
|
||||||
if (ata_port_online(ap))
|
if (ata_port_online(ap))
|
||||||
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
||||||
@@ -5155,6 +5147,9 @@ void ata_dev_init(struct ata_device *dev)
|
|||||||
struct ata_port *ap = dev->ap;
|
struct ata_port *ap = dev->ap;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* SATA spd limit is bound to the first device */
|
||||||
|
ap->sata_spd_limit = ap->hw_sata_spd_limit;
|
||||||
|
|
||||||
/* High bits of dev->flags are used to record warm plug
|
/* High bits of dev->flags are used to record warm plug
|
||||||
* requests which occur asynchronously. Synchronize using
|
* requests which occur asynchronously. Synchronize using
|
||||||
* host_set lock.
|
* host_set lock.
|
||||||
@@ -5210,7 +5205,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
|
|||||||
ap->udma_mask = ent->udma_mask;
|
ap->udma_mask = ent->udma_mask;
|
||||||
ap->flags |= ent->host_flags;
|
ap->flags |= ent->host_flags;
|
||||||
ap->ops = ent->port_ops;
|
ap->ops = ent->port_ops;
|
||||||
ap->sata_spd_limit = UINT_MAX;
|
ap->hw_sata_spd_limit = UINT_MAX;
|
||||||
ap->active_tag = ATA_TAG_POISON;
|
ap->active_tag = ATA_TAG_POISON;
|
||||||
ap->last_ctl = 0xFF;
|
ap->last_ctl = 0xFF;
|
||||||
ap->msg_enable = ATA_MSG_DRV;
|
ap->msg_enable = ATA_MSG_DRV;
|
||||||
@@ -5375,10 +5370,18 @@ int ata_device_add(const struct ata_probe_ent *ent)
|
|||||||
DPRINTK("probe begin\n");
|
DPRINTK("probe begin\n");
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
struct ata_port *ap;
|
struct ata_port *ap;
|
||||||
|
u32 scontrol;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ap = host_set->ports[i];
|
ap = host_set->ports[i];
|
||||||
|
|
||||||
|
/* init sata_spd_limit to the current value */
|
||||||
|
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
|
||||||
|
int spd = (scontrol >> 4) & 0xf;
|
||||||
|
ap->hw_sata_spd_limit &= (1 << spd) - 1;
|
||||||
|
}
|
||||||
|
ap->sata_spd_limit = ap->hw_sata_spd_limit;
|
||||||
|
|
||||||
DPRINTK("ata%u: bus probe begin\n", ap->id);
|
DPRINTK("ata%u: bus probe begin\n", ap->id);
|
||||||
rc = ata_bus_probe(ap);
|
rc = ata_bus_probe(ap);
|
||||||
DPRINTK("ata%u: bus probe end\n", ap->id);
|
DPRINTK("ata%u: bus probe end\n", ap->id);
|
||||||
|
@@ -489,6 +489,7 @@ struct ata_port {
|
|||||||
unsigned int mwdma_mask;
|
unsigned int mwdma_mask;
|
||||||
unsigned int udma_mask;
|
unsigned int udma_mask;
|
||||||
unsigned int cbl; /* cable type; ATA_CBL_xxx */
|
unsigned int cbl; /* cable type; ATA_CBL_xxx */
|
||||||
|
unsigned int hw_sata_spd_limit;
|
||||||
unsigned int sata_spd_limit; /* SATA PHY speed limit */
|
unsigned int sata_spd_limit; /* SATA PHY speed limit */
|
||||||
|
|
||||||
/* record runtime error info, protected by host_set lock */
|
/* record runtime error info, protected by host_set lock */
|
||||||
|
Reference in New Issue
Block a user