device.h revision 299931
1219820Sjeff/*- 2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc. 3219820Sjeff * Copyright (c) 2010 iX Systems, Inc. 4219820Sjeff * Copyright (c) 2010 Panasas, Inc. 5299674Shselasky * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. 6219820Sjeff * All rights reserved. 7219820Sjeff * 8219820Sjeff * Redistribution and use in source and binary forms, with or without 9219820Sjeff * modification, are permitted provided that the following conditions 10219820Sjeff * are met: 11219820Sjeff * 1. Redistributions of source code must retain the above copyright 12219820Sjeff * notice unmodified, this list of conditions, and the following 13219820Sjeff * disclaimer. 14219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 15219820Sjeff * notice, this list of conditions and the following disclaimer in the 16219820Sjeff * documentation and/or other materials provided with the distribution. 17219820Sjeff * 18219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28289644Shselasky * 29289644Shselasky * $FreeBSD: head/sys/compat/linuxkpi/common/include/linux/device.h 299931 2016-05-16 09:25:56Z hselasky $ 30219820Sjeff */ 31219820Sjeff#ifndef _LINUX_DEVICE_H_ 32219820Sjeff#define _LINUX_DEVICE_H_ 33219820Sjeff 34219820Sjeff#include <linux/types.h> 35219820Sjeff#include <linux/kobject.h> 36290335Shselasky#include <linux/sysfs.h> 37219820Sjeff#include <linux/list.h> 38219820Sjeff#include <linux/compiler.h> 39219820Sjeff#include <linux/types.h> 40219820Sjeff#include <linux/module.h> 41219820Sjeff#include <linux/workqueue.h> 42219820Sjeff#include <linux/sysfs.h> 43219820Sjeff#include <linux/kdev_t.h> 44219820Sjeff#include <asm/atomic.h> 45219820Sjeff 46219820Sjeff#include <sys/bus.h> 47219820Sjeff 48219820Sjeffenum irqreturn { IRQ_NONE = 0, IRQ_HANDLED, IRQ_WAKE_THREAD, }; 49219820Sjefftypedef enum irqreturn irqreturn_t; 50219820Sjeff 51219820Sjeffstruct class { 52219820Sjeff const char *name; 53219820Sjeff struct module *owner; 54219820Sjeff struct kobject kobj; 55219820Sjeff devclass_t bsdclass; 56219820Sjeff void (*class_release)(struct class *class); 57219820Sjeff void (*dev_release)(struct device *dev); 58270710Shselasky char * (*devnode)(struct device *dev, umode_t *mode); 59219820Sjeff}; 60219820Sjeff 61219820Sjeffstruct device { 62219820Sjeff struct device *parent; 63219820Sjeff struct list_head irqents; 64219820Sjeff device_t bsddev; 65219820Sjeff dev_t devt; 66219820Sjeff struct class *class; 67219820Sjeff void (*release)(struct device *dev); 68219820Sjeff struct kobject kobj; 69219820Sjeff uint64_t *dma_mask; 70219820Sjeff void *driver_data; 71219820Sjeff unsigned int irq; 72219820Sjeff unsigned int msix; 73219820Sjeff unsigned int msix_max; 74219820Sjeff}; 75219820Sjeff 76292987Shselaskyextern struct device linux_root_device; 77292987Shselaskyextern struct kobject linux_class_root; 78292987Shselaskyextern const struct kobj_type linux_dev_ktype; 79292987Shselaskyextern const struct kobj_type linux_class_ktype; 80219820Sjeff 81219820Sjeffstruct class_attribute { 82270710Shselasky struct attribute attr; 83270710Shselasky ssize_t (*show)(struct class *, struct class_attribute *, char *); 84270710Shselasky ssize_t (*store)(struct class *, struct class_attribute *, const char *, size_t); 85270710Shselasky const void *(*namespace)(struct class *, const struct class_attribute *); 86219820Sjeff}; 87270710Shselasky 88219820Sjeff#define CLASS_ATTR(_name, _mode, _show, _store) \ 89219820Sjeff struct class_attribute class_attr_##_name = \ 90219820Sjeff { { #_name, NULL, _mode }, _show, _store } 91219820Sjeff 92219820Sjeffstruct device_attribute { 93219820Sjeff struct attribute attr; 94219820Sjeff ssize_t (*show)(struct device *, 95270710Shselasky struct device_attribute *, char *); 96219820Sjeff ssize_t (*store)(struct device *, 97270710Shselasky struct device_attribute *, const char *, 98270710Shselasky size_t); 99219820Sjeff}; 100219820Sjeff 101219820Sjeff#define DEVICE_ATTR(_name, _mode, _show, _store) \ 102219820Sjeff struct device_attribute dev_attr_##_name = \ 103219820Sjeff { { #_name, NULL, _mode }, _show, _store } 104219820Sjeff 105270710Shselasky/* Simple class attribute that is just a static string */ 106270710Shselaskystruct class_attribute_string { 107270710Shselasky struct class_attribute attr; 108270710Shselasky char *str; 109270710Shselasky}; 110270710Shselasky 111270710Shselaskystatic inline ssize_t 112270710Shselaskyshow_class_attr_string(struct class *class, 113270710Shselasky struct class_attribute *attr, char *buf) 114270710Shselasky{ 115270710Shselasky struct class_attribute_string *cs; 116270710Shselasky cs = container_of(attr, struct class_attribute_string, attr); 117270710Shselasky return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); 118270710Shselasky} 119270710Shselasky 120270710Shselasky/* Currently read-only only */ 121270710Shselasky#define _CLASS_ATTR_STRING(_name, _mode, _str) \ 122270710Shselasky { __ATTR(_name, _mode, show_class_attr_string, NULL), _str } 123270710Shselasky#define CLASS_ATTR_STRING(_name, _mode, _str) \ 124270710Shselasky struct class_attribute_string class_attr_##_name = \ 125270710Shselasky _CLASS_ATTR_STRING(_name, _mode, _str) 126270710Shselasky 127219820Sjeff#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 128219820Sjeff#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 129219820Sjeff#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 130219820Sjeff#define dev_printk(lvl, dev, fmt, ...) \ 131219820Sjeff device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 132219820Sjeff 133219820Sjeffstatic inline void * 134219820Sjeffdev_get_drvdata(struct device *dev) 135219820Sjeff{ 136219820Sjeff 137219820Sjeff return dev->driver_data; 138219820Sjeff} 139219820Sjeff 140219820Sjeffstatic inline void 141219820Sjeffdev_set_drvdata(struct device *dev, void *data) 142219820Sjeff{ 143219820Sjeff 144219820Sjeff dev->driver_data = data; 145219820Sjeff} 146219820Sjeff 147219820Sjeffstatic inline struct device * 148219820Sjeffget_device(struct device *dev) 149219820Sjeff{ 150219820Sjeff 151219820Sjeff if (dev) 152219820Sjeff kobject_get(&dev->kobj); 153219820Sjeff 154219820Sjeff return (dev); 155219820Sjeff} 156219820Sjeff 157219820Sjeffstatic inline char * 158219820Sjeffdev_name(const struct device *dev) 159219820Sjeff{ 160219820Sjeff 161219820Sjeff return kobject_name(&dev->kobj); 162219820Sjeff} 163219820Sjeff 164219820Sjeff#define dev_set_name(_dev, _fmt, ...) \ 165219820Sjeff kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) 166219820Sjeff 167219820Sjeffstatic inline void 168219820Sjeffput_device(struct device *dev) 169219820Sjeff{ 170219820Sjeff 171219820Sjeff if (dev) 172219820Sjeff kobject_put(&dev->kobj); 173219820Sjeff} 174219820Sjeff 175219820Sjeffstatic inline int 176219820Sjeffclass_register(struct class *class) 177219820Sjeff{ 178219820Sjeff 179219820Sjeff class->bsdclass = devclass_create(class->name); 180292987Shselasky kobject_init(&class->kobj, &linux_class_ktype); 181219820Sjeff kobject_set_name(&class->kobj, class->name); 182292987Shselasky kobject_add(&class->kobj, &linux_class_root, class->name); 183219820Sjeff 184219820Sjeff return (0); 185219820Sjeff} 186219820Sjeff 187219820Sjeffstatic inline void 188219820Sjeffclass_unregister(struct class *class) 189219820Sjeff{ 190219820Sjeff 191219820Sjeff kobject_put(&class->kobj); 192219820Sjeff} 193219820Sjeff 194219820Sjeff/* 195219820Sjeff * Devices are registered and created for exporting to sysfs. create 196219820Sjeff * implies register and register assumes the device fields have been 197219820Sjeff * setup appropriately before being called. 198219820Sjeff */ 199219820Sjeffstatic inline int 200219820Sjeffdevice_register(struct device *dev) 201219820Sjeff{ 202219820Sjeff device_t bsddev; 203219820Sjeff int unit; 204219820Sjeff 205219820Sjeff bsddev = NULL; 206299674Shselasky unit = -1; 207299674Shselasky 208219820Sjeff if (dev->devt) { 209219820Sjeff unit = MINOR(dev->devt); 210219820Sjeff bsddev = devclass_get_device(dev->class->bsdclass, unit); 211299674Shselasky } else if (dev->parent == NULL) { 212299674Shselasky bsddev = devclass_get_device(dev->class->bsdclass, 0); 213299674Shselasky } 214299931Shselasky if (bsddev == NULL && dev->parent != NULL) { 215219820Sjeff bsddev = device_add_child(dev->parent->bsddev, 216219820Sjeff dev->class->kobj.name, unit); 217299931Shselasky } 218299931Shselasky if (bsddev != NULL) { 219219820Sjeff if (dev->devt == 0) 220219820Sjeff dev->devt = makedev(0, device_get_unit(bsddev)); 221219820Sjeff device_set_softc(bsddev, dev); 222219820Sjeff } 223219820Sjeff dev->bsddev = bsddev; 224292987Shselasky kobject_init(&dev->kobj, &linux_dev_ktype); 225219820Sjeff kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 226219820Sjeff 227219820Sjeff return (0); 228219820Sjeff} 229219820Sjeff 230219820Sjeffstatic inline void 231219820Sjeffdevice_unregister(struct device *dev) 232219820Sjeff{ 233219820Sjeff device_t bsddev; 234219820Sjeff 235219820Sjeff bsddev = dev->bsddev; 236219820Sjeff mtx_lock(&Giant); 237219820Sjeff if (bsddev) 238219820Sjeff device_delete_child(device_get_parent(bsddev), bsddev); 239219820Sjeff mtx_unlock(&Giant); 240219820Sjeff put_device(dev); 241219820Sjeff} 242219820Sjeff 243219820Sjeffstruct device *device_create(struct class *class, struct device *parent, 244219820Sjeff dev_t devt, void *drvdata, const char *fmt, ...); 245219820Sjeff 246219820Sjeffstatic inline void 247219820Sjeffdevice_destroy(struct class *class, dev_t devt) 248219820Sjeff{ 249219820Sjeff device_t bsddev; 250219820Sjeff int unit; 251219820Sjeff 252219820Sjeff unit = MINOR(devt); 253219820Sjeff bsddev = devclass_get_device(class->bsdclass, unit); 254219820Sjeff if (bsddev) 255219820Sjeff device_unregister(device_get_softc(bsddev)); 256219820Sjeff} 257219820Sjeff 258219820Sjeffstatic inline void 259292987Shselaskylinux_class_kfree(struct class *class) 260219820Sjeff{ 261219820Sjeff 262219820Sjeff kfree(class); 263219820Sjeff} 264219820Sjeff 265219820Sjeffstatic inline struct class * 266219820Sjeffclass_create(struct module *owner, const char *name) 267219820Sjeff{ 268219820Sjeff struct class *class; 269219820Sjeff int error; 270219820Sjeff 271219820Sjeff class = kzalloc(sizeof(*class), M_WAITOK); 272219820Sjeff class->owner = owner; 273219820Sjeff class->name= name; 274292987Shselasky class->class_release = linux_class_kfree; 275219820Sjeff error = class_register(class); 276219820Sjeff if (error) { 277219820Sjeff kfree(class); 278219820Sjeff return (NULL); 279219820Sjeff } 280219820Sjeff 281219820Sjeff return (class); 282219820Sjeff} 283219820Sjeff 284219820Sjeffstatic inline void 285219820Sjeffclass_destroy(struct class *class) 286219820Sjeff{ 287219820Sjeff 288219820Sjeff if (class == NULL) 289219820Sjeff return; 290219820Sjeff class_unregister(class); 291219820Sjeff} 292219820Sjeff 293219820Sjeffstatic inline int 294219820Sjeffdevice_create_file(struct device *dev, const struct device_attribute *attr) 295219820Sjeff{ 296219820Sjeff 297219820Sjeff if (dev) 298219820Sjeff return sysfs_create_file(&dev->kobj, &attr->attr); 299219820Sjeff return -EINVAL; 300219820Sjeff} 301219820Sjeff 302219820Sjeffstatic inline void 303219820Sjeffdevice_remove_file(struct device *dev, const struct device_attribute *attr) 304219820Sjeff{ 305219820Sjeff 306219820Sjeff if (dev) 307219820Sjeff sysfs_remove_file(&dev->kobj, &attr->attr); 308219820Sjeff} 309219820Sjeff 310219820Sjeffstatic inline int 311219820Sjeffclass_create_file(struct class *class, const struct class_attribute *attr) 312219820Sjeff{ 313219820Sjeff 314219820Sjeff if (class) 315219820Sjeff return sysfs_create_file(&class->kobj, &attr->attr); 316219820Sjeff return -EINVAL; 317219820Sjeff} 318219820Sjeff 319219820Sjeffstatic inline void 320219820Sjeffclass_remove_file(struct class *class, const struct class_attribute *attr) 321219820Sjeff{ 322219820Sjeff 323219820Sjeff if (class) 324219820Sjeff sysfs_remove_file(&class->kobj, &attr->attr); 325219820Sjeff} 326219820Sjeff 327292987Shselaskystatic inline int 328292987Shselaskydev_to_node(struct device *dev) 329255932Salfred{ 330255932Salfred return -1; 331255932Salfred} 332255932Salfred 333285088Shselaskychar *kvasprintf(gfp_t, const char *, va_list); 334278865Shselaskychar *kasprintf(gfp_t, const char *, ...); 335270710Shselasky 336219820Sjeff#endif /* _LINUX_DEVICE_H_ */ 337