static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, bool send_status, bool retry_crc_err) { struct mmc_host *host = card->host; int err; unsigned long timeout; u32 status = 0; bool expired = false; bool busy = false; /* We have an unspecified cmd timeout, use the fallback value. */ if (!timeout_ms) timeout_ms = MMC_OPS_TIMEOUT_MS; /* * In cases when not allowed to poll by using CMD13 or because we aren't * capable of polling by using ->card_busy(), then rely on waiting the * stated timeout to be sufficient. */ if (!send_status && !host->ops->card_busy) { mmc_delay(timeout_ms); return 0; } timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; do { /* * Due to the possibility of being preempted while polling, * check the expiration time first. */ expired = time_after(jiffies, timeout); if (host->ops->card_busy) { busy = host->ops->card_busy(host); } else { err = mmc_send_status(card, &status); if (retry_crc_err && err == -EILSEQ) { busy = true; } else if (err) { return err; } else { err = mmc_switch_status_error(host, status); if (err) return err; busy = R1_CURRENT_STATE(status) == R1_STATE_PRG; } } /* Timeout if the device still remains busy. */ if (expired && busy) { pr_err("%s: Card stuck being busy! %s\n", mmc_hostname(host), __func__); return -ETIMEDOUT; } } while (busy); return 0; }
/* Caller must hold re-tuning */ int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) { u32 status; int err; err = mmc_send_status(card, &status); if (!crc_err_fatal && err == -EILSEQ) return 0; if (err) return err; return mmc_switch_status_error(card->host, status); }
/** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer * @set: cmd set values * @index: EXT_CSD register index * @value: value to program into EXT_CSD register * @timeout_ms: timeout (ms) for operation performed by register write, * timeout of zero implies maximum possible timeout * @use_busy_signal: use the busy signal as response type * @send_status: send status cmd to poll for busy * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy * * Modifies the EXT_CSD register for selected card. */ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, bool use_busy_signal, bool send_status, bool ignore_crc) { struct mmc_host *host = card->host; int err; struct mmc_command cmd = {0}; unsigned long timeout; u32 status = 0; bool use_r1b_resp = use_busy_signal; bool expired = false; mmc_retune_hold(host); /* * If the cmd timeout and the max_busy_timeout of the host are both * specified, let's validate them. A failure means we need to prevent * the host from doing hw busy detection, which is done by converting * to a R1 response instead of a R1B. */ if (timeout_ms && host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) use_r1b_resp = false; cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set; cmd.flags = MMC_CMD_AC; if (use_r1b_resp) { cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; /* * A busy_timeout of zero means the host can decide to use * whatever value it finds suitable. */ cmd.busy_timeout = timeout_ms; } else { cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; } if (index == EXT_CSD_SANITIZE_START) cmd.sanitize_busy = true; err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); if (err) goto out; /* No need to check card status in case of unblocking command */ if (!use_busy_signal) goto out; /* * CRC errors shall only be ignored in cases were CMD13 is used to poll * to detect busy completion. */ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ignore_crc = false; /* We have an unspecified cmd timeout, use the fallback value. */ if (!timeout_ms) timeout_ms = MMC_OPS_TIMEOUT_MS; /* Must check status to be sure of no errors. */ timeout = jiffies + msecs_to_jiffies(timeout_ms); do { if (send_status) { /* * Due to the possibility of being preempted after * sending the status command, check the expiration * time first. */ expired = time_after(jiffies, timeout); err = __mmc_send_status(card, &status, ignore_crc); if (err) goto out; } if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) break; if (mmc_host_is_spi(host)) break; /* * We are not allowed to issue a status command and the host * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only * rely on waiting for the stated timeout to be sufficient. */ if (!send_status) { mmc_delay(timeout_ms); goto out; } /* Timeout if the device never leaves the program state. */ if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) { pr_err("%s: Card stuck in programming state! %s\n", mmc_hostname(host), __func__); err = -ETIMEDOUT; goto out; } } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); err = mmc_switch_status_error(host, status); out: mmc_retune_release(host); return err; }