mmc rescan簡析

mmc rescan是mmc host的detect work的功能函數,該函數用於探測目標卡的類型並且根據mmc/sd/sdio協議進行comm的初始化。

void mmc_rescan(struct work_struct *work)
{
	static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
	struct mmc_host *host =
		container_of(work, struct mmc_host, detect.work);
	int i;
	bool extend_wakelock = false;

	if (host->rescan_disable)
		return;

	mmc_bus_get(host);

	/*
	 * if there is a _removable_ card registered, check whether it is
	 * still present
	 */
	if (host->bus_ops && host->bus_ops->detect && !host->bus_dead
	    && !(host->caps & MMC_CAP_NONREMOVABLE))
		host->bus_ops->detect(host);//這裏所做的事情:當我們進入delay work時,我們首先要檢查一下,目標卡是否依然存在,如果仍然存在而且目標卡是可插拔的,那麼我們需要先將該卡在內核留下的一些痕跡清除,重新探測該卡。所以一般如果是目標卡復位的話,一般是調用內核提供的專用的復位接口(如sdio_reset_comm等),而不是調度host的這個delay work,

	host->detect_change = 0;

	/* If the card was removed the bus will be marked
	 * as dead - extend the wakelock so userspace
	 * can respond */
	if (host->bus_dead)
		extend_wakelock = 1;

	/*
	 * Let mmc_bus_put() free the bus/bus_ops if we've found that
	 * the card is no longer present.
	 */
	mmc_bus_put(host);
	mmc_bus_get(host);

	/* if there still is a card present, stop here */
	if (host->bus_ops != NULL) { //判斷是否bus的引用計數是否爲0,如果不爲0 ,說明bus仍然被引用,不能再繼續下面的探測了。
		mmc_bus_put(host);
		goto out;
	}

	/*
	 * Only we can add a new handler, so it's safe to
	 * release the lock here.
	 */
	mmc_bus_put(host);

	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
		goto out;

	mmc_claim_host(host);
	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
		if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) {
			extend_wakelock = true;
			break;
		}
		if (freqs[i] <= host->f_min)
			break;
	}
	mmc_release_host(host);

 out:
	if (extend_wakelock)
		wake_lock_timeout(&host->detect_wake_lock, HZ / 2);
	else
		wake_unlock(&host->detect_wake_lock);
	if (host->caps & MMC_CAP_NEEDS_POLL) {
		wake_lock(&host->detect_wake_lock);
		mmc_schedule_delayed_work(&host->detect, HZ);
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章