diff options
Diffstat (limited to 'sys/compat/linuxkpi/common/include/linux/device.h')
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/device.h | 233 |
1 files changed, 148 insertions, 85 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h index abafcd7ba5c4..668fe9cb8650 100644 --- a/sys/compat/linuxkpi/common/include/linux/device.h +++ b/sys/compat/linuxkpi/common/include/linux/device.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2021-2022 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,11 +29,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DEVICE_H_ -#define _LINUX_DEVICE_H_ +#ifndef _LINUXKPI_LINUX_DEVICE_H_ +#define _LINUXKPI_LINUX_DEVICE_H_ #include <linux/err.h> #include <linux/types.h> @@ -37,18 +39,21 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/compiler.h> -#include <linux/types.h> #include <linux/module.h> #include <linux/workqueue.h> #include <linux/kdev_t.h> #include <linux/backlight.h> +#include <linux/pm.h> +#include <linux/idr.h> +#include <linux/overflow.h> +#include <linux/ratelimit.h> /* via linux/dev_printk.h */ +#include <linux/fwnode.h> #include <asm/atomic.h> #include <sys/bus.h> #include <sys/backlight.h> struct device; -struct fwnode_handle; struct class { const char *name; @@ -64,6 +69,7 @@ struct class { struct dev_pm_ops { int (*prepare)(struct device *dev); + void (*complete)(struct device *dev); int (*suspend)(struct device *dev); int (*suspend_late)(struct device *dev); int (*resume)(struct device *dev); @@ -76,6 +82,7 @@ struct dev_pm_ops { int (*poweroff_late)(struct device *dev); int (*restore)(struct device *dev); int (*restore_early)(struct device *dev); + int (*suspend_noirq)(struct device *dev); int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); @@ -121,6 +128,8 @@ struct device { spinlock_t devres_lock; struct list_head devres_head; + + struct dev_pm_info power; }; extern struct device linux_root_device; @@ -180,14 +189,47 @@ show_class_attr_string(struct class *class, struct class_attribute_string class_attr_##_name = \ _CLASS_ATTR_STRING(_name, _mode, _str) -#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_dbg(dev, fmt, ...) do { } while (0) #define dev_printk(lvl, dev, fmt, ...) \ - device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + +#define dev_emerg(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_alert(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_dbg(dev, fmt, ...) do { } while (0) + +#define dev_WARN(dev, fmt, ...) \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#define dev_WARN_ONCE(dev, condition, fmt, ...) do { \ + static bool __dev_WARN_ONCE; \ + bool __ret_warn_on = (condition); \ + if (unlikely(__ret_warn_on)) { \ + if (!__dev_WARN_ONCE) { \ + __dev_WARN_ONCE = true; \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__); \ + } \ + } \ +} while (0) + +#define dev_info_once(dev, ...) do { \ + static bool __dev_info_once; \ + if (!__dev_info_once) { \ + __dev_info_once = true; \ + dev_info(dev, __VA_ARGS__); \ + } \ +} while (0) + +#define dev_warn_once(dev, ...) do { \ + static bool __dev_warn_once; \ + if (!__dev_warn_once) { \ + __dev_warn_once = 1; \ + dev_warn(dev, __VA_ARGS__); \ + } \ +} while (0) #define dev_err_once(dev, ...) do { \ static bool __dev_err_once; \ @@ -197,6 +239,14 @@ show_class_attr_string(struct class *class, } \ } while (0) +#define dev_dbg_once(dev, ...) do { \ + static bool __dev_dbg_once; \ + if (!__dev_dbg_once) { \ + __dev_dbg_once = 1; \ + dev_dbg(dev, __VA_ARGS__); \ + } \ +} while (0) + #define dev_err_ratelimited(dev, ...) do { \ static linux_ratelimit_t __ratelimited; \ if (linux_ratelimited(&__ratelimited)) \ @@ -209,6 +259,12 @@ show_class_attr_string(struct class *class, dev_warn(dev, __VA_ARGS__); \ } while (0) +#define dev_dbg_ratelimited(dev, ...) do { \ + static linux_ratelimit_t __ratelimited; \ + if (linux_ratelimited(&__ratelimited)) \ + dev_dbg(dev, __VA_ARGS__); \ +} while (0) + /* Public and LinuxKPI internal devres functions. */ void *lkpi_devres_alloc(void(*release)(struct device *, void *), size_t, gfp_t); void lkpi_devres_add(struct device *, void *); @@ -227,6 +283,22 @@ int lkpi_devres_destroy(struct device *, void(*release)(struct device *, void *) void lkpi_devres_release_free_list(struct device *); void lkpi_devres_unlink(struct device *, void *); void lkpi_devm_kmalloc_release(struct device *, void *); +#define devm_kfree(_d, _p) lkpi_devm_kmalloc_release(_d, _p) + +static inline const char * +dev_driver_string(const struct device *dev) +{ + driver_t *drv; + const char *str = ""; + + if (dev->bsddev != NULL) { + drv = device_get_driver(dev->bsddev); + if (drv != NULL) + str = drv->name; + } + + return (str); +} static inline void * dev_get_drvdata(const struct device *dev) @@ -270,6 +342,8 @@ put_device(struct device *dev) kobject_put(&dev->kobj); } +struct class *class_create(struct module *owner, const char *name); + static inline int class_register(struct class *class) { @@ -294,6 +368,12 @@ static inline struct device *kobj_to_dev(struct kobject *kobj) return container_of(kobj, struct device, kobj); } +struct device *device_create(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const char *fmt, ...); +struct device *device_create_groups_vargs(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const struct attribute_group **groups, + const char *fmt, va_list args); + /* * Devices are registered and created for exporting to sysfs. Create * implies register and register assumes the device fields have been @@ -354,47 +434,6 @@ device_create_release(struct device *dev) } static inline struct device * -device_create_groups_vargs(struct class *class, struct device *parent, - dev_t devt, void *drvdata, const struct attribute_group **groups, - const char *fmt, va_list args) -{ - struct device *dev = NULL; - int retval = -ENODEV; - - if (class == NULL || IS_ERR(class)) - goto error; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - retval = -ENOMEM; - goto error; - } - - dev->devt = devt; - dev->class = class; - dev->parent = parent; - dev->groups = groups; - dev->release = device_create_release; - /* device_initialize() needs the class and parent to be set */ - device_initialize(dev); - dev_set_drvdata(dev, drvdata); - - retval = kobject_set_name_vargs(&dev->kobj, fmt, args); - if (retval) - goto error; - - retval = device_add(dev); - if (retval) - goto error; - - return dev; - -error: - put_device(dev); - return ERR_PTR(retval); -} - -static inline struct device * device_create_with_groups(struct class *class, struct device *parent, dev_t devt, void *drvdata, const struct attribute_group **groups, const char *fmt, ...) @@ -465,9 +504,9 @@ device_unregister(struct device *dev) dev->bsddev = NULL; if (bsddev != NULL && dev->bsddev_attached_here) { - mtx_lock(&Giant); + bus_topo_lock(); device_delete_child(device_get_parent(bsddev), bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); } put_device(dev); } @@ -481,15 +520,12 @@ device_del(struct device *dev) dev->bsddev = NULL; if (bsddev != NULL && dev->bsddev_attached_here) { - mtx_lock(&Giant); + bus_topo_lock(); device_delete_child(device_get_parent(bsddev), bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); } } -struct device *device_create(struct class *class, struct device *parent, - dev_t devt, void *drvdata, const char *fmt, ...); - static inline void device_destroy(struct class *class, dev_t devt) { @@ -514,10 +550,10 @@ device_release_driver(struct device *dev) dev_set_drvdata(dev, NULL); /* Do not call dev->release! */ - mtx_lock(&Giant); + bus_topo_lock(); if (device_is_attached(dev->bsddev)) device_detach(dev->bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); #endif } @@ -527,40 +563,45 @@ device_reprobe(struct device *dev) int error; device_release_driver(dev); - mtx_lock(&Giant); + bus_topo_lock(); error = device_probe_and_attach(dev->bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); return (-error); } -#define dev_pm_set_driver_flags(dev, flags) do { \ -} while (0) - static inline void -linux_class_kfree(struct class *class) +device_set_wakeup_enable(struct device *dev __unused, bool enable __unused) { - kfree(class); + /* + * XXX-BZ TODO This is used by wireless drivers supporting WoWLAN which + * we currently do not support. + */ } -static inline struct class * -class_create(struct module *owner, const char *name) +static inline int +device_wakeup_enable(struct device *dev) { - struct class *class; - int error; - class = kzalloc(sizeof(*class), M_WAITOK); - class->owner = owner; - class->name = name; - class->class_release = linux_class_kfree; - error = class_register(class); - if (error) { - kfree(class); - return (NULL); - } + device_set_wakeup_enable(dev, true); + return (0); +} - return (class); +static inline bool +device_iommu_mapped(struct device *dev __unused) +{ + return (false); +} + +#define dev_pm_set_driver_flags(dev, flags) do { \ +} while (0) + +static inline void +linux_class_kfree(struct class *class) +{ + + kfree(class); } static inline void @@ -629,10 +670,32 @@ devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) return (p); } +static inline void * +devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp) +{ + void *dst; + + if (len == 0) + return (NULL); + + dst = devm_kmalloc(dev, len, gfp); + if (dst != NULL) + memcpy(dst, src, len); + + return (dst); +} + #define devm_kzalloc(_dev, _size, _gfp) \ devm_kmalloc((_dev), (_size), (_gfp) | __GFP_ZERO) #define devm_kcalloc(_dev, _sizen, _size, _gfp) \ devm_kmalloc((_dev), ((_sizen) * (_size)), (_gfp) | __GFP_ZERO) -#endif /* _LINUX_DEVICE_H_ */ +int lkpi_devm_add_action(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action(dev, action, data) \ + lkpi_devm_add_action(dev, action, data); +int lkpi_devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action_or_reset(dev, action, data) \ + lkpi_devm_add_action_or_reset(dev, action, data) + +#endif /* _LINUXKPI_LINUX_DEVICE_H_ */ |