Commit 0ccab014 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Improve API to make it clear that mmc_hw_reset() is for cards
   - Fixup support for writeback-cache for eMMC and SD
   - Check for errors after writes on SPI

  MMC host:
   - renesas_sdhi: A couple of fixes of TAP settings for eMMC HS400 mode
   - mmci_stm32: Fixup check of all elements in sg list
   - sdhci-xenon: Revert unnecessary fix for annoying 1.8V regulator warning"

* tag 'mmc-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: core: improve API to make clear mmc_hw_reset is for cards
  mmc: renesas_sdhi: don't overwrite TAP settings when HS400 tuning is complete
  mmc: renesas_sdhi: special 4tap settings only apply to HS400
  mmc: core: Fixup support for writeback-cache for eMMC and SD
  mmc: block: Check for errors after write on SPI
  mmc: mmci: stm32: correctly check all elements of sg list
  Revert "mmc: sdhci-xenon: fix annoying 1.8V regulator warning"
parents 02994fd2 b71597ed
Loading
Loading
Loading
Loading
+43 −5
Original line number Diff line number Diff line
@@ -993,7 +993,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
		return -EEXIST;

	md->reset_done |= type;
	err = mmc_hw_reset(host);
	err = mmc_hw_reset(host->card);
	/* Ensure we switch back to the correct partition */
	if (err) {
		struct mmc_blk_data *main_md =
@@ -1880,6 +1880,31 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
	       brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
}

static int mmc_spi_err_check(struct mmc_card *card)
{
	u32 status = 0;
	int err;

	/*
	 * SPI does not have a TRAN state we have to wait on, instead the
	 * card is ready again when it no longer holds the line LOW.
	 * We still have to ensure two things here before we know the write
	 * was successful:
	 * 1. The card has not disconnected during busy and we actually read our
	 * own pull-up, thinking it was still connected, so ensure it
	 * still responds.
	 * 2. Check for any error bits, in particular R1_SPI_IDLE to catch a
	 * just reconnected card after being disconnected during busy.
	 */
	err = __mmc_send_status(card, &status, 0);
	if (err)
		return err;
	/* All R1 and R2 bits of SPI are errors in our case */
	if (status)
		return -EIO;
	return 0;
}

static int mmc_blk_busy_cb(void *cb_data, bool *busy)
{
	struct mmc_blk_busy_data *data = cb_data;
@@ -1903,9 +1928,16 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
	struct mmc_blk_busy_data cb_data;
	int err;

	if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
	if (rq_data_dir(req) == READ)
		return 0;

	if (mmc_host_is_spi(card->host)) {
		err = mmc_spi_err_check(card);
		if (err)
			mqrq->brq.data.bytes_xfered = 0;
		return err;
	}

	cb_data.card = card;
	cb_data.status = 0;
	err = __mmc_poll_for_busy(card->host, 0, MMC_BLK_TIMEOUT_MS,
@@ -2350,6 +2382,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
	struct mmc_blk_data *md;
	int devidx, ret;
	char cap_str[10];
	bool cache_enabled = false;
	bool fua_enabled = false;

	devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);
	if (devidx < 0) {
@@ -2429,13 +2463,17 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
			md->flags |= MMC_BLK_CMD23;
	}

	if (mmc_card_mmc(card) &&
	    md->flags & MMC_BLK_CMD23 &&
	if (md->flags & MMC_BLK_CMD23 &&
	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
	     card->ext_csd.rel_sectors)) {
		md->flags |= MMC_BLK_REL_WR;
		blk_queue_write_cache(md->queue.queue, true, true);
		fua_enabled = true;
		cache_enabled = true;
	}
	if (mmc_cache_enabled(card->host))
		cache_enabled  = true;

	blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);

	string_get_size((u64)size, 512, STRING_UNITS_2,
			cap_str, sizeof(cap_str));
+3 −2
Original line number Diff line number Diff line
@@ -1995,7 +1995,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)

/**
 * mmc_hw_reset - reset the card in hardware
 * @host: MMC host to which the card is attached
 * @card: card to be reset
 *
 * Hard reset the card. This function is only for upper layers, like the
 * block layer or card drivers. You cannot use it in host drivers (struct
@@ -2003,8 +2003,9 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
 *
 * Return: 0 on success, -errno on failure
 */
int mmc_hw_reset(struct mmc_host *host)
int mmc_hw_reset(struct mmc_card *card)
{
	struct mmc_host *host = card->host;
	int ret;

	ret = host->bus_ops->hw_reset(host);
+1 −2
Original line number Diff line number Diff line
@@ -2325,10 +2325,9 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
static int mmc_test_reset(struct mmc_test_card *test)
{
	struct mmc_card *card = test->card;
	struct mmc_host *host = card->host;
	int err;

	err = mmc_hw_reset(host);
	err = mmc_hw_reset(card);
	if (!err) {
		/*
		 * Reset will re-enable the card's command queue, but tests
+3 −3
Original line number Diff line number Diff line
@@ -62,8 +62,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
	 * excepted the last element which has no constraint on idmasize
	 */
	for_each_sg(data->sg, sg, data->sg_len - 1, i) {
		if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) ||
		    !IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) {
		if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
		    !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
			dev_err(mmc_dev(host->mmc),
				"unaligned scatterlist: ofst:%x length:%d\n",
				data->sg->offset, data->sg->length);
@@ -71,7 +71,7 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
		}
	}

	if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) {
	if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
		dev_err(mmc_dev(host->mmc),
			"unaligned last scatterlist: ofst:%x length:%d\n",
			data->sg->offset, data->sg->length);
+4 −4
Original line number Diff line number Diff line
@@ -144,9 +144,9 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
		return clk_get_rate(priv->clk);

	if (priv->clkh) {
		/* HS400 with 4TAP needs different clock settings */
		bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
		bool need_slow_clkh = (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
				      (host->mmc->ios.timing == MMC_TIMING_MMC_HS400);
		bool need_slow_clkh = host->mmc->ios.timing == MMC_TIMING_MMC_HS400;
		clkh_shift = use_4tap && need_slow_clkh ? 1 : 2;
		ref_clk = priv->clkh;
	}
@@ -396,10 +396,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
			SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
			sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));

	/* Set the sampling clock selection range of HS400 mode */
	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
		       SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
		       0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
		       sd_scc_read32(host, priv,
				     SH_MOBILE_SDHI_SCC_DTCNTL));

	/* Avoid bad TAP */
	if (bad_taps & BIT(priv->tap_set)) {
Loading