device.h revision 278865
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. 28219820Sjeff */ 29219820Sjeff#ifndef _LINUX_DEVICE_H_ 30219820Sjeff#define _LINUX_DEVICE_H_ 31219820Sjeff 32219820Sjeff#include <linux/types.h> 33219820Sjeff#include <linux/kobject.h> 34219820Sjeff#include <linux/list.h> 35219820Sjeff#include <linux/compiler.h> 36219820Sjeff#include <linux/types.h> 37219820Sjeff#include <linux/module.h> 38219820Sjeff#include <linux/workqueue.h> 39219820Sjeff#include <linux/sysfs.h> 40219820Sjeff#include <linux/kdev_t.h> 41219820Sjeff#include <asm/atomic.h> 42219820Sjeff 43219820Sjeff#include <sys/bus.h> 44219820Sjeff 45219820Sjeffenum irqreturn { IRQ_NONE = 0, IRQ_HANDLED, IRQ_WAKE_THREAD, }; 46219820Sjefftypedef enum irqreturn irqreturn_t; 47219820Sjeff 48219820Sjeffstruct class { 49219820Sjeff const char *name; 50219820Sjeff struct module *owner; 51219820Sjeff struct kobject kobj; 52219820Sjeff devclass_t bsdclass; 53219820Sjeff void (*class_release)(struct class *class); 54219820Sjeff void (*dev_release)(struct device *dev); 55270710Shselasky char * (*devnode)(struct device *dev, umode_t *mode); 56219820Sjeff}; 57219820Sjeff 58219820Sjeffstruct device { 59219820Sjeff struct device *parent; 60219820Sjeff struct list_head irqents; 61219820Sjeff device_t bsddev; 62219820Sjeff dev_t devt; 63219820Sjeff struct class *class; 64219820Sjeff void (*release)(struct device *dev); 65219820Sjeff struct kobject kobj; 66219820Sjeff uint64_t *dma_mask; 67219820Sjeff void *driver_data; 68219820Sjeff unsigned int irq; 69219820Sjeff unsigned int msix; 70219820Sjeff unsigned int msix_max; 71219820Sjeff}; 72219820Sjeff 73219820Sjeffextern struct device linux_rootdev; 74219820Sjeffextern struct kobject class_root; 75219820Sjeff 76219820Sjeffstruct class_attribute { 77270710Shselasky struct attribute attr; 78270710Shselasky ssize_t (*show)(struct class *, struct class_attribute *, char *); 79270710Shselasky ssize_t (*store)(struct class *, struct class_attribute *, const char *, size_t); 80270710Shselasky const void *(*namespace)(struct class *, const struct class_attribute *); 81219820Sjeff}; 82270710Shselasky 83219820Sjeff#define CLASS_ATTR(_name, _mode, _show, _store) \ 84219820Sjeff struct class_attribute class_attr_##_name = \ 85219820Sjeff { { #_name, NULL, _mode }, _show, _store } 86219820Sjeff 87219820Sjeffstruct device_attribute { 88219820Sjeff struct attribute attr; 89219820Sjeff ssize_t (*show)(struct device *, 90270710Shselasky struct device_attribute *, char *); 91219820Sjeff ssize_t (*store)(struct device *, 92270710Shselasky struct device_attribute *, const char *, 93270710Shselasky size_t); 94219820Sjeff}; 95219820Sjeff 96219820Sjeff#define DEVICE_ATTR(_name, _mode, _show, _store) \ 97219820Sjeff struct device_attribute dev_attr_##_name = \ 98219820Sjeff { { #_name, NULL, _mode }, _show, _store } 99219820Sjeff 100270710Shselasky/* Simple class attribute that is just a static string */ 101270710Shselaskystruct class_attribute_string { 102270710Shselasky struct class_attribute attr; 103270710Shselasky char *str; 104270710Shselasky}; 105270710Shselasky 106270710Shselaskystatic inline ssize_t 107270710Shselaskyshow_class_attr_string(struct class *class, 108270710Shselasky struct class_attribute *attr, char *buf) 109270710Shselasky{ 110270710Shselasky struct class_attribute_string *cs; 111270710Shselasky cs = container_of(attr, struct class_attribute_string, attr); 112270710Shselasky return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); 113270710Shselasky} 114270710Shselasky 115270710Shselasky/* Currently read-only only */ 116270710Shselasky#define _CLASS_ATTR_STRING(_name, _mode, _str) \ 117270710Shselasky { __ATTR(_name, _mode, show_class_attr_string, NULL), _str } 118270710Shselasky#define CLASS_ATTR_STRING(_name, _mode, _str) \ 119270710Shselasky struct class_attribute_string class_attr_##_name = \ 120270710Shselasky _CLASS_ATTR_STRING(_name, _mode, _str) 121270710Shselasky 122219820Sjeff#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 123219820Sjeff#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 124219820Sjeff#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 125219820Sjeff#define dev_printk(lvl, dev, fmt, ...) \ 126219820Sjeff device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 127219820Sjeff 128219820Sjeffstatic inline void * 129219820Sjeffdev_get_drvdata(struct device *dev) 130219820Sjeff{ 131219820Sjeff 132219820Sjeff return dev->driver_data; 133219820Sjeff} 134219820Sjeff 135219820Sjeffstatic inline void 136219820Sjeffdev_set_drvdata(struct device *dev, void *data) 137219820Sjeff{ 138219820Sjeff 139219820Sjeff dev->driver_data = data; 140219820Sjeff} 141219820Sjeff 142219820Sjeffstatic inline struct device * 143219820Sjeffget_device(struct device *dev) 144219820Sjeff{ 145219820Sjeff 146219820Sjeff if (dev) 147219820Sjeff kobject_get(&dev->kobj); 148219820Sjeff 149219820Sjeff return (dev); 150219820Sjeff} 151219820Sjeff 152219820Sjeffstatic inline char * 153219820Sjeffdev_name(const struct device *dev) 154219820Sjeff{ 155219820Sjeff 156219820Sjeff return kobject_name(&dev->kobj); 157219820Sjeff} 158219820Sjeff 159219820Sjeff#define dev_set_name(_dev, _fmt, ...) \ 160219820Sjeff kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) 161219820Sjeff 162219820Sjeffstatic inline void 163219820Sjeffput_device(struct device *dev) 164219820Sjeff{ 165219820Sjeff 166219820Sjeff if (dev) 167219820Sjeff kobject_put(&dev->kobj); 168219820Sjeff} 169219820Sjeff 170219820Sjeffstatic inline ssize_t 171219820Sjeffclass_show(struct kobject *kobj, struct attribute *attr, char *buf) 172219820Sjeff{ 173219820Sjeff struct class_attribute *dattr; 174219820Sjeff ssize_t error; 175219820Sjeff 176219820Sjeff dattr = container_of(attr, struct class_attribute, attr); 177219820Sjeff error = -EIO; 178219820Sjeff if (dattr->show) 179219820Sjeff error = dattr->show(container_of(kobj, struct class, kobj), 180270710Shselasky dattr, buf); 181219820Sjeff return (error); 182219820Sjeff} 183219820Sjeff 184219820Sjeffstatic inline ssize_t 185219820Sjeffclass_store(struct kobject *kobj, struct attribute *attr, const char *buf, 186219820Sjeff size_t count) 187219820Sjeff{ 188219820Sjeff struct class_attribute *dattr; 189219820Sjeff ssize_t error; 190219820Sjeff 191219820Sjeff dattr = container_of(attr, struct class_attribute, attr); 192219820Sjeff error = -EIO; 193219820Sjeff if (dattr->store) 194219820Sjeff error = dattr->store(container_of(kobj, struct class, kobj), 195270710Shselasky dattr, buf, count); 196219820Sjeff return (error); 197219820Sjeff} 198219820Sjeff 199219820Sjeffstatic inline void 200219820Sjeffclass_release(struct kobject *kobj) 201219820Sjeff{ 202219820Sjeff struct class *class; 203219820Sjeff 204219820Sjeff class = container_of(kobj, struct class, kobj); 205219820Sjeff if (class->class_release) 206219820Sjeff class->class_release(class); 207219820Sjeff} 208219820Sjeff 209219820Sjeffstatic struct sysfs_ops class_sysfs = { 210219820Sjeff .show = class_show, 211219820Sjeff .store = class_store, 212219820Sjeff}; 213219820Sjeffstatic struct kobj_type class_ktype = { 214219820Sjeff .release = class_release, 215219820Sjeff .sysfs_ops = &class_sysfs 216219820Sjeff}; 217219820Sjeff 218219820Sjeffstatic inline int 219219820Sjeffclass_register(struct class *class) 220219820Sjeff{ 221219820Sjeff 222219820Sjeff class->bsdclass = devclass_create(class->name); 223219820Sjeff kobject_init(&class->kobj, &class_ktype); 224219820Sjeff kobject_set_name(&class->kobj, class->name); 225219820Sjeff kobject_add(&class->kobj, &class_root, class->name); 226219820Sjeff 227219820Sjeff return (0); 228219820Sjeff} 229219820Sjeff 230219820Sjeffstatic inline void 231219820Sjeffclass_unregister(struct class *class) 232219820Sjeff{ 233219820Sjeff 234219820Sjeff kobject_put(&class->kobj); 235219820Sjeff} 236219820Sjeff 237219820Sjeffstatic inline void 238219820Sjeffdevice_release(struct kobject *kobj) 239219820Sjeff{ 240219820Sjeff struct device *dev; 241219820Sjeff 242219820Sjeff dev = container_of(kobj, struct device, kobj); 243219820Sjeff /* This is the precedence defined by linux. */ 244219820Sjeff if (dev->release) 245219820Sjeff dev->release(dev); 246219820Sjeff else if (dev->class && dev->class->dev_release) 247219820Sjeff dev->class->dev_release(dev); 248219820Sjeff} 249219820Sjeff 250219820Sjeffstatic inline ssize_t 251219820Sjeffdev_show(struct kobject *kobj, struct attribute *attr, char *buf) 252219820Sjeff{ 253219820Sjeff struct device_attribute *dattr; 254219820Sjeff ssize_t error; 255219820Sjeff 256219820Sjeff dattr = container_of(attr, struct device_attribute, attr); 257219820Sjeff error = -EIO; 258219820Sjeff if (dattr->show) 259219820Sjeff error = dattr->show(container_of(kobj, struct device, kobj), 260219820Sjeff dattr, buf); 261219820Sjeff return (error); 262219820Sjeff} 263219820Sjeff 264219820Sjeffstatic inline ssize_t 265219820Sjeffdev_store(struct kobject *kobj, struct attribute *attr, const char *buf, 266219820Sjeff size_t count) 267219820Sjeff{ 268219820Sjeff struct device_attribute *dattr; 269219820Sjeff ssize_t error; 270219820Sjeff 271219820Sjeff dattr = container_of(attr, struct device_attribute, attr); 272219820Sjeff error = -EIO; 273219820Sjeff if (dattr->store) 274219820Sjeff error = dattr->store(container_of(kobj, struct device, kobj), 275219820Sjeff dattr, buf, count); 276219820Sjeff return (error); 277219820Sjeff} 278219820Sjeff 279219820Sjeffstatic struct sysfs_ops dev_sysfs = { .show = dev_show, .store = dev_store, }; 280219820Sjeffstatic struct kobj_type dev_ktype = { 281219820Sjeff .release = device_release, 282219820Sjeff .sysfs_ops = &dev_sysfs 283219820Sjeff}; 284219820Sjeff 285219820Sjeff/* 286219820Sjeff * Devices are registered and created for exporting to sysfs. create 287219820Sjeff * implies register and register assumes the device fields have been 288219820Sjeff * setup appropriately before being called. 289219820Sjeff */ 290219820Sjeffstatic inline int 291219820Sjeffdevice_register(struct device *dev) 292219820Sjeff{ 293219820Sjeff device_t bsddev; 294219820Sjeff int unit; 295219820Sjeff 296219820Sjeff bsddev = NULL; 297219820Sjeff if (dev->devt) { 298219820Sjeff unit = MINOR(dev->devt); 299219820Sjeff bsddev = devclass_get_device(dev->class->bsdclass, unit); 300219820Sjeff } else 301219820Sjeff unit = -1; 302219820Sjeff if (bsddev == NULL) 303219820Sjeff bsddev = device_add_child(dev->parent->bsddev, 304219820Sjeff dev->class->kobj.name, unit); 305219820Sjeff if (bsddev) { 306219820Sjeff if (dev->devt == 0) 307219820Sjeff dev->devt = makedev(0, device_get_unit(bsddev)); 308219820Sjeff device_set_softc(bsddev, dev); 309219820Sjeff } 310219820Sjeff dev->bsddev = bsddev; 311219820Sjeff kobject_init(&dev->kobj, &dev_ktype); 312219820Sjeff kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 313219820Sjeff 314219820Sjeff return (0); 315219820Sjeff} 316219820Sjeff 317219820Sjeffstatic inline void 318219820Sjeffdevice_unregister(struct device *dev) 319219820Sjeff{ 320219820Sjeff device_t bsddev; 321219820Sjeff 322219820Sjeff bsddev = dev->bsddev; 323219820Sjeff mtx_lock(&Giant); 324219820Sjeff if (bsddev) 325219820Sjeff device_delete_child(device_get_parent(bsddev), bsddev); 326219820Sjeff mtx_unlock(&Giant); 327219820Sjeff put_device(dev); 328219820Sjeff} 329219820Sjeff 330219820Sjeffstruct device *device_create(struct class *class, struct device *parent, 331219820Sjeff dev_t devt, void *drvdata, const char *fmt, ...); 332219820Sjeff 333219820Sjeffstatic inline void 334219820Sjeffdevice_destroy(struct class *class, dev_t devt) 335219820Sjeff{ 336219820Sjeff device_t bsddev; 337219820Sjeff int unit; 338219820Sjeff 339219820Sjeff unit = MINOR(devt); 340219820Sjeff bsddev = devclass_get_device(class->bsdclass, unit); 341219820Sjeff if (bsddev) 342219820Sjeff device_unregister(device_get_softc(bsddev)); 343219820Sjeff} 344219820Sjeff 345219820Sjeffstatic inline void 346219820Sjeffclass_kfree(struct class *class) 347219820Sjeff{ 348219820Sjeff 349219820Sjeff kfree(class); 350219820Sjeff} 351219820Sjeff 352219820Sjeffstatic inline struct class * 353219820Sjeffclass_create(struct module *owner, const char *name) 354219820Sjeff{ 355219820Sjeff struct class *class; 356219820Sjeff int error; 357219820Sjeff 358219820Sjeff class = kzalloc(sizeof(*class), M_WAITOK); 359219820Sjeff class->owner = owner; 360219820Sjeff class->name= name; 361219820Sjeff class->class_release = class_kfree; 362219820Sjeff error = class_register(class); 363219820Sjeff if (error) { 364219820Sjeff kfree(class); 365219820Sjeff return (NULL); 366219820Sjeff } 367219820Sjeff 368219820Sjeff return (class); 369219820Sjeff} 370219820Sjeff 371219820Sjeffstatic inline void 372219820Sjeffclass_destroy(struct class *class) 373219820Sjeff{ 374219820Sjeff 375219820Sjeff if (class == NULL) 376219820Sjeff return; 377219820Sjeff class_unregister(class); 378219820Sjeff} 379219820Sjeff 380219820Sjeffstatic inline int 381219820Sjeffdevice_create_file(struct device *dev, const struct device_attribute *attr) 382219820Sjeff{ 383219820Sjeff 384219820Sjeff if (dev) 385219820Sjeff return sysfs_create_file(&dev->kobj, &attr->attr); 386219820Sjeff return -EINVAL; 387219820Sjeff} 388219820Sjeff 389219820Sjeffstatic inline void 390219820Sjeffdevice_remove_file(struct device *dev, const struct device_attribute *attr) 391219820Sjeff{ 392219820Sjeff 393219820Sjeff if (dev) 394219820Sjeff sysfs_remove_file(&dev->kobj, &attr->attr); 395219820Sjeff} 396219820Sjeff 397219820Sjeffstatic inline int 398219820Sjeffclass_create_file(struct class *class, const struct class_attribute *attr) 399219820Sjeff{ 400219820Sjeff 401219820Sjeff if (class) 402219820Sjeff return sysfs_create_file(&class->kobj, &attr->attr); 403219820Sjeff return -EINVAL; 404219820Sjeff} 405219820Sjeff 406219820Sjeffstatic inline void 407219820Sjeffclass_remove_file(struct class *class, const struct class_attribute *attr) 408219820Sjeff{ 409219820Sjeff 410219820Sjeff if (class) 411219820Sjeff sysfs_remove_file(&class->kobj, &attr->attr); 412219820Sjeff} 413219820Sjeff 414255932Salfredstatic inline int dev_to_node(struct device *dev) 415255932Salfred{ 416255932Salfred return -1; 417255932Salfred} 418255932Salfred 419270710Shselaskystatic inline char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap) 420270710Shselasky{ 421270710Shselasky unsigned int len; 422270710Shselasky char *p = NULL; 423270710Shselasky va_list aq; 424255932Salfred 425270710Shselasky va_copy(aq, ap); 426270710Shselasky len = vsnprintf(NULL, 0, fmt, aq); 427270710Shselasky va_end(aq); 428270710Shselasky 429270710Shselasky vsnprintf(p, len+1, fmt, ap); 430270710Shselasky 431270710Shselasky return p; 432270710Shselasky} 433270710Shselasky 434278865Shselaskychar *kasprintf(gfp_t, const char *, ...); 435270710Shselasky 436219820Sjeff#endif /* _LINUX_DEVICE_H_ */ 437