Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b36ac50 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mmc-fixes-for-3.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc

MMC fixes for 3.3-rc4:
 * The most visible fix here is against a regression introduced in 3.3-rc1
   that ran cards in Ultra High Speed mode even when they failed to initialize
   in that mode, leading to lower-speed cards failing to mount.
 * A lockdep warning introduced in 3.3-rc1 is fixed.
 * Various other small driver fixes, most notably for a NULL dereference
   when using highmem with dw_mmc.

* tag 'mmc-fixes-for-3.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc:
  mmc: dw_mmc: Fix PIO mode with support of highmem
  mmc: atmel-mci: save and restore sdioirq when soft reset is performed
  mmc: block: Init ro_lock sysfs attr to fix lockdep warnings
  mmc: sh_mmcif: fix late delayed work initialisation
  mmc: tmio_mmc: fix card eject during IO with DMA
  mmc: core: Fix comparison issue in mmc_compare_ext_csds
  mmc: core: Fix PowerOff Notify suspend/resume
  mmc: sdhci-pci: set Medfield SDIO as non-removable
  mmc: core: add the capability for broken voltage
  mmc: core: Fix low speed mmc card detection failure
  mmc: esdhc: set the timeout to the max value
  mmc: esdhc: add PIO mode support
  mmc: core: Ensure clocks are always enabled before host interaction
  mmc: of_mmc_spi: fix little endian support
  mmc: core: UHS sdio card that fails should not exceed 50MHz
  mmc: esdhc: fix errors when booting kernel on Freescale eSDHC version 2.3
parents 694ce18e f9c2a0dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1694,6 +1694,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)

		md->power_ro_lock.show = power_ro_lock_show;
		md->power_ro_lock.store = power_ro_lock_store;
		sysfs_attr_init(&md->power_ro_lock.attr);
		md->power_ro_lock.attr.mode = mode;
		md->power_ro_lock.attr.name =
					"ro_lock_until_next_power_on";
+39 −10
Original line number Diff line number Diff line
@@ -290,8 +290,11 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
		 bool is_first_req)
{
	if (host->ops->pre_req)
	if (host->ops->pre_req) {
		mmc_host_clk_hold(host);
		host->ops->pre_req(host, mrq, is_first_req);
		mmc_host_clk_release(host);
	}
}

/**
@@ -306,8 +309,11 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
			 int err)
{
	if (host->ops->post_req)
	if (host->ops->post_req) {
		mmc_host_clk_hold(host);
		host->ops->post_req(host, mrq, err);
		mmc_host_clk_release(host);
	}
}

/**
@@ -620,7 +626,9 @@ int mmc_host_enable(struct mmc_host *host)
		int err;

		host->en_dis_recurs = 1;
		mmc_host_clk_hold(host);
		err = host->ops->enable(host);
		mmc_host_clk_release(host);
		host->en_dis_recurs = 0;

		if (err) {
@@ -640,7 +648,9 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy)
		int err;

		host->en_dis_recurs = 1;
		mmc_host_clk_hold(host);
		err = host->ops->disable(host, lazy);
		mmc_host_clk_release(host);
		host->en_dis_recurs = 0;

		if (err < 0) {
@@ -1121,6 +1131,10 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
		 * might not allow this operation
		 */
		voltage = regulator_get_voltage(supply);

		if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE)
			min_uV = max_uV = voltage;

		if (voltage < 0)
			result = voltage;
		else if (voltage < min_uV || voltage > max_uV)
@@ -1203,8 +1217,11 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11

	host->ios.signal_voltage = signal_voltage;

	if (host->ops->start_signal_voltage_switch)
	if (host->ops->start_signal_voltage_switch) {
		mmc_host_clk_hold(host);
		err = host->ops->start_signal_voltage_switch(host, &host->ios);
		mmc_host_clk_release(host);
	}

	return err;
}
@@ -1239,6 +1256,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
	int err = 0;

	card = host->card;
	mmc_claim_host(host);

	/*
	 * Send power notify command only if card
@@ -1269,6 +1287,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
		/* Set the card state to no notification after the poweroff */
		card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
	}
	mmc_release_host(host);
}

/*
@@ -1327,12 +1346,28 @@ static void mmc_power_up(struct mmc_host *host)

void mmc_power_off(struct mmc_host *host)
{
	int err = 0;
	mmc_host_clk_hold(host);

	host->ios.clock = 0;
	host->ios.vdd = 0;

	/*
	 * For eMMC 4.5 device send AWAKE command before
	 * POWER_OFF_NOTIFY command, because in sleep state
	 * eMMC 4.5 devices respond to only RESET and AWAKE cmd
	 */
	if (host->card && mmc_card_is_sleep(host->card) &&
	    host->bus_ops->resume) {
		err = host->bus_ops->resume(host);

		if (!err)
			mmc_poweroff_notify(host);
		else
			pr_warning("%s: error %d during resume "
				   "(continue with poweroff sequence)\n",
				   mmc_hostname(host), err);
	}

	/*
	 * Reset ocr mask to be the highest possible voltage supported for
@@ -2386,12 +2421,6 @@ int mmc_suspend_host(struct mmc_host *host)
		 */
		if (mmc_try_claim_host(host)) {
			if (host->bus_ops->suspend) {
				/*
				 * For eMMC 4.5 device send notify command
				 * before sleep, because in sleep state eMMC 4.5
				 * devices respond to only RESET and AWAKE cmd
				 */
				mmc_poweroff_notify(host);
				err = host->bus_ops->suspend(host);
			}
			mmc_do_release_host(host);
+0 −21
Original line number Diff line number Diff line
@@ -14,27 +14,6 @@

int mmc_register_host_class(void);
void mmc_unregister_host_class(void);

#ifdef CONFIG_MMC_CLKGATE
void mmc_host_clk_hold(struct mmc_host *host);
void mmc_host_clk_release(struct mmc_host *host);
unsigned int mmc_host_clk_rate(struct mmc_host *host);

#else
static inline void mmc_host_clk_hold(struct mmc_host *host)
{
}

static inline void mmc_host_clk_release(struct mmc_host *host)
{
}

static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
{
	return host->ios.clock;
}
#endif

void mmc_host_deeper_disable(struct work_struct *work);

#endif
+17 −9
Original line number Diff line number Diff line
@@ -376,7 +376,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
	}

	card->ext_csd.raw_hc_erase_gap_size =
		ext_csd[EXT_CSD_PARTITION_ATTRIBUTE];
		ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
	card->ext_csd.raw_sec_trim_mult =
		ext_csd[EXT_CSD_SEC_TRIM_MULT];
	card->ext_csd.raw_sec_erase_mult =
@@ -551,7 +551,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
		goto out;

	/* only compare read only fields */
	err = (!(card->ext_csd.raw_partition_support ==
	err = !((card->ext_csd.raw_partition_support ==
			bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
		(card->ext_csd.raw_erased_mem_count ==
			bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) &&
@@ -1006,7 +1006,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
			err = mmc_select_hs200(card);
		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_HS_TIMING, 1, 0);
					 EXT_CSD_HS_TIMING, 1,
					 card->ext_csd.generic_cmd6_time);

		if (err && err != -EBADMSG)
			goto free_card;
@@ -1116,7 +1117,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 * Activate wide bus and DDR (if supported).
	 */
	if (!mmc_card_hs200(card) &&
	    (card->csd.mmca_vsn >= CSD_SPEC_VER_3) &&
	    (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		static unsigned ext_csd_bits[][2] = {
			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
@@ -1315,11 +1316,13 @@ static int mmc_suspend(struct mmc_host *host)
	BUG_ON(!host->card);

	mmc_claim_host(host);
	if (mmc_card_can_sleep(host))
	if (mmc_card_can_sleep(host)) {
		err = mmc_card_sleep(host);
	else if (!mmc_host_is_spi(host))
		if (!err)
			mmc_card_set_sleep(host->card);
	} else if (!mmc_host_is_spi(host))
		mmc_deselect_cards(host);
	host->card->state &= ~MMC_STATE_HIGHSPEED;
	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
	mmc_release_host(host);

	return err;
@@ -1339,6 +1342,10 @@ static int mmc_resume(struct mmc_host *host)
	BUG_ON(!host->card);

	mmc_claim_host(host);
	if (mmc_card_is_sleep(host->card)) {
		err = mmc_card_awake(host);
		mmc_card_clr_sleep(host->card);
	} else
		err = mmc_init_card(host, host->ocr, host->card);
	mmc_release_host(host);

@@ -1349,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host)
{
	int ret;

	host->card->state &= ~MMC_STATE_HIGHSPEED;
	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
	mmc_card_clr_sleep(host->card);
	mmc_claim_host(host);
	ret = mmc_init_card(host, host->ocr, host->card);
	mmc_release_host(host);
+18 −4
Original line number Diff line number Diff line
@@ -451,9 +451,11 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
	 * information and let the hardware specific code
	 * return what is possible given the options
	 */
	mmc_host_clk_hold(card->host);
	drive_strength = card->host->ops->select_drive_strength(
		card->sw_caps.uhs_max_dtr,
		host_drv_type, card_drv_type);
	mmc_host_clk_release(card->host);

	err = mmc_sd_switch(card, 1, 2, drive_strength, status);
	if (err)
@@ -660,9 +662,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
		goto out;

	/* SPI mode doesn't define CMD19 */
	if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
	if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
		mmc_host_clk_hold(card->host);
		err = card->host->ops->execute_tuning(card->host,
						      MMC_SEND_TUNING_BLOCK);
		mmc_host_clk_release(card->host);
	}

out:
	kfree(status);
@@ -850,8 +855,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
	if (!reinit) {
		int ro = -1;

		if (host->ops->get_ro)
		if (host->ops->get_ro) {
			mmc_host_clk_hold(card->host);
			ro = host->ops->get_ro(host);
			mmc_host_clk_release(card->host);
		}

		if (ro < 0) {
			pr_warning("%s: host does not "
@@ -967,8 +975,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
		 * Since initialization is now complete, enable preset
		 * value registers for UHS-I cards.
		 */
		if (host->ops->enable_preset_value)
		if (host->ops->enable_preset_value) {
			mmc_host_clk_hold(card->host);
			host->ops->enable_preset_value(host, true);
			mmc_host_clk_release(card->host);
		}
	} else {
		/*
		 * Attempt to change to high-speed (if supported)
@@ -1151,8 +1162,11 @@ int mmc_attach_sd(struct mmc_host *host)
		return err;

	/* Disable preset value enable if already set since last time */
	if (host->ops->enable_preset_value)
	if (host->ops->enable_preset_value) {
		mmc_host_clk_hold(host);
		host->ops->enable_preset_value(host, false);
		mmc_host_clk_release(host);
	}

	err = mmc_send_app_op_cond(host, 0, &ocr);
	if (err)
Loading