aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linuxkpi/common/include/linux/device.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linuxkpi/common/include/linux/device.h')
-rw-r--r--sys/compat/linuxkpi/common/include/linux/device.h233
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_ */