zoukankan      html  css  js  c++  java
  • devres in linux driver

    写 driver 时, probe 中常常要为设备分配一些资源, 如 内存 / irq / gpio / iomap 等. 而在 probe 中失败时又要小心的释放掉这些资源. 底层驱动开发人员可能会把大部分精力放在 probe 成功的处理流程上, 而失败的情况可能出现的较少以致于忘记测试. 这导致的一个问题是当设备加载失败时, 系统中会遗留许多与之相关的资源.

    为了干净优雅的处理这种问题, 驱动模型中引入了 devres 机制. 在为 device 分配资源的时候记录下它们, 等到 device detach 的时候, 就可以统一释放.

    devres 是一种资源管理机制, 类似于一种垃圾收集处理器. 而资源的处理时机在 driver 的 install / remove 时候. 这样我们在为 device 分配相关资源之后, 就不必要关心如何释放它们了. 与 device 相关的资源有 memory / dma / iomap / regmap / interrupt / gpio 等, 这些资源都可以用 devres 机制管理起来, 使用相关资源封闭的 devres 接口, 就可以让这些资源自动销毁.

    API: drivers/base/devres.c

    1. void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
    申请 "sizeof(struct devres) + size" 大小的内存, size 是指resource的大小. 清0内存, 初始化链表节点 dr->node.entry, 返回 resouce 的指针.

    2. void devres_free(void *res)
    由 resource 指针定位到 devres 结构体指针, 然后 kfree 掉.

    3. void devres_add(struct device *dev, void *res)
    将 res 对应的 devres 结构体加入到 dev 的资源管理链表 dev->devres_head 上.

    4. void * devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
    在 dev->devres_head 链表中查找 release / match_data 都匹配的 devres 结构. 并返回 devres 中的 resource 指针 dr->data.

    5. void * devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data)
    在 dev->devres_head 中查找 new_res 这个资源是否已经存在, 如果没找到, 则把 new_res 添加到链表中. 如果找到了, 则销毁 new_dr.

    6. void * devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
    在 dev->devres_head 链表中查找 release / match_data 都匹配的 devres 结构. 并将其中 dev->devres_head 链表中移除.

    7. int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
    在 devices 管理的资源中找到匹配的, 然后移除并销毁它.

    8. int devres_release_all(struct device *dev)
    release_nodes() 先将 [first, end] 区间的所有节点都移动到todo链表里, 然后删除todo链表(kfree 掉todo链表的所有节点).
    devres_release_all()会在device detach时或 device 的 probe 失败时调用. 如此一来, 我们只需分配资源, 无需再关心资源释放了.
    这个函数的调用也是 devres 机制的关键所在.

    删除链表的时候使用到了 list_for_each_entry_safe_reverse() , 这个宏安全在哪里?
    遍历链表的过程中, 我们可能会删除节点. 这个宏 safe 在于它会先记录下一个节点, 然后再操作当前节点. 这样如果当前节点被del掉了, 下一个节点还是可以安全的访问到.

    9. void * devres_open_group(struct device *dev, void *id, gfp_t gfp)

    10. void devres_close_group(struct device *dev, void *id)

    11. void devres_remove_group(struct device *dev, void *id)

    12. int devres_release_group(struct device *dev, void *id)


    使用到 devres 机制的模块:

    drivers/base/dma-mapping.c
    kernel/irq/devres.c
    mm/dmapool.c
    drivers/gpio/devres.c
    drivers/base/regmap/regmap.c
    drivers/regulator/core.c
    drivers/base/regmap/regmap.c
    drivers/base/devres.c
    drivers/pci/pci.c


    参考文献:
    Documentation/driver-model/devres.txt
    http://lwn.net/Articles/222860/

  • 相关阅读:
    [洛谷 U68862] 奶牛滑迷宫 题解
    STL的妙用(二)——洛谷 P2073 送花
    平衡树 x 01-trie √
    最小生成树(大纲,待补全)
    单源最短路算法
    黑科技:如何提高整数域内高斯消元的精度和速度——高斯消元与辗转相除法的结合
    Scratch的入门笔记
    Ubuntu18.04安装Tensorflow
    Ubuntu18.04安装英伟达显卡驱动
    macOS下appstore提示未能完成该操作的解决办法
  • 原文地址:https://www.cnblogs.com/sammei/p/3498052.html
Copyright © 2011-2022 走看看