提交 5a04bf4b 编写于 作者: T Tejun Heo

[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: NTejun Heo <htejun@gmail.com>
上级 31534363
...@@ -2466,17 +2466,9 @@ static int sata_phy_resume(struct ata_port *ap) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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 { ...@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册