我应该在使用由 `gpio_to_desc` 返回的 `gpio_desc` 之前使用 `gpio_free` 吗?

Should I use `gpio_free` before using `gpio_desc` which is returned by `gpio_to_desc`?

2020/10/31更新

感谢 0andriy asking the question on mailing list. And Alexandre Courbot aka Gunurou 我的问题!

再次感谢0andriy!你才是这个问题背后真正的英雄。


老问题:

这个问题似乎是文档中的错字,但我想仔细检查一下。

我的问题是GPIO Descriptor Consumer Interface最后一节的最后两段。

the following two functions allow you to convert a GPIO descriptor into the GPIO integer namespace and vice-versa:

int desc_to_gpio(const struct gpio_desc *desc)
struct gpio_desc *gpio_to_desc(unsigned gpio)

The GPIO number returned by desc_to_gpio() can be safely used as long as the GPIO descriptor has not been freed. All the same, a GPIO number passed to gpio_to_desc() must have been properly acquired, and usage of the returned GPIO descriptor is only possible after the GPIO number has been released.

Freeing a GPIO obtained by one API with the other API is forbidden and an unchecked error.

我对每句话的理解

The GPIO number returned by desc_to_gpio() can be safely used as long as the GPIO descriptor has not been freed.

gpiod_put() 释放描述符之前可以使用任何 GPIO 引脚。以下是我理解的伪代码。

struct gpio_desc desc = gpiod_get(...);
gpio pin = desc_to_gpio(desc);

// operation here

gpiod_put(desc);

All the same, a GPIO number passed to gpio_to_desc() must have been properly acquired, and usage of the returned GPIO descriptor is only possible after the GPIO number has been released.

我对 "All the same""usage of the returned GPIO descriptor is only possible after the GPIO number has been released" 感到困惑。

如果 "All the same" 适用,我认为 gpio_desc 可以在 gpio_free() 之前使用。但是“只有在 GPIO 编号被释放后才能使用 returned GPIO 描述符”让我觉得我必须 gpio_free() 在使用 gpio_desc returned 来自 gpio_to_desc().

为了重申我的问题,以下哪个代码片段应该是 gpio_to_desc() 的正确用法? 我假设 "usage of the returned GPIO descriptor" 表示来自 gpio_to_desc().

gpio_desc return

我认为第二个应该是不正确的,但我想通过任何文档或示例对其进行确认。

  1. 免费前使用gpio_desc
    gpio pin = gpio_request( ... );
    struct gpio_desc desc = gpio_to_desc(pin);
    
    // gpiod operation here, before free
    
    gpio_free(gpio_desc)
  1. 免费后使用 gpio_desc
    gpio pin = gpio_request( ... );
    struct gpio_desc desc = gpio_to_desc(pin);
    gpio_free(gpio_desc)
    
    // gpiod operation here, after free

也就是说,应该

“只有在释放 GPIO 编号后才能使用 returned GPIO 描述符”

改为

“只有在 GPIO 编号被释放之前 才能使用 returned GPIO 描述符”?


附带问题

根据这句话。

Freeing a GPIO obtained by one API with the other API is forbidden and an unchecked error.

我不应该发布由 gpio_to_desc() 编辑 gpiod_put() return 的 gpio_desc 吗?


Google 上的关键字。

  • gpio_to_desc() 必须先 gpio_free()

    没有官方文章提及它。

  • gpio_to_desc() gpiod_put()

    我找到了 header files。然而它并没有解释它。

All the same, a GPIO number passed to gpio_to_desc() must have been properly acquired, and usage of the returned GPIO descriptor is only possible after the GPIO number has been released.

after不应该改成before吗?

可能两者都不是。我猜这句话想表达的是不要混合遗留 gpio_XXX 和现代 gpiod_XXX API。例如。在使用 gpiod 个资源之前释放 gpio 个资源。

你是对的,使用gpio_free()之后的描述符是错误的。

在实践中,内核违反了陈述句本身,因为几乎每个 gpio 操作都使用 gpio_to_desc()。例如

void gpio_free(unsigned gpio)
{
    gpiod_free(gpio_to_desc(gpio));
}

static inline void __gpio_set_value(unsigned gpio, int value)
{
    return gpiod_set_raw_value(gpio_to_desc(gpio), value);
}

gpio_to_desc()desc_to_gpio()获取资源,但return指向现有对象的指针:

struct gpio_desc *gpio_to_desc(unsigned gpio)
{
  ...
            return &gdev->descs[gpio - gdev->base];
}
int desc_to_gpio(const struct gpio_desc *desc)
{
    return desc->gdev->base + (desc - &desc->gdev->descs[0]);
}

这个问题的简短回答是永远不要调用这些函数。它们自 2014 年以来就已过时,新代码应该没有理由使用它们。新代码应该只依赖于 gpiod_*() 系列函数,并且永远不要使用 GPIO 数字。

如果您处理旧代码,最安全的做法是首先将其转换为使用 gpiod 接口。

现在,如果您绝对需要使用这些功能,我的回忆是以下用法是有效的(从您的问题中复制):

struct gpio_desc desc = gpiod_get(...);
gpio pin = desc_to_gpio(desc);

// operation here

gpiod_put(desc);
gpio pin = gpio_request( ... );
struct gpio_desc desc = gpio_to_desc(pin);
   
// gpiod operation here, before free
  
gpio_free(gpio_desc)

这是因为 gpio_*() 系列函数构建在 gpiod 接口之上,如您在 drivers/gpio/gpiolib-legacy.c 中所见。因此,与您请求的 GPIO 编号对应的描述符将已被 gpiod_request() 获取,因此保证在 gpio_free() 之前一直有效(实际上只是调用 gpiod_free() 被调用。

关于你的附带问题:

Should I NOT release the gpio_desc with gpiod_put() returned by gpio_to_desc()?

没错,你永远不应该那样做。目前 API 的构建方式使得这样做 可能 有效,但不能保证它们将来不会分歧。此外,如果您获得了一个描述符,则没有理由不保留它以使用正确的 API.

释放它。

但同样,最好的做法是假设这些函数不存在,并尽可能使用 gpiod。