device.h revision 292987
1219820Sjeff/*- 2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc. 3219820Sjeff * Copyright (c) 2010 iX Systems, Inc. 4219820Sjeff * Copyright (c) 2010 Panasas, Inc. 5270710Shselasky * Copyright (c) 2013, 2014 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 292987 2015-12-31 12:30:19Z 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; 206219820Sjeff if (dev->devt) { 207219820Sjeff unit = MINOR(dev->devt); 208219820Sjeff bsddev = devclass_get_device(dev->class->bsdclass, unit); 209219820Sjeff } else 210219820Sjeff unit = -1; 211219820Sjeff if (bsddev == NULL) 212219820Sjeff bsddev = device_add_child(dev->parent->bsddev, 213219820Sjeff dev->class->kobj.name, unit); 214219820Sjeff if (bsddev) { 215219820Sjeff if (dev->devt == 0) 216219820Sjeff dev->devt = makedev(0, device_get_unit(bsddev)); 217219820Sjeff device_set_softc(bsddev, dev); 218219820Sjeff } 219219820Sjeff dev->bsddev = bsddev; 220292987Shselasky kobject_init(&dev->kobj, &linux_dev_ktype); 221219820Sjeff kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 222219820Sjeff 223219820Sjeff return (0); 224219820Sjeff} 225219820Sjeff 226219820Sjeffstatic inline void 227219820Sjeffdevice_unregister(struct device *dev) 228219820Sjeff{ 229219820Sjeff device_t bsddev; 230219820Sjeff 231219820Sjeff bsddev = dev->bsddev; 232219820Sjeff mtx_lock(&Giant); 233219820Sjeff if (bsddev) 234219820Sjeff device_delete_child(device_get_parent(bsddev), bsddev); 235219820Sjeff mtx_unlock(&Giant); 236219820Sjeff put_device(dev); 237219820Sjeff} 238219820Sjeff 239219820Sjeffstruct device *device_create(struct class *class, struct device *parent, 240219820Sjeff dev_t devt, void *drvdata, const char *fmt, ...); 241219820Sjeff 242219820Sjeffstatic inline void 243219820Sjeffdevice_destroy(struct class *class, dev_t devt) 244219820Sjeff{ 245219820Sjeff device_t bsddev; 246219820Sjeff int unit; 247219820Sjeff 248219820Sjeff unit = MINOR(devt); 249219820Sjeff bsddev = devclass_get_device(class->bsdclass, unit); 250219820Sjeff if (bsddev) 251219820Sjeff device_unregister(device_get_softc(bsddev)); 252219820Sjeff} 253219820Sjeff 254219820Sjeffstatic inline void 255292987Shselaskylinux_class_kfree(struct class *class) 256219820Sjeff{ 257219820Sjeff 258219820Sjeff kfree(class); 259219820Sjeff} 260219820Sjeff 261219820Sjeffstatic inline struct class * 262219820Sjeffclass_create(struct module *owner, const char *name) 263219820Sjeff{ 264219820Sjeff struct class *class; 265219820Sjeff int error; 266219820Sjeff 267219820Sjeff class = kzalloc(sizeof(*class), M_WAITOK); 268219820Sjeff class->owner = owner; 269219820Sjeff class->name= name; 270292987Shselasky class->class_release = linux_class_kfree; 271219820Sjeff error = class_register(class); 272219820Sjeff if (error) { 273219820Sjeff kfree(class); 274219820Sjeff return (NULL); 275219820Sjeff } 276219820Sjeff 277219820Sjeff return (class); 278219820Sjeff} 279219820Sjeff 280219820Sjeffstatic inline void 281219820Sjeffclass_destroy(struct class *class) 282219820Sjeff{ 283219820Sjeff 284219820Sjeff if (class == NULL) 285219820Sjeff return; 286219820Sjeff class_unregister(class); 287219820Sjeff} 288219820Sjeff 289219820Sjeffstatic inline int 290219820Sjeffdevice_create_file(struct device *dev, const struct device_attribute *attr) 291219820Sjeff{ 292219820Sjeff 293219820Sjeff if (dev) 294219820Sjeff return sysfs_create_file(&dev->kobj, &attr->attr); 295219820Sjeff return -EINVAL; 296219820Sjeff} 297219820Sjeff 298219820Sjeffstatic inline void 299219820Sjeffdevice_remove_file(struct device *dev, const struct device_attribute *attr) 300219820Sjeff{ 301219820Sjeff 302219820Sjeff if (dev) 303219820Sjeff sysfs_remove_file(&dev->kobj, &attr->attr); 304219820Sjeff} 305219820Sjeff 306219820Sjeffstatic inline int 307219820Sjeffclass_create_file(struct class *class, const struct class_attribute *attr) 308219820Sjeff{ 309219820Sjeff 310219820Sjeff if (class) 311219820Sjeff return sysfs_create_file(&class->kobj, &attr->attr); 312219820Sjeff return -EINVAL; 313219820Sjeff} 314219820Sjeff 315219820Sjeffstatic inline void 316219820Sjeffclass_remove_file(struct class *class, const struct class_attribute *attr) 317219820Sjeff{ 318219820Sjeff 319219820Sjeff if (class) 320219820Sjeff sysfs_remove_file(&class->kobj, &attr->attr); 321219820Sjeff} 322219820Sjeff 323292987Shselaskystatic inline int 324292987Shselaskydev_to_node(struct device *dev) 325255932Salfred{ 326255932Salfred return -1; 327255932Salfred} 328255932Salfred 329285088Shselaskychar *kvasprintf(gfp_t, const char *, va_list); 330278865Shselaskychar *kasprintf(gfp_t, const char *, ...); 331270710Shselasky 332219820Sjeff#endif /* _LINUX_DEVICE_H_ */ 333