device.h revision 354616
163899Sarchie/*- 263899Sarchie * Copyright (c) 2010 Isilon Systems, Inc. 363899Sarchie * Copyright (c) 2010 iX Systems, Inc. 463899Sarchie * Copyright (c) 2010 Panasas, Inc. 563899Sarchie * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. 663899Sarchie * All rights reserved. 763899Sarchie * 863899Sarchie * Redistribution and use in source and binary forms, with or without 963899Sarchie * modification, are permitted provided that the following conditions 1063899Sarchie * are met: 1163899Sarchie * 1. Redistributions of source code must retain the above copyright 1263899Sarchie * notice unmodified, this list of conditions, and the following 1363899Sarchie * disclaimer. 1463899Sarchie * 2. Redistributions in binary form must reproduce the above copyright 1563899Sarchie * notice, this list of conditions and the following disclaimer in the 1663899Sarchie * documentation and/or other materials provided with the distribution. 1763899Sarchie * 1863899Sarchie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1963899Sarchie * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2063899Sarchie * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2163899Sarchie * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2263899Sarchie * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2363899Sarchie * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2463899Sarchie * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2563899Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2663899Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2763899Sarchie * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2863899Sarchie * 2963899Sarchie * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/device.h 354616 2019-11-11 15:28:27Z hselasky $ 3063899Sarchie */ 3163899Sarchie#ifndef _LINUX_DEVICE_H_ 3263899Sarchie#define _LINUX_DEVICE_H_ 3363899Sarchie 3463899Sarchie#include <linux/err.h> 3563899Sarchie#include <linux/types.h> 3663899Sarchie#include <linux/kobject.h> 3763899Sarchie#include <linux/sysfs.h> 3863899Sarchie#include <linux/list.h> 3963899Sarchie#include <linux/compiler.h> 4063899Sarchie#include <linux/types.h> 4163899Sarchie#include <linux/module.h> 4263899Sarchie#include <linux/workqueue.h> 4363899Sarchie#include <linux/kdev_t.h> 4463899Sarchie#include <asm/atomic.h> 4563899Sarchie 4663899Sarchie#include <sys/bus.h> 4763899Sarchie 4863899Sarchiestruct device; 4963899Sarchiestruct fwnode_handle; 5063899Sarchie 5163899Sarchiestruct class { 5263899Sarchie const char *name; 5363899Sarchie struct module *owner; 5463899Sarchie struct kobject kobj; 5563899Sarchie devclass_t bsdclass; 5663899Sarchie const struct dev_pm_ops *pm; 5763899Sarchie const struct attribute_group **dev_groups; 5863899Sarchie void (*class_release)(struct class *class); 5963899Sarchie void (*dev_release)(struct device *dev); 6063899Sarchie char * (*devnode)(struct device *dev, umode_t *mode); 6163899Sarchie}; 6263899Sarchie 6363899Sarchiestruct dev_pm_ops { 6463899Sarchie int (*suspend)(struct device *dev); 6563899Sarchie int (*suspend_late)(struct device *dev); 6684195Sdillon int (*resume)(struct device *dev); 6784195Sdillon int (*resume_early)(struct device *dev); 6884195Sdillon int (*freeze)(struct device *dev); 6963899Sarchie int (*freeze_late)(struct device *dev); 7063899Sarchie int (*thaw)(struct device *dev); 7163899Sarchie int (*thaw_early)(struct device *dev); 7263899Sarchie int (*poweroff)(struct device *dev); 7399207Sbrian int (*poweroff_late)(struct device *dev); 7463899Sarchie int (*restore)(struct device *dev); 7563899Sarchie int (*restore_early)(struct device *dev); 7699207Sbrian int (*runtime_suspend)(struct device *dev); 7799207Sbrian int (*runtime_resume)(struct device *dev); 7863899Sarchie int (*runtime_idle)(struct device *dev); 7963899Sarchie}; 8063899Sarchie 8163899Sarchiestruct device_driver { 8263899Sarchie const char *name; 8399207Sbrian const struct dev_pm_ops *pm; 8463899Sarchie}; 8563899Sarchie 8663899Sarchiestruct device_type { 8763899Sarchie const char *name; 8863899Sarchie}; 8963899Sarchie 9063899Sarchiestruct device { 9163899Sarchie struct device *parent; 9263899Sarchie struct list_head irqents; 9363899Sarchie device_t bsddev; 9463899Sarchie /* 9563899Sarchie * The following flag is used to determine if the LinuxKPI is 9663899Sarchie * responsible for detaching the BSD device or not. If the 9763899Sarchie * LinuxKPI got the BSD device using devclass_get_device(), it 9899207Sbrian * must not try to detach or delete it, because it's already 9963899Sarchie * done somewhere else. 10063899Sarchie */ 101145921Sglebius bool bsddev_attached_here; 102145921Sglebius struct device_driver *driver; 103145921Sglebius struct device_type *type; 104145921Sglebius dev_t devt; 105145921Sglebius struct class *class; 10663899Sarchie void (*release)(struct device *dev); 10763899Sarchie struct kobject kobj; 108145921Sglebius uint64_t *dma_mask; 109145921Sglebius void *driver_data; 11063899Sarchie unsigned int irq; 11163899Sarchie#define LINUX_IRQ_INVALID 65535 11263899Sarchie unsigned int irq_start; 11363899Sarchie unsigned int irq_end; 11463899Sarchie const struct attribute_group **groups; 11563899Sarchie struct fwnode_handle *fwnode; 116145921Sglebius 117145932Sglebius spinlock_t devres_lock; 118145921Sglebius struct list_head devres_head; 119145921Sglebius}; 12063899Sarchie 121145921Sglebiusextern struct device linux_root_device; 12263899Sarchieextern struct kobject linux_class_root; 12399207Sbrianextern const struct kobj_type linux_dev_ktype; 12499207Sbrianextern const struct kobj_type linux_class_ktype; 12563899Sarchie 12663899Sarchiestruct class_attribute { 12763899Sarchie struct attribute attr; 12863899Sarchie ssize_t (*show)(struct class *, struct class_attribute *, char *); 12965892Sru ssize_t (*store)(struct class *, struct class_attribute *, const char *, size_t); 13071796Sbrian const void *(*namespace)(struct class *, const struct class_attribute *); 13163899Sarchie}; 132127094Sdes 133127094Sdes#define CLASS_ATTR(_name, _mode, _show, _store) \ 13463899Sarchie struct class_attribute class_attr_##_name = \ 135127094Sdes { { #_name, NULL, _mode }, _show, _store } 136127094Sdes 137127094Sdesstruct device_attribute { 138127094Sdes struct attribute attr; 139127094Sdes ssize_t (*show)(struct device *, 140127094Sdes struct device_attribute *, char *); 141127094Sdes ssize_t (*store)(struct device *, 142127094Sdes struct device_attribute *, const char *, 143131613Sdes size_t); 144127094Sdes}; 145127094Sdes 14663899Sarchie#define DEVICE_ATTR(_name, _mode, _show, _store) \ 147131613Sdes struct device_attribute dev_attr_##_name = \ 14863899Sarchie __ATTR(_name, _mode, _show, _store) 14963899Sarchie#define DEVICE_ATTR_RO(_name) \ 15065892Sru struct device_attribute dev_attr_##_name = __ATTR_RO(_name) 151124621Sphk#define DEVICE_ATTR_WO(_name) \ 152131614Sdes struct device_attribute dev_attr_##_name = __ATTR_WO(_name) 153127094Sdes#define DEVICE_ATTR_RW(_name) \ 154127094Sdes struct device_attribute dev_attr_##_name = __ATTR_RW(_name) 15563899Sarchie 156127094Sdes/* Simple class attribute that is just a static string */ 157127094Sdesstruct class_attribute_string { 158127094Sdes struct class_attribute attr; 159127094Sdes char *str; 160127094Sdes}; 161127094Sdes 162127094Sdesstatic inline ssize_t 163127094Sdesshow_class_attr_string(struct class *class, 164127094Sdes struct class_attribute *attr, char *buf) 165131614Sdes{ 166127094Sdes struct class_attribute_string *cs; 16763899Sarchie cs = container_of(attr, struct class_attribute_string, attr); 168127094Sdes return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); 169131699Sdes} 170127094Sdes 171127094Sdes/* Currently read-only only */ 172127094Sdes#define _CLASS_ATTR_STRING(_name, _mode, _str) \ 17363899Sarchie { __ATTR(_name, _mode, show_class_attr_string, NULL), _str } 174127094Sdes#define CLASS_ATTR_STRING(_name, _mode, _str) \ 175127094Sdes struct class_attribute_string class_attr_##_name = \ 17663899Sarchie _CLASS_ATTR_STRING(_name, _mode, _str) 177131613Sdes 17863899Sarchie#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 179127094Sdes#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 180127094Sdes#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 18163899Sarchie#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 182127094Sdes#define dev_dbg(dev, fmt, ...) do { } while (0) 183127094Sdes#define dev_printk(lvl, dev, fmt, ...) \ 18463899Sarchie device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 185131614Sdes 186127094Sdes#define dev_err_once(dev, ...) do { \ 187127094Sdes static bool __dev_err_once; \ 188127094Sdes if (!__dev_err_once) { \ 189127094Sdes __dev_err_once = 1; \ 19063899Sarchie dev_err(dev, __VA_ARGS__); \ 191127094Sdes } \ 192127094Sdes} while (0) 19363899Sarchie 194127094Sdes#define dev_err_ratelimited(dev, ...) do { \ 195127094Sdes static linux_ratelimit_t __ratelimited; \ 196127094Sdes if (linux_ratelimited(&__ratelimited)) \ 197127094Sdes dev_err(dev, __VA_ARGS__); \ 198127094Sdes} while (0) 199127094Sdes 200127094Sdes#define dev_warn_ratelimited(dev, ...) do { \ 201127094Sdes static linux_ratelimit_t __ratelimited; \ 202127094Sdes if (linux_ratelimited(&__ratelimited)) \ 203127094Sdes dev_warn(dev, __VA_ARGS__); \ 204127094Sdes} while (0) 205127094Sdes 206127094Sdesstatic inline void * 207127094Sdesdev_get_drvdata(const struct device *dev) 208127094Sdes{ 209127094Sdes 210127094Sdes return dev->driver_data; 211127094Sdes} 212127094Sdes 213127094Sdesstatic inline void 214127094Sdesdev_set_drvdata(struct device *dev, void *data) 215127094Sdes{ 216127094Sdes 217127094Sdes dev->driver_data = data; 218127094Sdes} 219127094Sdes 220127094Sdesstatic inline struct device * 221127094Sdesget_device(struct device *dev) 222127094Sdes{ 223127094Sdes 224127094Sdes if (dev) 225127094Sdes kobject_get(&dev->kobj); 226127094Sdes 22763899Sarchie return (dev); 228127094Sdes} 229127094Sdes 230127094Sdesstatic inline char * 231127094Sdesdev_name(const struct device *dev) 232127094Sdes{ 233127094Sdes 234127094Sdes return kobject_name(&dev->kobj); 235127094Sdes} 236127094Sdes 237127094Sdes#define dev_set_name(_dev, _fmt, ...) \ 238127094Sdes kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) 239127094Sdes 240127094Sdesstatic inline void 241127094Sdesput_device(struct device *dev) 242127094Sdes{ 243145961Sglebius 244127094Sdes if (dev) 245127094Sdes kobject_put(&dev->kobj); 24663899Sarchie} 247127094Sdes 24863899Sarchiestatic inline int 249127094Sdesclass_register(struct class *class) 250127094Sdes{ 251127094Sdes 252127094Sdes class->bsdclass = devclass_create(class->name); 253127094Sdes kobject_init(&class->kobj, &linux_class_ktype); 254127094Sdes kobject_set_name(&class->kobj, class->name); 255127094Sdes kobject_add(&class->kobj, &linux_class_root, class->name); 256131614Sdes 257127094Sdes return (0); 258127094Sdes} 259131614Sdes 26063899Sarchiestatic inline void 261127094Sdesclass_unregister(struct class *class) 262127094Sdes{ 263127094Sdes 264127094Sdes kobject_put(&class->kobj); 265127094Sdes} 266131614Sdes 26763899Sarchiestatic inline struct device *kobj_to_dev(struct kobject *kobj) 268127094Sdes{ 269145961Sglebius return container_of(kobj, struct device, kobj); 270127094Sdes} 271127094Sdes 27263899Sarchie/* 273127094Sdes * Devices are registered and created for exporting to sysfs. Create 274127094Sdes * implies register and register assumes the device fields have been 275127094Sdes * setup appropriately before being called. 276127094Sdes */ 277127094Sdesstatic inline void 278127094Sdesdevice_initialize(struct device *dev) 279131614Sdes{ 28063899Sarchie device_t bsddev = NULL; 281127094Sdes int unit = -1; 28263899Sarchie 283127094Sdes if (dev->devt) { 284127094Sdes unit = MINOR(dev->devt); 285127094Sdes bsddev = devclass_get_device(dev->class->bsdclass, unit); 286127094Sdes dev->bsddev_attached_here = false; 28763899Sarchie } else if (dev->parent == NULL) { 288127094Sdes bsddev = devclass_get_device(dev->class->bsdclass, 0); 289127094Sdes dev->bsddev_attached_here = false; 290127094Sdes } else { 29163899Sarchie dev->bsddev_attached_here = true; 292127094Sdes } 293127094Sdes 294127094Sdes if (bsddev == NULL && dev->parent != NULL) { 295127094Sdes bsddev = device_add_child(dev->parent->bsddev, 296127094Sdes dev->class->kobj.name, unit); 297127094Sdes } 298127094Sdes 299127094Sdes if (bsddev != NULL) 300127094Sdes device_set_softc(bsddev, dev); 301127094Sdes 302127094Sdes dev->bsddev = bsddev; 303127094Sdes MPASS(dev->bsddev != NULL); 304127094Sdes kobject_init(&dev->kobj, &linux_dev_ktype); 305127094Sdes 30663899Sarchie spin_lock_init(&dev->devres_lock); 307127094Sdes INIT_LIST_HEAD(&dev->devres_head); 308127094Sdes} 30963899Sarchie 31063899Sarchiestatic inline int 311127094Sdesdevice_add(struct device *dev) 312131613Sdes{ 31363899Sarchie if (dev->bsddev != NULL) { 314127094Sdes if (dev->devt == 0) 315127094Sdes dev->devt = makedev(0, device_get_unit(dev->bsddev)); 316127094Sdes } 31763899Sarchie kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 318127094Sdes 319127094Sdes if (dev->groups) 320127094Sdes return (sysfs_create_groups(&dev->kobj, dev->groups)); 32163899Sarchie 322131614Sdes return (0); 323131614Sdes} 324131614Sdes 32563899Sarchiestatic inline void 326127094Sdesdevice_create_release(struct device *dev) 327127094Sdes{ 328127094Sdes kfree(dev); 329127094Sdes} 330127094Sdes 331127094Sdesstatic inline struct device * 33263899Sarchiedevice_create_groups_vargs(struct class *class, struct device *parent, 333127094Sdes dev_t devt, void *drvdata, const struct attribute_group **groups, 334127094Sdes const char *fmt, va_list args) 33563899Sarchie{ 336131613Sdes struct device *dev = NULL; 33763899Sarchie int retval = -ENODEV; 33863899Sarchie 33963899Sarchie if (class == NULL || IS_ERR(class)) 34063899Sarchie goto error; 34165892Sru 342124621Sphk dev = kzalloc(sizeof(*dev), GFP_KERNEL); 343131614Sdes if (!dev) { 344127094Sdes retval = -ENOMEM; 345127094Sdes goto error; 34663899Sarchie } 347127094Sdes 348127094Sdes dev->devt = devt; 349127094Sdes dev->class = class; 350127094Sdes dev->parent = parent; 351127094Sdes dev->groups = groups; 35263899Sarchie dev->release = device_create_release; 353127094Sdes /* device_initialize() needs the class and parent to be set */ 354127094Sdes device_initialize(dev); 355127094Sdes dev_set_drvdata(dev, drvdata); 356127094Sdes 357127094Sdes retval = kobject_set_name_vargs(&dev->kobj, fmt, args); 358127094Sdes if (retval) 359127094Sdes goto error; 360127094Sdes 361127094Sdes retval = device_add(dev); 362131613Sdes if (retval) 363127094Sdes goto error; 364127094Sdes 365127094Sdes return dev; 366131614Sdes 367127094Sdeserror: 368127094Sdes put_device(dev); 36963899Sarchie return ERR_PTR(retval); 370127094Sdes} 371127094Sdes 37263899Sarchiestatic inline struct device * 373131699Sdesdevice_create_with_groups(struct class *class, 374127094Sdes struct device *parent, dev_t devt, void *drvdata, 375127094Sdes const struct attribute_group **groups, const char *fmt, ...) 37663899Sarchie{ 377127094Sdes va_list vargs; 378127094Sdes struct device *dev; 379127094Sdes 380127094Sdes va_start(vargs, fmt); 381127094Sdes dev = device_create_groups_vargs(class, parent, devt, drvdata, 382127094Sdes groups, fmt, vargs); 38363899Sarchie va_end(vargs); 38499207Sbrian return dev; 385131613Sdes} 38663899Sarchie 38763899Sarchiestatic inline bool 38863899Sarchiedevice_is_registered(struct device *dev) 389131614Sdes{ 39063899Sarchie 391127094Sdes return (dev->bsddev != NULL); 392127094Sdes} 393127094Sdes 394127094Sdesstatic inline int 395127094Sdesdevice_register(struct device *dev) 396127094Sdes{ 397127094Sdes device_t bsddev = NULL; 39863899Sarchie int unit = -1; 399131614Sdes 400131614Sdes if (device_is_registered(dev)) 401131699Sdes goto done; 402127094Sdes 403127094Sdes if (dev->devt) { 404127094Sdes unit = MINOR(dev->devt); 40563899Sarchie bsddev = devclass_get_device(dev->class->bsdclass, unit); 406127094Sdes dev->bsddev_attached_here = false; 407127094Sdes } else if (dev->parent == NULL) { 40863899Sarchie bsddev = devclass_get_device(dev->class->bsdclass, 0); 409127094Sdes dev->bsddev_attached_here = false; 410127094Sdes } else { 411127094Sdes dev->bsddev_attached_here = true; 41263899Sarchie } 413131614Sdes if (bsddev == NULL && dev->parent != NULL) { 414127094Sdes bsddev = device_add_child(dev->parent->bsddev, 415131614Sdes dev->class->kobj.name, unit); 416127094Sdes } 417127094Sdes if (bsddev != NULL) { 418127094Sdes if (dev->devt == 0) 419131614Sdes dev->devt = makedev(0, device_get_unit(bsddev)); 420127094Sdes device_set_softc(bsddev, dev); 421131614Sdes } 422127094Sdes dev->bsddev = bsddev; 423127094Sdesdone: 424127094Sdes kobject_init(&dev->kobj, &linux_dev_ktype); 42563899Sarchie kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 426127094Sdes 427127094Sdes sysfs_create_groups(&dev->kobj, dev->class->dev_groups); 428127094Sdes 429127094Sdes return (0); 43063899Sarchie} 431131614Sdes 43263899Sarchiestatic inline void 433127094Sdesdevice_unregister(struct device *dev) 434131614Sdes{ 435127094Sdes device_t bsddev; 436127094Sdes 437127094Sdes sysfs_remove_groups(&dev->kobj, dev->class->dev_groups); 438127094Sdes 439127094Sdes bsddev = dev->bsddev; 440127094Sdes dev->bsddev = NULL; 441127094Sdes 44263899Sarchie if (bsddev != NULL && dev->bsddev_attached_here) { 443127094Sdes mtx_lock(&Giant); 444127094Sdes device_delete_child(device_get_parent(bsddev), bsddev); 445127094Sdes mtx_unlock(&Giant); 44663899Sarchie } 447131614Sdes put_device(dev); 44899207Sbrian} 449127094Sdes 450131614Sdesstatic inline void 45163899Sarchiedevice_del(struct device *dev) 452127094Sdes{ 453127094Sdes device_t bsddev; 454127094Sdes 455127094Sdes bsddev = dev->bsddev; 45663899Sarchie dev->bsddev = NULL; 457 458 if (bsddev != NULL && dev->bsddev_attached_here) { 459 mtx_lock(&Giant); 460 device_delete_child(device_get_parent(bsddev), bsddev); 461 mtx_unlock(&Giant); 462 } 463} 464 465struct device *device_create(struct class *class, struct device *parent, 466 dev_t devt, void *drvdata, const char *fmt, ...); 467 468static inline void 469device_destroy(struct class *class, dev_t devt) 470{ 471 device_t bsddev; 472 int unit; 473 474 unit = MINOR(devt); 475 bsddev = devclass_get_device(class->bsdclass, unit); 476 if (bsddev != NULL) 477 device_unregister(device_get_softc(bsddev)); 478} 479 480#define dev_pm_set_driver_flags(dev, flags) do { \ 481} while (0) 482 483static inline void 484linux_class_kfree(struct class *class) 485{ 486 487 kfree(class); 488} 489 490static inline struct class * 491class_create(struct module *owner, const char *name) 492{ 493 struct class *class; 494 int error; 495 496 class = kzalloc(sizeof(*class), M_WAITOK); 497 class->owner = owner; 498 class->name = name; 499 class->class_release = linux_class_kfree; 500 error = class_register(class); 501 if (error) { 502 kfree(class); 503 return (NULL); 504 } 505 506 return (class); 507} 508 509static inline void 510class_destroy(struct class *class) 511{ 512 513 if (class == NULL) 514 return; 515 class_unregister(class); 516} 517 518static inline int 519device_create_file(struct device *dev, const struct device_attribute *attr) 520{ 521 522 if (dev) 523 return sysfs_create_file(&dev->kobj, &attr->attr); 524 return -EINVAL; 525} 526 527static inline void 528device_remove_file(struct device *dev, const struct device_attribute *attr) 529{ 530 531 if (dev) 532 sysfs_remove_file(&dev->kobj, &attr->attr); 533} 534 535static inline int 536class_create_file(struct class *class, const struct class_attribute *attr) 537{ 538 539 if (class) 540 return sysfs_create_file(&class->kobj, &attr->attr); 541 return -EINVAL; 542} 543 544static inline void 545class_remove_file(struct class *class, const struct class_attribute *attr) 546{ 547 548 if (class) 549 sysfs_remove_file(&class->kobj, &attr->attr); 550} 551 552static inline int 553dev_to_node(struct device *dev) 554{ 555 return -1; 556} 557 558char *kvasprintf(gfp_t, const char *, va_list); 559char *kasprintf(gfp_t, const char *, ...); 560 561#endif /* _LINUX_DEVICE_H_ */ 562