歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux設備模型之mmc,sd子系統<三>

Linux設備模型之mmc,sd子系統<三>

日期:2017/2/28 15:57:56   编辑:Linux教程

####看一下重要的卡掃描函數,mmc_rescan,卡就指著他
####活著呢,

相關閱讀:

Linux設備模型之mmc,sd子系統<一> http://www.linuxidc.com/Linux/2012-02/52948.htm

Linux設備模型之mmc,sd子系統<二> http://www.linuxidc.com/Linux/2012-02/53024.htm

/driver/mmc/core/core.c

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;

if (host->rescan_disable) //disable 直接返回
return;


mmc_bus_get(host); //增加bus引用計數

/*
* 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); //存在熱插拔卡,不包括emmc,調用探測函數

/*
* 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) {
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); //用於檢測host是否被占用,占用則退出,否則標記成占用
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) //利用不同的頻率探測卡
break;
if (freqs[i] <= host->f_min)
break;
}
mmc_release_host(host);

out:

if (host->caps & MMC_CAP_NEEDS_POLL) //輪詢標志,設置了就會輪詢

mmc_schedule_delayed_work(&host->detect, HZ);

}

#####

/**

* mmc_claim_host - exclusively claim a host

* @host: mmc host to claim

*

* Claim a host for a set of operations.

*/

static inline void mmc_claim_host(struct mmc_host *host)

{

__mmc_claim_host(host, NULL);

}

#####
/**
* __mmc_claim_host - exclusively claim a host
* @host: mmc host to claim
* @abort: whether or not the operation should be aborted
*
* Claim a host for a set of operations. If @abort is non null and
* dereference a non-zero value then this will return prematurely with
* that non-zero value without acquiring the lock. Returns zero
* with the lock held otherwise.
*/
int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
{
DECLARE_WAITQUEUE(wait, current); //定義一個等待隊列
unsigned long flags;
int stop;

might_sleep(); //調度點

add_wait_queue(&host->wq, &wait);
spin_lock_irqsave(&host->lock, flags);
while (1) {
set_current_state(TASK_UNINTERRUPTIBLE);
stop = abort ? atomic_read(abort) : 0;
if (stop || !host->claimed || host->claimer == current)
break;
spin_unlock_irqrestore(&host->lock, flags);
schedule();
spin_lock_irqsave(&host->lock, flags);
} //只有claim為空的時候還會跳出循環,否則就一直等待釋放
set_current_state(TASK_RUNNING);
if (!stop) {
host->claimed = 1;
host->claimer = current;
host->claim_cnt += 1;
} else
wake_up(&host->wq);
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);
if (!stop)
mmc_host_enable(host); //使能該host
return stop;
}


#####
mmc_host_enable函數可以做一些底電流工作

#####


/**
* mmc_host_enable - enable a host.
* @host: mmc host to enable
*
* Hosts that support power saving can use the 'enable' and 'disable'
* methods to exit and enter power saving states. For more information
* see comments for struct mmc_host_ops.
*/
int mmc_host_enable(struct mmc_host *host)
{
if (!(host->caps & MMC_CAP_DISABLE))
return 0;

if (host->en_dis_recurs)
return 0;

if (host->nesting_cnt++)
return 0;

cancel_delayed_work_sync(&host->disable);

if (host->enabled)
return 0;

if (host->ops->enable) {
int err;

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

if (err) {
pr_debug("%s: enable error %d\n",
mmc_hostname(host), err);
return err;
}
}
host->enabled = 1;
return 0;
}

Copyright © Linux教程網 All Rights Reserved