4244|0

4

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

一个关于MMC的问题 [复制链接]

今天看帖子看到一个关于MMC的问题,然后自己对照了一些最新的android4.1.2的内核源代码,发现问题依然存在。我将内容发布在这里供大家浏览,并希望TI的FAE可以尽快修复这个问题。
最近在測試 整個 kernel 功能的時候發現 , SD Card 移除的過程中 kernel 會"卡機" 約800mS , 這 800 mS 中 , 連 kernel driver 中的 add_timer() function 都停滯 !!
初步 判別 , 應該卡在 IRQ 中.

尋找了半天 ,發現 , Card remove 過程 , 會呼叫
int _mmc_detect_card_removed(struct mmc_host *host)
在這個 function 中 會呼叫 ret = host->bus_ops->alive(host);
alive() ; 在core/sd.c 中有註冊 , 內容是

static int mmc_sd_alive(struct mmc_host *host)
{
    return mmc_send_status(host->card, NULL);
}

好玩的事情來了 , Card 已經拔除 , 還送 status command 給 Host !!

mmc_send_status() 定義在 mmc_ops.c  中

int mmc_send_status(struct mmc_card *card, u32 *status)
{
    int err;
    struct mmc_command cmd = {0};

    BUG_ON(!card);
    BUG_ON(!card->host);

    cmd.opcode = MMC_SEND_STATUS;
    if (!mmc_host_is_spi(card->host))
        cmd.arg = card->rca << 16;
    cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;

    err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
    if (err)
        return err;

    /* NOTE: callers are required to understand the difference
     * between "native" and SPI format status words!
     */
    if (status)
        *status = cmd.resp[0];

    return 0;
}

送出 command 後要等  cmd done. cmd done 需要 mmc controller 的irq 中斷 .
AM335x BSP 的 mmc 中斷流程如下:

omap_hsmmc_irq()
   omap_hsmmc_do_irq()
      ## if have error.
          omap_hsmmc_reset_controller_fsm()

主要卡在 omap_hsmmc_reset_controller_fsm() 中.

首先 , 我不喜歡 IRQ 執行太多事情 , 所以先用 tasklet 分開 ,這時候要注意 , MMC 的 IRQ 會一直送 ,直到IRQ 事件處理完畢 , tasklet 只能排程一次 , 所以要先關閉   IRQ , 等 tasklit 完成後在打開.

修改後如下:

static void omap_hsmmc_irq_tasklet(unsigned long arg)
{
struct omap_hsmmc_host *host = (struct omap_hsmmc_host *) arg;

    omap_hsmmc_do_irq(host, host->irq_status,host->irq);

//---- reenable mmc irq signal.

    OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
    spin_unlock(&host->irq_lock);

}

static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
{
struct omap_hsmmc_host *host = dev_id;


#if defined(USING_TASKLET)

//---- disable mmc irq signal.
    spin_lock(&host->irq_lock);
    OMAP_HSMMC_WRITE(host->base, ISE, 0);

    host->irq_status = OMAP_HSMMC_READ(host->base, STAT);

    tasklet_schedule(&host->omap_irq_tasklet);

#else

int status;

    status = OMAP_HSMMC_READ(host->base, STAT);
    do {
        omap_hsmmc_do_irq(host, status, irq);
        /* Flush posted write */
        status = OMAP_HSMMC_READ(host->base, STAT);
    } while (status & INT_EN_MASK);


#endif

    return IRQ_HANDLED;
}

這樣後還是會 "卡機" , 看一下主要卡住的地方 omap_hsmmc_reset_controller_fsm()

unsigned long limit = (loops_per_jiffy  *
            msecs_to_jiffies(MMC_TIMEOUT_MS));

..............
...............

        while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) &&
                    (i++ < limit))
            cpu_relax();


首先 , cpu_relax() 其實應該是 一堆 NOP 指令(我之前沒有用過@@) , 主要是 loops_per_jiffy 這個參數 ,這個參數應該是每秒執行多少個 nop 指令 , 所以上面這樣的 code 感覺怪怪的 , 這個 cpu_relax() + OMAP_HSMMC_READ + 其他判別 的 code 會執行 數百萬次 ....當然會卡住 !!
都改成 tacklet 了 , 就想說換成一般 mdelay 的方式 , 這個 limit 只是 timeout 的變數, 沒有太大影響. 修改後如下:

static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
                           unsigned long bit)
{
unsigned long i = 0;

#if !defined(USING_TASKLET)
unsigned long limit = (loops_per_jiffy  *
            msecs_to_jiffies(MMC_TIMEOUT_MS));
#endif

    OMAP_HSMMC_WRITE(host->base, SYSCTL,
             OMAP_HSMMC_READ(host->base, SYSCTL) | bit);

    /*
     * OMAP4 ES2 and greater has an updated reset logic.
     * Monitor a 0->1 transition first
     */
    if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET)
    {

#if defined(USING_TASKLET)
        while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) &&
                    (i++ < MMC_TIMEOUT_MS))
            mdelay(1);

#else
        while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) &&
                    (i++ < limit))
            cpu_relax();
#endif
......................
}
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表