Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 212812
b: refs/heads/master
c: 6b7ae95
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Oct 22, 2010
1 parent d62bc9c commit ace4700
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 357 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1152b2617a6e1943b6b82e07c962950e56f1000c
refs/heads/master: 6b7ae9545ad9875a289f4191c0216b473e313cb9
3 changes: 0 additions & 3 deletions trunk/drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1208,9 +1208,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
ata_port_pbar_desc(ap, AHCI_PCI_BAR,
0x100 + ap->port_no * 0x80, "port");

/* set initial link pm policy */
ap->lpm_policy = ATA_LPM_UNKNOWN;

/* set enclosure management message type */
if (ap->flags & ATA_FLAG_EM)
ap->em_message_type = hpriv->em_msg_type;
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/ata/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ enum {
AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
Expand Down
3 changes: 0 additions & 3 deletions trunk/drivers/ata/ahci_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ static int __init ahci_probe(struct platform_device *pdev)
ata_port_desc(ap, "mmio %pR", mem);
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);

/* set initial link pm policy */
ap->lpm_policy = ATA_LPM_UNKNOWN;

/* set enclosure management message type */
if (ap->flags & ATA_FLAG_EM)
ap->em_message_type = hpriv->em_msg_type;
Expand Down
158 changes: 41 additions & 117 deletions trunk/drivers/ata/libahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)
module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");

static int ahci_enable_alpm(struct ata_port *ap, enum ata_lpm_policy policy);
static void ahci_disable_alpm(struct ata_port *ap);
static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
unsigned hints);
static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
size_t size);
Expand Down Expand Up @@ -163,8 +163,7 @@ struct ata_port_operations ahci_ops = {
.pmp_attach = ahci_pmp_attach,
.pmp_detach = ahci_pmp_detach,

.enable_pm = ahci_enable_alpm,
.disable_pm = ahci_disable_alpm,
.set_lpm = ahci_set_lpm,
.em_show = ahci_led_show,
.em_store = ahci_led_store,
.sw_activity_show = ahci_activity_show,
Expand Down Expand Up @@ -641,126 +640,56 @@ static void ahci_power_up(struct ata_port *ap)
writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
}

static void ahci_disable_alpm(struct ata_port *ap)
static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
unsigned int hints)
{
struct ata_port *ap = link->ap;
struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
u32 cmd;
struct ahci_port_priv *pp = ap->private_data;

/* LPM bits should be disabled by libata-core */
/* get the existing command bits */
cmd = readl(port_mmio + PORT_CMD);

/* disable ALPM and ASP */
cmd &= ~PORT_CMD_ASP;
cmd &= ~PORT_CMD_ALPE;

/* force the interface back to active */
cmd |= PORT_CMD_ICC_ACTIVE;

/* write out new cmd value */
writel(cmd, port_mmio + PORT_CMD);
cmd = readl(port_mmio + PORT_CMD);

/* wait 10ms to be sure we've come out of any low power state */
msleep(10);

/* clear out any PhyRdy stuff from interrupt status */
writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);

/* go ahead and clean out PhyRdy Change from Serror too */
ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));

/*
* Clear flag to indicate that we should ignore all PhyRdy
* state changes
*/
hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;

/*
* Enable interrupts on Phy Ready.
*/
pp->intr_mask |= PORT_IRQ_PHYRDY;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);

/*
* don't change the link pm policy - we can be called
* just to turn of link pm temporarily
*/
}

static int ahci_enable_alpm(struct ata_port *ap, enum ata_lpm_policy policy)
{
struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
u32 cmd;
struct ahci_port_priv *pp = ap->private_data;
u32 asp;

/* Make sure the host is capable of link power management */
if (!(hpriv->cap & HOST_CAP_ALPM))
return -EINVAL;

switch (policy) {
case ATA_LPM_MAX_POWER:
case ATA_LPM_UNKNOWN:
if (policy != ATA_LPM_MAX_POWER) {
/*
* if we came here with ATA_LPM_UNKNOWN,
* it just means this is the first time we
* have tried to enable - default to max performance,
* and let the user go to lower power modes on request.
* Disable interrupts on Phy Ready. This keeps us from
* getting woken up due to spurious phy ready
* interrupts.
*/
ahci_disable_alpm(ap);
return 0;
case ATA_LPM_MIN_POWER:
/* configure HBA to enter SLUMBER */
asp = PORT_CMD_ASP;
break;
case ATA_LPM_MED_POWER:
/* configure HBA to enter PARTIAL */
asp = 0;
break;
default:
return -EINVAL;
pp->intr_mask &= ~PORT_IRQ_PHYRDY;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);

sata_link_scr_lpm(link, policy, false);
}

/*
* Disable interrupts on Phy Ready. This keeps us from
* getting woken up due to spurious phy ready interrupts
* TBD - Hot plug should be done via polling now, is
* that even supported?
*/
pp->intr_mask &= ~PORT_IRQ_PHYRDY;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
if (hpriv->cap & HOST_CAP_ALPM) {
u32 cmd = readl(port_mmio + PORT_CMD);

/*
* Set a flag to indicate that we should ignore all PhyRdy
* state changes since these can happen now whenever we
* change link state
*/
hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
cmd |= PORT_CMD_ICC_ACTIVE;

/* get the existing command bits */
cmd = readl(port_mmio + PORT_CMD);
writel(cmd, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD);

/*
* Set ASP based on Policy
*/
cmd |= asp;
/* wait 10ms to be sure we've come out of LPM state */
msleep(10);
} else {
cmd |= PORT_CMD_ALPE;
if (policy == ATA_LPM_MIN_POWER)
cmd |= PORT_CMD_ASP;

/*
* Setting this bit will instruct the HBA to aggressively
* enter a lower power link state when it's appropriate and
* based on the value set above for ASP
*/
cmd |= PORT_CMD_ALPE;
/* write out new cmd value */
writel(cmd, port_mmio + PORT_CMD);
}
}

/* write out new cmd value */
writel(cmd, port_mmio + PORT_CMD);
cmd = readl(port_mmio + PORT_CMD);
if (policy == ATA_LPM_MAX_POWER) {
sata_link_scr_lpm(link, policy, false);

/* turn PHYRDY IRQ back on */
pp->intr_mask |= PORT_IRQ_PHYRDY;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}

/* LPM bits should be set by libata-core */
return 0;
}

Expand Down Expand Up @@ -1658,15 +1587,10 @@ static void ahci_port_intr(struct ata_port *ap)
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;

/* If we are getting PhyRdy, this is
* just a power state change, we should
* clear out this, plus the PhyRdy/Comm
* Wake bits from Serror
*/
if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
(status & PORT_IRQ_PHYRDY)) {
/* if LPM is enabled, PHYRDY doesn't mean anything */
if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
status &= ~PORT_IRQ_PHYRDY;
ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
}

if (unlikely(status & PORT_IRQ_ERROR)) {
Expand Down
Loading

0 comments on commit ace4700

Please sign in to comment.