device.h revision 255932
1/*- 2 * Copyright (c) 2010 Isilon Systems, Inc. 3 * Copyright (c) 2010 iX Systems, Inc. 4 * Copyright (c) 2010 Panasas, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28#ifndef _LINUX_DEVICE_H_ 29#define _LINUX_DEVICE_H_ 30 31#include <linux/types.h> 32#include <linux/kobject.h> 33#include <linux/list.h> 34#include <linux/compiler.h> 35#include <linux/types.h> 36#include <linux/module.h> 37#include <linux/workqueue.h> 38#include <linux/sysfs.h> 39#include <linux/kdev_t.h> 40#include <asm/atomic.h> 41 42#include <sys/bus.h> 43 44enum irqreturn { IRQ_NONE = 0, IRQ_HANDLED, IRQ_WAKE_THREAD, }; 45typedef enum irqreturn irqreturn_t; 46 47struct class { 48 const char *name; 49 struct module *owner; 50 struct kobject kobj; 51 devclass_t bsdclass; 52 void (*class_release)(struct class *class); 53 void (*dev_release)(struct device *dev); 54}; 55 56struct device { 57 struct device *parent; 58 struct list_head irqents; 59 device_t bsddev; 60 dev_t devt; 61 struct class *class; 62 void (*release)(struct device *dev); 63 struct kobject kobj; 64 uint64_t *dma_mask; 65 void *driver_data; 66 unsigned int irq; 67 unsigned int msix; 68 unsigned int msix_max; 69}; 70 71extern struct device linux_rootdev; 72extern struct kobject class_root; 73 74struct class_attribute { 75 struct attribute attr; 76 ssize_t (*show)(struct class *, char *); 77 ssize_t (*store)(struct class *, const char *, size_t); 78}; 79#define CLASS_ATTR(_name, _mode, _show, _store) \ 80 struct class_attribute class_attr_##_name = \ 81 { { #_name, NULL, _mode }, _show, _store } 82 83struct device_attribute { 84 struct attribute attr; 85 ssize_t (*show)(struct device *, 86 struct device_attribute *, char *); 87 ssize_t (*store)(struct device *, 88 struct device_attribute *, const char *, 89 size_t); 90}; 91 92#define DEVICE_ATTR(_name, _mode, _show, _store) \ 93 struct device_attribute dev_attr_##_name = \ 94 { { #_name, NULL, _mode }, _show, _store } 95 96#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 97#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 98#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 99#define dev_printk(lvl, dev, fmt, ...) \ 100 device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) 101 102static inline void * 103dev_get_drvdata(struct device *dev) 104{ 105 106 return dev->driver_data; 107} 108 109static inline void 110dev_set_drvdata(struct device *dev, void *data) 111{ 112 113 dev->driver_data = data; 114} 115 116static inline struct device * 117get_device(struct device *dev) 118{ 119 120 if (dev) 121 kobject_get(&dev->kobj); 122 123 return (dev); 124} 125 126static inline char * 127dev_name(const struct device *dev) 128{ 129 130 return kobject_name(&dev->kobj); 131} 132 133#define dev_set_name(_dev, _fmt, ...) \ 134 kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) 135 136static inline void 137put_device(struct device *dev) 138{ 139 140 if (dev) 141 kobject_put(&dev->kobj); 142} 143 144static inline ssize_t 145class_show(struct kobject *kobj, struct attribute *attr, char *buf) 146{ 147 struct class_attribute *dattr; 148 ssize_t error; 149 150 dattr = container_of(attr, struct class_attribute, attr); 151 error = -EIO; 152 if (dattr->show) 153 error = dattr->show(container_of(kobj, struct class, kobj), 154 buf); 155 return (error); 156} 157 158static inline ssize_t 159class_store(struct kobject *kobj, struct attribute *attr, const char *buf, 160 size_t count) 161{ 162 struct class_attribute *dattr; 163 ssize_t error; 164 165 dattr = container_of(attr, struct class_attribute, attr); 166 error = -EIO; 167 if (dattr->store) 168 error = dattr->store(container_of(kobj, struct class, kobj), 169 buf, count); 170 return (error); 171} 172 173static inline void 174class_release(struct kobject *kobj) 175{ 176 struct class *class; 177 178 class = container_of(kobj, struct class, kobj); 179 if (class->class_release) 180 class->class_release(class); 181} 182 183static struct sysfs_ops class_sysfs = { 184 .show = class_show, 185 .store = class_store, 186}; 187static struct kobj_type class_ktype = { 188 .release = class_release, 189 .sysfs_ops = &class_sysfs 190}; 191 192static inline int 193class_register(struct class *class) 194{ 195 196 class->bsdclass = devclass_create(class->name); 197 kobject_init(&class->kobj, &class_ktype); 198 kobject_set_name(&class->kobj, class->name); 199 kobject_add(&class->kobj, &class_root, class->name); 200 201 return (0); 202} 203 204static inline void 205class_unregister(struct class *class) 206{ 207 208 kobject_put(&class->kobj); 209} 210 211static inline void 212device_release(struct kobject *kobj) 213{ 214 struct device *dev; 215 216 dev = container_of(kobj, struct device, kobj); 217 /* This is the precedence defined by linux. */ 218 if (dev->release) 219 dev->release(dev); 220 else if (dev->class && dev->class->dev_release) 221 dev->class->dev_release(dev); 222} 223 224static inline ssize_t 225dev_show(struct kobject *kobj, struct attribute *attr, char *buf) 226{ 227 struct device_attribute *dattr; 228 ssize_t error; 229 230 dattr = container_of(attr, struct device_attribute, attr); 231 error = -EIO; 232 if (dattr->show) 233 error = dattr->show(container_of(kobj, struct device, kobj), 234 dattr, buf); 235 return (error); 236} 237 238static inline ssize_t 239dev_store(struct kobject *kobj, struct attribute *attr, const char *buf, 240 size_t count) 241{ 242 struct device_attribute *dattr; 243 ssize_t error; 244 245 dattr = container_of(attr, struct device_attribute, attr); 246 error = -EIO; 247 if (dattr->store) 248 error = dattr->store(container_of(kobj, struct device, kobj), 249 dattr, buf, count); 250 return (error); 251} 252 253static struct sysfs_ops dev_sysfs = { .show = dev_show, .store = dev_store, }; 254static struct kobj_type dev_ktype = { 255 .release = device_release, 256 .sysfs_ops = &dev_sysfs 257}; 258 259/* 260 * Devices are registered and created for exporting to sysfs. create 261 * implies register and register assumes the device fields have been 262 * setup appropriately before being called. 263 */ 264static inline int 265device_register(struct device *dev) 266{ 267 device_t bsddev; 268 int unit; 269 270 bsddev = NULL; 271 if (dev->devt) { 272 unit = MINOR(dev->devt); 273 bsddev = devclass_get_device(dev->class->bsdclass, unit); 274 } else 275 unit = -1; 276 if (bsddev == NULL) 277 bsddev = device_add_child(dev->parent->bsddev, 278 dev->class->kobj.name, unit); 279 if (bsddev) { 280 if (dev->devt == 0) 281 dev->devt = makedev(0, device_get_unit(bsddev)); 282 device_set_softc(bsddev, dev); 283 } 284 dev->bsddev = bsddev; 285 kobject_init(&dev->kobj, &dev_ktype); 286 kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); 287 288 return (0); 289} 290 291static inline void 292device_unregister(struct device *dev) 293{ 294 device_t bsddev; 295 296 bsddev = dev->bsddev; 297 mtx_lock(&Giant); 298 if (bsddev) 299 device_delete_child(device_get_parent(bsddev), bsddev); 300 mtx_unlock(&Giant); 301 put_device(dev); 302} 303 304struct device *device_create(struct class *class, struct device *parent, 305 dev_t devt, void *drvdata, const char *fmt, ...); 306 307static inline void 308device_destroy(struct class *class, dev_t devt) 309{ 310 device_t bsddev; 311 int unit; 312 313 unit = MINOR(devt); 314 bsddev = devclass_get_device(class->bsdclass, unit); 315 if (bsddev) 316 device_unregister(device_get_softc(bsddev)); 317} 318 319static inline void 320class_kfree(struct class *class) 321{ 322 323 kfree(class); 324} 325 326static inline struct class * 327class_create(struct module *owner, const char *name) 328{ 329 struct class *class; 330 int error; 331 332 class = kzalloc(sizeof(*class), M_WAITOK); 333 class->owner = owner; 334 class->name= name; 335 class->class_release = class_kfree; 336 error = class_register(class); 337 if (error) { 338 kfree(class); 339 return (NULL); 340 } 341 342 return (class); 343} 344 345static inline void 346class_destroy(struct class *class) 347{ 348 349 if (class == NULL) 350 return; 351 class_unregister(class); 352} 353 354static inline int 355device_create_file(struct device *dev, const struct device_attribute *attr) 356{ 357 358 if (dev) 359 return sysfs_create_file(&dev->kobj, &attr->attr); 360 return -EINVAL; 361} 362 363static inline void 364device_remove_file(struct device *dev, const struct device_attribute *attr) 365{ 366 367 if (dev) 368 sysfs_remove_file(&dev->kobj, &attr->attr); 369} 370 371static inline int 372class_create_file(struct class *class, const struct class_attribute *attr) 373{ 374 375 if (class) 376 return sysfs_create_file(&class->kobj, &attr->attr); 377 return -EINVAL; 378} 379 380static inline void 381class_remove_file(struct class *class, const struct class_attribute *attr) 382{ 383 384 if (class) 385 sysfs_remove_file(&class->kobj, &attr->attr); 386} 387 388static inline int dev_to_node(struct device *dev) 389{ 390 return -1; 391} 392 393 394#endif /* _LINUX_DEVICE_H_ */ 395