staticvoid ahci_enable_ahci(void __iomem *mmio)
{ int i;
u32 tmp;
/* turn on AHCI_EN */
tmp = readl(mmio + HOST_CTL); if (tmp & HOST_AHCI_EN) return;
/* Some controllers need AHCI_EN to be written multiple times. * Try a few times before giving up.
*/ for (i = 0; i < 5; i++) {
tmp |= HOST_AHCI_EN;
writel(tmp, mmio + HOST_CTL);
tmp = readl(mmio + HOST_CTL); /* flush && sanity check */ if (tmp & HOST_AHCI_EN) return;
msleep(10);
}
WARN_ON(1);
}
/** * ahci_rpm_get_port - Make sure the port is powered on * @ap: Port to power on * * Whenever there is need to access the AHCI host registers outside of * normal execution paths, call this function to make sure the host is * actually powered on.
*/ staticint ahci_rpm_get_port(struct ata_port *ap)
{ return pm_runtime_get_sync(ap->dev);
}
/** * ahci_rpm_put_port - Undoes ahci_rpm_get_port() * @ap: Port to power down * * Undoes ahci_rpm_get_port() and possibly powers down the AHCI host * if it has no more active users.
*/ staticvoid ahci_rpm_put_port(struct ata_port *ap)
{
pm_runtime_put(ap->dev);
}
if (!(em_ctl & EM_CTL_SMB))
em_mmio += hpriv->em_buf_sz;
count = hpriv->em_buf_sz;
/* the count should not be larger than PAGE_SIZE */ if (count > PAGE_SIZE) { if (printk_ratelimit())
ata_port_warn(ap, "EM read buffer size too large: " "buffer size %u, page size %lu\n",
hpriv->em_buf_sz, PAGE_SIZE);
count = PAGE_SIZE;
}
/** * ahci_save_initial_config - Save and fixup initial config values * @dev: target AHCI device * @hpriv: host private area to store config values * * Some registers containing configuration info might be setup by * BIOS and might be cleared on reset. This function saves the * initial values of those registers into @hpriv such that they * can be restored after controller reset. * * If inconsistent, config values are fixed up by this function. * * If it is not set already this function sets hpriv->start_engine to * ahci_start_engine. * * LOCKING: * None.
*/ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
{ void __iomem *mmio = hpriv->mmio; void __iomem *port_mmio; unsignedlong port_map;
u32 cap, cap2, vers; int i;
/* make sure AHCI mode is enabled before accessing CAP */
ahci_enable_ahci(mmio);
/* * Values prefixed with saved_ are written back to the HBA and ports * registers after reset. Values without are used for driver operation.
*/
/* * Override HW-init HBA capability fields with the platform-specific * values. The rest of the HBA capabilities are defined as Read-only * and can't be modified in CSR anyway.
*/
cap = readl(mmio + HOST_CAP); if (hpriv->saved_cap)
cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
hpriv->saved_cap = cap;
/* CAP2 register is only defined for AHCI 1.2 and later */
vers = readl(mmio + HOST_VERSION); if ((vers >> 16) > 1 ||
((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2); else
hpriv->saved_cap2 = cap2 = 0;
/* some chips have errata preventing 64bit use */ if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
dev_info(dev, "controller can't do 64bit DMA, forcing 32bit\n");
cap &= ~HOST_CAP_64;
}
if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
dev_info(dev, "controller can't do NCQ, turning off CAP_NCQ\n");
cap &= ~HOST_CAP_NCQ;
}
if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
dev_info(dev, "controller can do NCQ, turning on CAP_NCQ\n");
cap |= HOST_CAP_NCQ;
}
if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
dev_info(dev, "controller can't do PMP, turning off CAP_PMP\n");
cap &= ~HOST_CAP_PMP;
}
if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
dev_info(dev, "controller can't do SNTF, turning off CAP_SNTF\n");
cap &= ~HOST_CAP_SNTF;
}
if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
cap |= HOST_CAP_FBS;
}
if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) {
dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n");
cap &= ~HOST_CAP_FBS;
}
if (!(cap & HOST_CAP_ALPM) && (hpriv->flags & AHCI_HFLAG_YES_ALPM)) {
dev_info(dev, "controller can do ALPM, turning on CAP_ALPM\n");
cap |= HOST_CAP_ALPM;
}
if ((cap & HOST_CAP_SXS) && (hpriv->flags & AHCI_HFLAG_NO_SXS)) {
dev_info(dev, "controller does not support SXS, disabling CAP_SXS\n");
cap &= ~HOST_CAP_SXS;
}
/* Override the HBA ports mapping if the platform needs it */
port_map = readl(mmio + HOST_PORTS_IMPL); if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
port_map, hpriv->saved_port_map);
port_map = hpriv->saved_port_map;
} else {
hpriv->saved_port_map = port_map;
}
/* mask_port_map not set means that all ports are available */ if (hpriv->mask_port_map) {
dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
port_map,
port_map & hpriv->mask_port_map);
port_map &= hpriv->mask_port_map;
}
/* cross check port_map and cap.n_ports */ if (port_map) { int map_ports = 0;
for (i = 0; i < AHCI_MAX_PORTS; i++) if (port_map & (1 << i))
map_ports++;
/* If PI has more ports than n_ports, whine, clear * port_map and let it be generated from n_ports.
*/ if (map_ports > ahci_nr_ports(cap)) {
dev_warn(dev, "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
port_map, ahci_nr_ports(cap));
port_map = 0;
}
}
/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ if (!port_map && vers < 0x10300) {
port_map = (1 << ahci_nr_ports(cap)) - 1;
dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
/* write the fixed up value to the PI register */
hpriv->saved_port_map = port_map;
}
/* * Preserve the ports capabilities defined by the platform. Note there * is no need in storing the rest of the P#.CMD fields since they are * volatile.
*/
for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) { if (hpriv->saved_port_cap[i]) continue;
/* * On some controllers, stopping a port's DMA engine while the port * is in ALPM state (partial or slumber) results in failures on * subsequent DMA engine starts. For those controllers, put the * port back in active state before stopping its DMA engine.
*/ if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) &&
(ap->link.lpm_policy > ATA_LPM_MAX_POWER) &&
ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) {
dev_err(ap->host->dev, "Failed to wake up port before engine stop\n"); return -EIO;
}
tmp = readl(port_mmio + PORT_CMD);
/* check if the HBA is idle */ if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0) return 0;
/* * Don't try to issue commands but return with ENODEV if the * AHCI controller not available anymore (e.g. due to PCIe hot * unplugging). Otherwise a 500ms delay for each port is added.
*/ if (tmp == 0xffffffff) {
dev_err(ap->host->dev, "AHCI controller unavailable!\n"); return -ENODEV;
}
/* wait for engine to stop. This could be as long as 500 msec */
tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); if (tmp & PORT_CMD_LIST_ON) return -EIO;
if (policy != ATA_LPM_MAX_POWER) { /* wakeup flag only applies to the max power policy */
hints &= ~ATA_LPM_WAKE_ONLY;
/* * Disable interrupts on Phy Ready. This keeps us from * getting woken up due to spurious phy ready * interrupts.
*/
pp->intr_mask &= ~PORT_IRQ_PHYRDY;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
/* put device into listen mode, first set PxSCTL.DET to 0 */
scontrol = readl(port_mmio + PORT_SCR_CTL);
scontrol &= ~0xf;
writel(scontrol, port_mmio + PORT_SCR_CTL);
/* then set PxCMD.SUD to 0 */
cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
cmd &= ~PORT_CMD_SPIN_UP;
writel(cmd, port_mmio + PORT_CMD);
} #endif
/* enable DMA */ if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
hpriv->start_engine(ap);
/* turn on LEDs */ if (ap->flags & ATA_FLAG_EM) {
ata_for_each_link(link, ap, EDGE) {
emp = &pp->em_priv[link->pmp];
/* EM Transmit bit maybe busy during init */ for (i = 0; i < EM_MAX_RETRY; i++) {
rc = ap->ops->transmit_led_message(ap,
emp->led_state,
4); /* * If busy, give a breather but do not * release EH ownership by using msleep() * instead of ata_msleep(). EM Transmit * bit is busy for the whole host and * releasing ownership will cause other * ports to fail the same way.
*/ if (rc == -EBUSY)
msleep(1); else break;
}
}
}
if (ap->flags & ATA_FLAG_SW_ACTIVITY)
ata_for_each_link(link, ap, EDGE)
ahci_init_sw_activity(link);
/* * To perform host reset, OS should set HOST_RESET and poll until this * bit is read to be "0". Reset must complete within 1 second, or the * hardware should be considered fried.
*/
tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
HOST_RESET, 10, 1000); if (tmp & HOST_RESET) {
dev_err(host->dev, "Controller reset failed (0x%x)\n",
tmp); return -EIO;
}
/* Turn on AHCI mode */
ahci_enable_ahci(mmio);
/* Some registers might be cleared on reset. Restore initial values. */ if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
ahci_restore_initial_config(host);
/* check to see if we've had activity. If so, * toggle state of LED and reset timer. If not, * turn LED to desired idle state.
*/
spin_lock_irqsave(ap->lock, flags); if (emp->saved_activity != emp->activity) {
emp->saved_activity = emp->activity; /* get the current LED state */
activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
if (activity_led_state)
activity_led_state = 0; else
activity_led_state = 1;
/* clear old state */
led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
/* get the slot number from the message */
pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < EM_MAX_SLOTS)
emp = &pp->em_priv[pmp]; else return -EINVAL;
/* * if we are still busy transmitting a previous message, * do not allow
*/
em_ctl = readl(mmio + HOST_EM_CTL); if (em_ctl & EM_CTL_TM) {
spin_unlock_irqrestore(ap->lock, flags);
ahci_rpm_put_port(ap); return -EBUSY;
}
if (hpriv->em_msg_type & EM_MSG_TYPE_LED) { /* * create message header - this is all zero except for * the message size, which is 4 bytes.
*/
message[0] |= (4 << 8);
/* ignore 0:4 of byte zero, fill in port info yourself */
message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
if (kstrtouint(buf, 0, &state) < 0) return -EINVAL;
/* get the slot number from the message */
pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < EM_MAX_SLOTS) {
pmp = array_index_nospec(pmp, EM_MAX_SLOTS);
emp = &pp->em_priv[pmp];
} else { return -EINVAL;
}
/* mask off the activity bits if we are in sw_activity * mode, user should turn off sw_activity before setting * activity led through em_message
*/ if (emp->blink_policy)
state &= ~EM_MSG_LED_VALUE_ACTIVITY;
/* need to do CLO? * always do CLO if PMP is attached (AHCI-1.3 9.2)
*/
busy = status & (ATA_BUSY | ATA_DRQ); if (!busy && !sata_pmp_attached(ap)) {
rc = 0; goto out_restart;
}
/* prepare for SRST (AHCI-1.1 10.4.1) */
rc = ahci_kick_engine(ap); if (rc && rc != -EOPNOTSUPP)
ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
/* * According to AHCI-1.2 9.3.9: if FBS is enable, software shall * clear PxFBS.EN to '0' prior to issuing software reset to devices * that is attached to port multiplier.
*/ if (!ata_is_host_link(link) && pp->fbs_enabled) {
ahci_disable_fbs(ap);
fbs_disabled = true;
}
ata_tf_init(link->device, &tf);
/* issue the first H2D Register FIS */
msecs = 0;
now = jiffies; if (time_after(deadline, now))
msecs = jiffies_to_msecs(deadline - now);
/* spec says at least 5us, but be generous and sleep for 1ms */
ata_msleep(ap, 1);
/* issue the second H2D Register FIS */
tf.ctl &= ~ATA_SRST;
ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
/* wait for link to become ready */
rc = ata_wait_after_reset(link, deadline, check_ready); if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) { /* * Workaround for cases where link online status can't * be trusted. Treat device readiness timeout as link * offline.
*/
ata_link_info(link, "device not ready, treating as offline\n");
*class = ATA_DEV_NONE;
} elseif (rc) { /* link occupied, -ENODEV too is an error */
reason = "device not ready"; goto fail;
} else
*class = ahci_dev_classify(ap);
/* re-enable FBS if disabled before */ if (fbs_disabled)
ahci_enable_fbs(ap);
/* * There is no need to check TFDATA if BAD PMP is found due to HW bug, * which can save timeout delay.
*/ if (irq_status & PORT_IRQ_BAD_PMP) return -EIO;
/* * Soft reset fails with IPMS set when PMP is enabled but * SATA HDD/ODD is connected to SATA port, do soft reset * again to port 0.
*/ if (rc == -EIO) {
irq_sts = readl(port_mmio + PORT_IRQ_STAT); if (irq_sts & PORT_IRQ_BAD_PMP) {
ata_link_warn(link, "applying PMP SRST workaround " "and retrying\n");
rc = ahci_do_softreset(link, class, 0, deadline,
ahci_check_ready);
}
}
/* * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS.
*/
cmd_tbl = pp->cmd_tbl + qc->hw_tag * AHCI_CMD_TBL_SZ;
/* time to wait for DEC is not specified by AHCI spec, * add a retry loop for safety.
*/
writel(fbs | PORT_FBS_DEC, port_mmio + PORT_FBS);
fbs = readl(port_mmio + PORT_FBS); while ((fbs & PORT_FBS_DEC) && retries--) {
udelay(1);
fbs = readl(port_mmio + PORT_FBS);
}
if (fbs & PORT_FBS_DEC)
dev_err(ap->host->dev, "failed to clear device error\n");
}
/* record irq stat */
ata_ehi_clear_desc(host_ehi);
ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
/* AHCI needs SError cleared; otherwise, it might lock up */
ahci_scr_read(&ap->link, SCR_ERROR, &serror);
ahci_scr_write(&ap->link, SCR_ERROR, serror);
host_ehi->serror |= serror;
/* some controllers set IRQ_IF_ERR on device errors, ignore it */ if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
irq_stat &= ~PORT_IRQ_IF_ERR;
if (irq_stat & PORT_IRQ_TF_ERR) { /* If qc is active, charge it; otherwise, the active * link. There's no active qc on NCQ errors. It will * be determined by EH by reading log page 10h.
*/ if (active_qc)
active_qc->err_mask |= AC_ERR_DEV; else
active_ehi->err_mask |= AC_ERR_DEV;
if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
host_ehi->serror &= ~SERR_INTERNAL;
}
/* * pp->active_link is not reliable once FBS is enabled, both * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because * NCQ and non-NCQ commands may be in flight at the same time.
*/ if (pp->fbs_enabled) { if (ap->qc_active) {
qc_active = readl(port_mmio + PORT_SCR_ACT);
qc_active |= readl(port_mmio + PORT_CMD_ISSUE);
}
} else { /* pp->active_link is valid iff any command is in flight */ if (ap->qc_active && pp->active_link->sactive)
qc_active = readl(port_mmio + PORT_SCR_ACT); else
qc_active = readl(port_mmio + PORT_CMD_ISSUE);
}
/* ignore BAD_PMP while resetting */ if (unlikely(ap->pflags & ATA_PFLAG_RESETTING))
status &= ~PORT_IRQ_BAD_PMP;
if (sata_lpm_ignore_phy_events(&ap->link)) {
status &= ~PORT_IRQ_PHYRDY;
ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
}
if (unlikely(status & PORT_IRQ_ERROR)) { /* * Before getting the error notification, we may have * received SDB FISes notifying successful completions. * Handle these first and then handle the error.
*/
ahci_qc_complete(ap, port_mmio);
ahci_error_intr(ap, status); return;
}
if (status & PORT_IRQ_SDB_FIS) { /* If SNotification is available, leave notification * handling to sata_async_notification(). If not, * emulate it by snooping SDB FIS RX area. * * Snooping FIS RX area is probably cheaper than * poking SNotification but some constrollers which * implement SNotification, ICH9 for example, don't * store AN SDB FIS into receive area.
*/ if (hpriv->cap & HOST_CAP_SNTF)
sata_async_notification(ap); else { /* If the 'N' bit in word 0 of the FIS is set, * we just received asynchronous notification. * Tell libata about it. * * Lack of SNotification should not appear in * ahci 1.2, so the workaround is unnecessary * when FBS is enabled.
*/ if (pp->fbs_enabled)
WARN_ON_ONCE(1); else { const __le32 *f = pp->rx_fis + RX_FIS_SDB;
u32 f0 = le32_to_cpu(f[0]); if (f0 & (1 << 15))
sata_async_notification(ap);
}
}
}
/* sigh. 0xffffffff is a valid return from h/w */
irq_stat = readl(mmio + HOST_IRQ_STAT); if (!irq_stat) return IRQ_NONE;
irq_masked = irq_stat & hpriv->port_map;
spin_lock(&host->lock);
rc = ahci_handle_port_intr(host, irq_masked);
/* HOST_IRQ_STAT behaves as level triggered latch meaning that * it should be cleared after all the port events are cleared; * otherwise, it will raise a spurious interrupt after each * valid one. Please read section 10.6.2 of ahci 1.1 for more * information. * * Also, use the unmasked value to clear interrupt as spurious * pending event on a dummy port might cause screaming IRQ.
*/
writel(irq_stat, mmio + HOST_IRQ_STAT);
/* Keep track of the currently active link. It will be used * in completion path to determine whether NCQ phase is in * progress.
*/
pp->active_link = qc->dev->link;
if (ata_is_ncq(qc->tf.protocol))
writel(1 << qc->hw_tag, port_mmio + PORT_SCR_ACT);
if (pp->fbs_enabled)
rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
/* * After a successful execution of an ATA PIO data-in command, * the device doesn't send D2H Reg FIS to update the TF and * the host should take TF and E_Status from the preceding PIO * Setup FIS.
*/ if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
!(qc->flags & ATA_QCFLAG_EH)) {
ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; return;
}
/* * For NCQ commands, we never get a D2H FIS, so reading the D2H Register * FIS area of the Received FIS Structure (which contains a copy of the * last D2H FIS received) will contain an outdated status code. * For NCQ commands, we instead get a SDB FIS, so read the SDB FIS area * instead. However, the SDB FIS does not contain the LBA, so we can't * use the ata_tf_from_fis() helper.
*/ if (ata_is_ncq(qc->tf.protocol)) { const u8 *fis = rx_fis + RX_FIS_SDB;
/* * Successful NCQ commands have been filled already. * A failed NCQ command will read the status here. * (Note that a failed NCQ command will get a more specific * error when reading the NCQ Command Error log.)
*/
qc->result_tf.status = fis[2];
qc->result_tf.error = fis[3]; return;
}
/* * FBS enabled, so read the status and error for each QC, since the QCs * can belong to different PMP links. (Each PMP link has its own FIS * Receive Area.)
*/ while (done_mask) { struct ata_queued_cmd *qc; unsignedint tag = __ffs64(done_mask);
/* device sleep was already enabled and same dito */ if ((devslp & PORT_DEVSLP_ADSE) && (dito_conf == dito)) return;
/* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
rc = hpriv->stop_engine(ap); if (rc) return;
/* Use the nominal value 10 ms if the read MDAT is zero, * the nominal value of DETO is 20 ms.
*/ if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
ATA_LOG_DEVSLP_VALID_MASK) {
mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
ATA_LOG_DEVSLP_MDAT_MASK; if (!mdat)
mdat = 10;
deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; if (!deto)
deto = 20;
} else {
mdat = 10;
deto = 20;
}
/* * We must not change the port interrupt mask register if the * port is marked frozen, the value in pp->intr_mask will be * restored later when the port is thawed. * * Note that during initialization, the port is marked as * frozen since the irq handler is not yet registered.
*/ if (!ata_port_is_frozen(ap))
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.