Linux设备模型之mmc,sd子系统<三>


####看一下重要的卡扫描函数,mmc_rescan,卡就指着他
####活着呢,

相关阅读:

Linux设备模型之mmc,sd子系统<一>

Linux设备模型之mmc,sd子系统<二> 

/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;
}

  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容