The Road to Linux Kernel - GPIO Subsystem - GPIO Devres, Managed Device Resource(3)

3 篇文章 0 订阅
2 篇文章 0 订阅

GPIO Devres

之前常用的gpio接口,需要对申请的资源进行管理,如果要管理多个资源,这是很麻烦的一件事,Is there a easier way?
调用下面的接口,将申请的资源与device绑定,就不需要手动管理这些资源了:

  devm_gpiod_get()
  devm_gpiod_get_index()
  devm_gpiod_get_index_optional()
  devm_gpiod_get_optional()
  devm_gpiod_put()
  devm_gpiod_unhinge()
  devm_gpiochip_add_data()
  devm_gpio_request()
  devm_gpio_request_one()
  devm_gpio_free()

其实很多资源都可以用这种方法进行管理的,这个在Documentation/driver-api/driver-model/devres.rst中有简单的介绍。
那么,对资源进行管理都发生在什么时候呢:

  • 驱动remove时
  • 驱动probe失败时
  • 驱动响应一个事件时临时申请释放的资源

devres机制可以对这些资源全部进行管理吗?这个有待商榷,至少第三种资源是不适合的。不过这种资源可以通过devres group机制进行管理。
那先看第一种,接下来以platform驱动为例,查看函数platform_driver_unregister

platform_driver_unregister
			|
			V
driver_unregister
			|
			V
bus_remove_driver
			|
			V
driver_detach
			|
			V
device_release_driver_internal
			|
			V
__device_release_driver

一直跟踪,在__device_release_driver中有一个与devres机制相关的函数调用devres_release_all,将其展开,不用查看函数内部,看注释该函数的功能,是将device所绑定的资源全部release。所以说,只要使用devres机制,在驱动probe函数获取的资源,就不需要在驱动remove时进行释放了。

/**
 * devres_release_all - Release all managed resources
 * @dev: Device to release resources for
 *
 * Release all resources associated with @dev.  This function is
 * called on driver detach.
 */
int devres_release_all(struct device *dev)
{
	unsigned long flags;

	/* Looks like an uninitialized device structure */
	if (WARN_ON(dev->devres_head.next == NULL))
		return -ENODEV;
	spin_lock_irqsave(&dev->devres_lock, flags);
	return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
			     flags);
}

接下来看第二种情况,驱动probe失败时,devres机制可以对这种资源进行管理吗,接下来以platform驱动为例,跟踪platform_driver_register

platform_driver_register
			|
			V
__platform_driver_register
			|
			V
driver_register
			|
			V
bus_add_driver
			|
			V
driver_attach
			|
			V
bus_for_each_dev
			|
			V
__driver_attach
			|
			V
device_driver_attach
			|
			V
driver_probe_device
			|
			V
really_probe

really_probe函数展开,下面的函数只保留本次分析的关键点,在调用驱动的probe时,若probe失败,会调用devres_release_all将probe时获取的资源释放掉。

static int really_probe(struct device *dev, struct device_driver *drv)
{
	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {
		ret = drv->probe(dev);
		if (ret)
			goto probe_failed;
	}

probe_failed:
	if (dev->bus)
		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
					     BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
pinctrl_bind_failed:
	device_links_no_driver(dev);
	devres_release_all(dev);
}

对devres机制要有更深入的了解,可以查看源码drivers/gpio/gpiolib-devres.c,及drivers/base/devres.c等等。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值