linux sdio card睡眠治疗 sdio card removed解决方案

摘要:
最近,当调试多个sdiocard挂起时,将显示sdiocardremoved,然后系统将崩溃或模块将无法正常工作。根本原因是睡眠处理不当。昨天终于找到了解决办法。1: 主机侧必须设置为不可移动。软件设置:mmc->caps|=MMC_ CAP_不可移除;2: 主机端需要在sdioc中设置keepbower
         近期调试几款sdio card suspend时都会出现sdio card removed,之后 

要么死机要么模块不能正常工作。根本原因也就是休眠没有处理好。昨天最终找到了

解决方法。

         1:host端须要设置nonremovable,软件设置:mmc->caps |= 
MMC_CAP_NONREMOVABLE;
         2:host端须要设置keep power,在sdio card suspend时 软件设 
置:host->pm_flags | = MMC_PM_KEEP_POWER;


         眼下我所接触到的4g网卡,博通网卡,sdio加密t卡等都会出现card 
removed问题。



         关于2补充下须要在sdio card pm中置host keep power:


         static int XXX_suspend(struct device *pdev)
{
     struct sdio_func *func = dev_to_sdio_func(pdev);

     /* keep power while host suspended */
     ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
     if (ret) {
         sd_err(("%s: error while trying to keep power
", __FUNCTION__));
         return ret;
     }

     return 0;
}

static const struct dev_pm_ops XXX_pm_ops = {
     .suspend    = XXX_suspend,
     .resume        = XXX_resume,
};


          今天花了点时间理清了card removed的原因。

        出现1错误的原因是在resume 时pm_notify调用到了msm_rescan,假设没 
有置nonremovable,将会跑进detect,而进去就会detect出了card removed,
进而进行了移除操作。



       
  void mmc_rescan(struct work_struct *work)
     {
         struct mmc_host *host =
             container_of(work, struct mmc_host, detect.work);
         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);
         ---------
     }
         以下是dump_stack()打印的调用信息:
<4>[   48.709320] [<c0013d4c>] (unwind_backtrace+0x0/0x11c) from 
[<bf011d74>] (dhdsdio_disconnect+0xc/0x10c [bcmdhd])
<4>[   48.720214] [<bf011d74>] (dhdsdio_disconnect+0xc/0x10c [bcmdhd]) 
from [<bf01f9a8>] (bcmsdh_remove+0x1c/0x98 [bcmdhd])
<4>[   48.730041] [<bf01f9a8>] (bcmsdh_remove+0x1c/0x98 [bcmdhd]) from 
[<bf001a00>] (bcmsdh_sdmmc_remove+0x28/0x70 [bcmdhd])
<4>[   48.740600] [<bf001a00>] (bcmsdh_sdmmc_remove+0x28/0x70 [bcmdhd]) 
from [<c05855e0>] (sdio_bus_remove+0x38/0xf0)
<4>[   48.753021] [<c05855e0>] (sdio_bus_remove+0x38/0xf0) from 
[<c03a26c8>] (__device_release_driver+0x9c/0xe0)
<4>[   48.762725] [<c03a26c8>] (__device_release_driver+0x9c/0xe0) from 
[<c03a2728>] (device_release_driver+0x1c/0x28)
<4>[   48.771881] [<c03a2728>] (device_release_driver+0x1c/0x28) from 
[<c03a21f8>] (bus_remove_device+0x124/0x140)
<4>[   48.781829] [<c03a21f8>] (bus_remove_device+0x124/0x140) from 
[<c039fe30>] (device_del+0x108/0x16c)
<4>[   48.790802] [<c039fe30>] (device_del+0x108/0x16c) from 
[<c058596c>] (sdio_remove_func+0x1c/0x28)
<4>[   48.799560] [<c058596c>] (sdio_remove_func+0x1c/0x28) from 
[<c0584bfc>] (mmc_sdio_remove+0x3c/0x68)
<4>[   48.808593] [<c0584bfc>] (mmc_sdio_remove+0x3c/0x68) from 
[<c0584cb4>] (mmc_sdio_detect+0x8c/0xb4)
<4>[   48.817565] [<c0584cb4>] (mmc_sdio_detect+0x8c/0xb4) from 
[<c057e0c8>] (mmc_rescan+0x7c/0x2d8)
<4>[   48.826141] [<c057e0c8>] (mmc_rescan+0x7c/0x2d8) from [<c0099dd8>] 
(process_one_work+0x27c/0x484)
<4>[   48.834991] [<c0099dd8>] (process_one_work+0x27c/0x484) from 
[<c009a1f0>] (worker_thread+0x210/0x3b0)
<4>[   48.844177] [<c009a1f0>] (worker_thread+0x210/0x3b0) from 
[<c009e08c>] (kthread+0x80/0x8c)
<4>[   48.852355] [<c009e08c>] (kthread+0x80/0x8c) from [<c000eaa8>] 
(kernel_thread_exit+0x0/0x8)
<6>[   49.083587] mmc2: card 0001 removed


          出现2错误的原因是在sdio resume时,假设没有设置keep power就会 
跑sdio reset与go idle(CMD 0)后进入init_card第一个CMD就不会响应了。也就是
这2个操作后card异常了。



  
static int mmc_sdio_resume(struct mmc_host *host)
{
     int i, err = 0;

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

     /* Basic card reinitialization. */
     mmc_claim_host(host);

     /* No need to reinitialize powered-resumed nonremovable cards */
     if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
         sdio_reset(host);
         mmc_go_idle(host);
         err = mmc_sdio_init_card(host, host->ocr, host->card,
                     mmc_card_keep_power(host));
         ---------
}
        下面是dump_stack()信息打印:
     <4>[   55.269378] [<c0013d4c>] (unwind_backtrace+0x0/0x11c) from 
[<c057d650>] (mmc_resume_host+0xec/0x15c)
<4>[   55.269439] [<c057d650>] (mmc_resume_host+0xec/0x15c) from 
[<c058bfdc>] (msmsdcc_runtime_resume+0xb8/0x17c)
<4>[   55.269500] [<c058bfdc>] (msmsdcc_runtime_resume+0xb8/0x17c) from 
[<c058c2ac>] (msmsdcc_pm_resume+0x44/0xa8)
<4>[   55.269561] [<c058c2ac>] (msmsdcc_pm_resume+0x44/0xa8) from 
[<c03a4074>] (platform_pm_resume+0x40/0x54)
<4>[   55.269653] [<c03a4074>] (platform_pm_resume+0x40/0x54) from 
[<c03a8160>] (dpm_run_callback+0x44/0x7c)
<4>[   55.269683] [<c03a8160>] (dpm_run_callback+0x44/0x7c) from 
[<c03a8c18>] (device_resume+0x140/0x184)
<4>[   55.269744] [<c03a8c18>] (device_resume+0x140/0x184) from 
[<c03a94ec>] (dpm_resume+0xfc/0x234)
<4>[   55.269805] [<c03a94ec>] (dpm_resume+0xfc/0x234) from [<c03a97f0>] 
(dpm_resume_end+0xc/0x18)
<4>[   55.269866] [<c03a97f0>] (dpm_resume_end+0xc/0x18) from 
[<c00b63bc>] (suspend_devices_and_enter+0x240/0x314)
<4>[   55.269927] [<c00b63bc>] (suspend_devices_and_enter+0x240/0x314) 
from [<c00b65b0>] (pm_suspend+0x120/0x200)
<4>[   55.269958] [<c00b65b0>] (pm_suspend+0x120/0x200) from 
[<c00b7508>] (suspend+0x68/0x180)
<4>[   55.270019] [<c00b7508>] (suspend+0x68/0x180) from [<c0099dd8>] 
(process_one_work+0x27c/0x484)
<4>[   55.270080] [<c0099dd8>] (process_one_work+0x27c/0x484) from 
[<c009a1f0>] (worker_thread+0x210/0x3b0)
<4>[   55.270141] [<c009a1f0>] (worker_thread+0x210/0x3b0) from 
[<c009e08c>] (kthread+0x80/0x8c)
<4>[   55.270202] [<c009e08c>] (kthread+0x80/0x8c) from [<c000eaa8>] 
(kernel_thread_exit+0x0/0x8)
<4>[   55.270233] mmc2: error -110 during resume (card was removed?

)



以上2点做到了理论上kernel能够正常睡眠了,以下是正常的睡眠log:

linux sdio card睡眠治疗 sdio card removed解决方案第1张


版权声明:本文博客原创文章,博客,未经同意,不得转载。

免责声明:文章转载自《linux sdio card睡眠治疗 sdio card removed解决方案》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇底部浮动微信小程序页面引入公用头部底部下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

多密钥ssh-key生成与管理

由于 git 大文件用 http 方式难以传输,必须使用 ssh-key,而 ssh-key 又生成了好多个。最近在各种折腾 ssh,公钥私钥上花费了很多时间,现将一些问题总结如下。系统为 Mac/Linux。 密钥的原理 SSH之所以能够保证安全,原因在于它采用了公钥加密。 整个ssh密码登录过程是这样的: 用户向远程主机发登录请求:ssh user@...

嵌入式驱动开发之---Linux ALSA音频驱动(一)

本文的部分内容参考来自DroidPhone的博客(http://blog.csdn.net/droidphone/article/details/6271122),关于ALSA写得很不错的文章,只是少了实例。本文就是结合实例来分析ALSA音频驱动。 开发环境:ubuntu10.04 目标板:linux-2.6.37 (通过命令uname -r 查看lin...

Linux教程

  管道和重定向! 保持数据流动 介绍   在前两节中,我们看了一些可以为我们操作数据的过滤器。在本节中,我们将看到我们如何将它们结合在一起来执行更强大的数据操作。 本节涉及一些阅读。即使这些机制及其使用非常简单,但如果您希望有效使用这些机制,了解其行为的各种特征也很重要。 那么他们是什么? 我们在命令行上运行的每个程序都会自动连接三个数据流。 S...

Linux 根目录所在分区被脏数据占满

背景: ​ 公司在做一个项目,大概功能就是一个通行闸机的人脸识别系统,要经过门禁的人注册了之后,系统就会存储一张原始的图片在服务器的数据文件夹里面,包括了永久的存储和一些访客注册临时存储。一天周五的时候要使用df -h 查看根目录已经被占用98%,根目录挂载的分区有50G大小;当时显示的是还有3.8G可用,按照每个人脸产生的数据只有200K大小的话,根据...

Linux命令之dd

dd [OPERAND] dd 选项 复制一个文件,根据[OPERAND]进行转换和格式化 (1). OPERAND参数 说明1:dd的选项只有’--help’和’--version’,也就是帮助与版本信息。而下列都是[操作数],而非选项。 说明2:读取是输入,写入是输出 说明3:不指定if,默认从标准输入读取。如果不指定of,默认写入到标准输出 bs=B...

Linux内核分析总结

周子轩 原创作品转载注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 笔记: 冯诺依曼体系结构的核心思想是存储程序计算机。在计算机中有两种指令,一是用户指令,一是系统调用。 Linux是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统...