• platform_set_drvdata()/platform_get_drvdata()/container_of()【转】


    本文转载自:http://blog.csdn.net/angle_birds/article/details/8443695

    platform_set_drvdata(struct platform_device *pdev, void *data)

    platform_get_drvdata(const struct platform_device *pdev):
    驱动中常用到platform_set_drvdata 和 platform_get_drvdata这两个函数,用于保存局部变量:
    include/linux/platform_device.h中:
    static inline void *platform_get_drvdata(const struct platform_device *pdev)
    {
            return dev_get_drvdata(&pdev->dev);
    }
    static inline void platform_set_drvdata(struct platform_device *pdev, void *data)
    {
            dev_set_drvdata(&pdev->dev, data);
    }
     
    static inline void
    dev_set_drvdata (struct device *dev, void *data)
    {
        dev->driver_data = data;
    }
    就是吧data赋值给dev->driver_data,pdev是平台总线设备,对于整个驱动是可见的,所以可以通过platform_get_drvdata来获取data。
     
    marvell sd驱动eg:
    chip是在probe函数中定义的局部变量,如果想在其他地方使用它怎么办呢? 这就需要把它保存起来。内核提供了这个方法,使用函数platform_set_drvdata()可以将chip保存成平台总线设备的私有
    数据。以后再要使用它时只需调用platform_get_drvdata()就可以了。
    static int sdhci_mv_probe(struct platform_device *pdev)
    {
     struct sdhci_mv_chip *chip;
     struct sdhci_mv_slot *slot;
     chip = kzalloc(sizeof(struct sdhci_mv_chip), GFP_KERNEL);
     if (!chip) {
      ret = -ENOMEM;
      goto err;
     }
     chip->fixes = (sdhci_mv_get_interface(pdev) == INTERFACE_SDIO0)? &sdhci0_fixes : &sdhci1_fixes;
     if (chip->fixes)
         chip->quirks = chip->fixes->quirks;
     platform_set_drvdata(pdev, chip);
    }
    chip是局部变量,在驱动其他函数使用时,eg:
    static int __devexit sdhci_mv_remove(struct platform_device *pdev)
    {
     int i;
     struct sdhci_mv_chip *chip;
     chip = platform_get_drvdata(pdev);
     if (chip) {
      for (i = 0;i < chip->num_slots; i++)
       sdhci_mv_remove_slot(chip->slots[i]);
      platform_set_drvdata(pdev, NULL);
      kfree(chip);
     }
     return 0;
    }
     
    container_of(ptr, type, member)
    问题:如何通过结构中的某个变量获取结构本身的指针???
    container_of(ptr, type, member)宏的作用是 传入结构体类型type的域member的地址ptr,返回该结构体变量的首地址。
    member是结构体类型type的成员,ptr是成员member的实例,返回ptr的入口地址;即通过结构体中一个成员的地址来得到此成员所在结构体的地址。
    关于container_of见kernel.h中:
    /**
    * container_of - cast a member of a structure out to the containing structure
    * @ptr:     the pointer to the member.
    * @type:     the type of the container struct this is embedded in.
    * @member:     the name of the member within the struct.
    *
    */
    #define container_of(ptr, type, member) ({             /
             const typeof( ((type *)0)->member ) *__mptr = (ptr);     /
             (type *)( (char *)__mptr - offsetof(type,member) );})
    container_of在Linux Kernel中的应用非常广泛,它用于获得某结构中某成员的入口地址.
     
     
    /* sprd keypad backlight */
    struct sprd_lcd_led {
    struct platform_device *pdev;
    struct mutex mutex;
    struct work_structwork;
    spinlock_t value_lock;
    enum led_brightness value;
    struct led_classdev cdev;
    int enabled;
    int suspend;
    struct early_suspend sprd_early_suspend_desc;
    };
    static void led_work(structwork_struct*work)
    {                                       // 传入的参数是结构体类型sprd_lcd_led 的成员work的实例的地址
    structsprd_lcd_led*led =container_of(work, struct sprd_lcd_led, work);
    unsigned long flags;
    mutex_lock(&led->mutex);
    spin_lock_irqsave(&led->value_lock, flags);
    if (led->value == LED_OFF || led->suspend) {
    spin_unlock_irqrestore(&led->value_lock, flags);
    sprd_led_disable(led);
    goto out;
    }
    spin_unlock_irqrestore(&led->value_lock, flags);
    sprd_led_enable(led);
    out:
    mutex_unlock(&led->mutex);
    }
    static void sprd_lcd_led_shutdown(structplatform_device*pdev) 
    {                                          //传入的参数为platform_device 类型,所以使用platform_get_drvdata()来获取platform_device->device->driver_data

    struct sprd_lcd_led*led =platform_get_drvdata(pdev);
    mutex_lock(&led->mutex);
    led->value = LED_OFF;
    led->enabled = 1;
    sprd_led_disable(led);
    mutex_unlock(&led->mutex);
    }
    static int sprd_lcd_led_probe(structplatform_device*pdev)
    {
    struct sprd_lcd_led*led;//局部变量
    int ret;
    ...............................................
    led = kzalloc(sizeof(*led), GFP_KERNEL);
    platform_set_drvdata(pdev, led);//局部变量保存到pdev->dev->driver_data      (platform_device->device->driver_data)
    ...............................................
    }
  • 相关阅读:
    MuJS官网示例讲解
    Windows下用Bochs编译运行Linux-0.11(转)
    mysql数据库设置远程连接权限
    Courses in Computer Science and Engineering
    docker-ce 安装和卸载
    实现自定义docker 镜像共享
    cmakelists.txt中配置openg环境出现: undefined reference to symbol 'glLightfv'
    ubuntu16.04如何查看内存和CPU的使用情况
    ROS
    QT_OPENGL-------- 5.model
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6945028.html
Copyright © 2020-2023  润新知