1 /* 2 * linux/fs/char_dev.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 #include <linux/config.h> 8 #include <linux/init.h> 9 #include <linux/fs.h> 10 #include <linux/slab.h> 11 #include <linux/string.h> 12 13 #include <linux/major.h> 14 #include <linux/errno.h> 15 #include <linux/module.h> 16 #include <linux/smp_lock.h> 17 #include <linux/devfs_fs_kernel.h> 18 19 #include <linux/kobject.h> 20 #include <linux/kobj_map.h> 21 #include <linux/cdev.h> 22 23 #ifdef CONFIG_KMOD 24 #include <linux/kmod.h> 25 #endif 26 27 static struct kobj_map *cdev_map; 28 29 #define MAX_PROBE_HASH 255 /* random */ 30 31 static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED; 32 33 static struct char_device_struct { 34 struct char_device_struct *next; 35 unsigned int major; 36 unsigned int baseminor; 37 int minorct; 38 const char *name; 39 struct file_operations *fops; 40 struct cdev *cdev; /* will die */ 41 } *chrdevs[MAX_PROBE_HASH]; 42 43 /* index in the above */ 44 static inline int major_to_index(int major) 45 { 46 return major % MAX_PROBE_HASH; 47 } 48 49 /* get char device names in somewhat random order */ 50 int get_chrdev_list(char *page) 51 { 52 struct char_device_struct *cd; 53 int i, len; 54 55 len = sprintf(page, "Character devices:\n"); 56 57 read_lock(&chrdevs_lock); 58 for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { 59 for (cd = chrdevs[i]; cd; cd = cd->next) 60 len += sprintf(page+len, "%3d %s\n", 61 cd->major, cd->name); 62 } 63 read_unlock(&chrdevs_lock); 64 65 return len; 66 } 67 68 /* 69 * Register a single major with a specified minor range. 70 * 71 * If major == 0 this functions will dynamically allocate a major and return 72 * its number. 73 * 74 * If major > 0 this function will attempt to reserve the passed range of 75 * minors and will return zero on success. 76 * 77 * Returns a -ve errno on failure. 78 */ 79 static struct char_device_struct * 80 __register_chrdev_region(unsigned int major, unsigned int baseminor, 81 int minorct, const char *name) 82 { 83 struct char_device_struct *cd, **cp; 84 int ret = 0; 85 int i; 86 87 cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL); 88 if (cd == NULL) 89 return ERR_PTR(-ENOMEM); 90 91 memset(cd, 0, sizeof(struct char_device_struct)); 92 93 write_lock_irq(&chrdevs_lock); 94 95 /* temporary */ 96 if (major == 0) { 97 for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { 98 if (chrdevs[i] == NULL) 99 break; 100 } 101 102 if (i == 0) { 103 ret = -EBUSY; 104 goto out; 105 } 106 major = i; 107 ret = major; 108 } 109 110 cd->major = major; 111 cd->baseminor = baseminor; 112 cd->minorct = minorct; 113 cd->name = name; 114 115 i = major_to_index(major); 116 117 for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) 118 if ((*cp)->major > major || 119 ((*cp)->major == major && (*cp)->baseminor >= baseminor)) 120 break; 121 if (*cp && (*cp)->major == major && 122 (*cp)->baseminor < baseminor + minorct) { 123 ret = -EBUSY; 124 goto out; 125 } 126 cd->next = *cp; 127 *cp = cd; 128 write_unlock_irq(&chrdevs_lock); 129 return cd; 130 out: 131 write_unlock_irq(&chrdevs_lock); 132 kfree(cd); 133 return ERR_PTR(ret); 134 } 135 136 static struct char_device_struct * 137 __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) 138 { 139 struct char_device_struct *cd = NULL, **cp; 140 int i = major_to_index(major); 141 142 write_lock_irq(&chrdevs_lock); 143 for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) 144 if ((*cp)->major == major && 145 (*cp)->baseminor == baseminor && 146 (*cp)->minorct == minorct) 147 break; 148 if (*cp) { 149 cd = *cp; 150 *cp = cd->next; 151 } 152 write_unlock_irq(&chrdevs_lock); 153 return cd; 154 } 155 156 int register_chrdev_region(dev_t from, unsigned count, char *name) 157 { 158 struct char_device_struct *cd; 159 dev_t to = from + count; 160 dev_t n, next; 161 162 for (n = from; n < to; n = next) { 163 next = MKDEV(MAJOR(n)+1, 0); 164 if (next > to) 165 next = to; 166 cd = __register_chrdev_region(MAJOR(n), MINOR(n), 167 next - n, name); 168 if (IS_ERR(cd)) 169 goto fail; 170 } 171 return 0; 172 fail: 173 to = n; 174 for (n = from; n < to; n = next) { 175 next = MKDEV(MAJOR(n)+1, 0); 176 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); 177 } 178 return PTR_ERR(cd); 179 } 180 181 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char *name) 182 { 183 struct char_device_struct *cd; 184 cd = __register_chrdev_region(0, baseminor, count, name); 185 if (IS_ERR(cd)) 186 return PTR_ERR(cd); 187 *dev = MKDEV(cd->major, cd->baseminor); 188 return 0; 189 } 190 191 int register_chrdev(unsigned int major, const char *name, 192 struct file_operations *fops) 193 { 194 struct char_device_struct *cd; 195 struct cdev *cdev; 196 char *s; 197 int err = -ENOMEM; 198 199 cd = __register_chrdev_region(major, 0, 256, name); 200 if (IS_ERR(cd)) 201 return PTR_ERR(cd); 202 203 cdev = cdev_alloc(); 204 if (!cdev) 205 goto out2; 206 207 cdev->owner = fops->owner; 208 cdev->ops = fops; 209 strcpy(cdev->kobj.name, name); 210 for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/')) 211 *s = '!'; 212 213 err = cdev_add(cdev, MKDEV(cd->major, 0), 256); 214 if (err) 215 goto out; 216 217 cd->cdev = cdev; 218 219 return major ? 0 : cd->major; 220 out: 221 kobject_put(&cdev->kobj); 222 out2: 223 kfree(__unregister_chrdev_region(cd->major, 0, 256)); 224 return err; 225 } 226 227 void unregister_chrdev_region(dev_t from, unsigned count) 228 { 229 dev_t to = from + count; 230 dev_t n, next; 231 232 for (n = from; n < to; n = next) { 233 next = MKDEV(MAJOR(n)+1, 0); 234 if (next > to) 235 next = to; 236 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); 237 } 238 } 239 240 int unregister_chrdev(unsigned int major, const char *name) 241 { 242 struct char_device_struct *cd; 243 cd = __unregister_chrdev_region(major, 0, 256); 244 if (cd && cd->cdev) 245 cdev_del(cd->cdev); 246 kfree(cd); 247 return 0; 248 } 249 250 static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED; 251 /* 252 * Called every time a character special file is opened 253 */ 254 int chrdev_open(struct inode * inode, struct file * filp) 255 { 256 struct cdev *p; 257 struct cdev *new = NULL; 258 int ret = 0; 259 260 spin_lock(&cdev_lock); 261 p = inode->i_cdev; 262 if (!p) { 263 struct kobject *kobj; 264 int idx; 265 spin_unlock(&cdev_lock); 266 kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); 267 if (!kobj) 268 return -ENXIO; 269 new = container_of(kobj, struct cdev, kobj); 270 spin_lock(&cdev_lock); 271 p = inode->i_cdev; 272 if (!p) { 273 inode->i_cdev = p = new; 274 inode->i_cindex = idx; 275 list_add(&inode->i_devices, &p->list); 276 new = NULL; 277 } else if (!cdev_get(p)) 278 ret = -ENXIO; 279 } else if (!cdev_get(p)) 280 ret = -ENXIO; 281 spin_unlock(&cdev_lock); 282 cdev_put(new); 283 if (ret) 284 return ret; 285 filp->f_op = fops_get(p->ops); 286 if (!filp->f_op) { 287 cdev_put(p); 288 return -ENXIO; 289 } 290 if (filp->f_op->open) { 291 lock_kernel(); 292 ret = filp->f_op->open(inode,filp); 293 unlock_kernel(); 294 } 295 if (ret) 296 cdev_put(p); 297 return ret; 298 } 299 300 void cd_forget(struct inode *inode) 301 { 302 spin_lock(&cdev_lock); 303 list_del_init(&inode->i_devices); 304 inode->i_cdev = NULL; 305 spin_unlock(&cdev_lock); 306 } 307 308 void cdev_purge(struct cdev *cdev) 309 { 310 spin_lock(&cdev_lock); 311 while (!list_empty(&cdev->list)) { 312 struct inode *inode; 313 inode = container_of(cdev->list.next, struct inode, i_devices); 314 list_del_init(&inode->i_devices); 315 inode->i_cdev = NULL; 316 } 317 spin_unlock(&cdev_lock); 318 } 319 320 /* 321 * Dummy default file-operations: the only thing this does 322 * is contain the open that then fills in the correct operations 323 * depending on the special file... 324 */ 325 struct file_operations def_chr_fops = { 326 .open = chrdev_open, 327 }; 328 329 static struct kobject *exact_match(dev_t dev, int *part, void *data) 330 { 331 struct cdev *p = data; 332 return &p->kobj; 333 } 334 335 static int exact_lock(dev_t dev, void *data) 336 { 337 struct cdev *p = data; 338 return cdev_get(p) ? 0 : -1; 339 } 340 341 int cdev_add(struct cdev *p, dev_t dev, unsigned count) 342 { 343 p->dev = dev; 344 p->count = count; 345 return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); 346 } 347 348 static void cdev_unmap(dev_t dev, unsigned count) 349 { 350 kobj_unmap(cdev_map, dev, count); 351 } 352 353 void cdev_del(struct cdev *p) 354 { 355 cdev_unmap(p->dev, p->count); 356 kobject_put(&p->kobj); 357 } 358 359 struct kobject *cdev_get(struct cdev *p) 360 { 361 struct module *owner = p->owner; 362 struct kobject *kobj; 363 364 if (owner && !try_module_get(owner)) 365 return NULL; 366 kobj = kobject_get(&p->kobj); 367 if (!kobj) 368 module_put(owner); 369 return kobj; 370 } 371 372 void cdev_put(struct cdev *p) 373 { 374 if (p) { 375 kobject_put(&p->kobj); 376 module_put(p->owner); 377 } 378 } 379 380 static decl_subsys(cdev, NULL, NULL); 381 382 static void cdev_default_release(struct kobject *kobj) 383 { 384 struct cdev *p = container_of(kobj, struct cdev, kobj); 385 cdev_purge(p); 386 } 387 388 static void cdev_dynamic_release(struct kobject *kobj) 389 { 390 struct cdev *p = container_of(kobj, struct cdev, kobj); 391 cdev_purge(p); 392 kfree(p); 393 } 394 395 static struct kobj_type ktype_cdev_default = { 396 .release = cdev_default_release, 397 }; 398 399 static struct kobj_type ktype_cdev_dynamic = { 400 .release = cdev_dynamic_release, 401 }; 402 403 struct cdev *cdev_alloc(void) 404 { 405 struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL); 406 if (p) { 407 memset(p, 0, sizeof(struct cdev)); 408 p->kobj.ktype = &ktype_cdev_dynamic; 409 INIT_LIST_HEAD(&p->list); 410 kobject_init(&p->kobj); 411 } 412 return p; 413 } 414 415 void cdev_init(struct cdev *cdev, struct file_operations *fops) 416 { 417 INIT_LIST_HEAD(&cdev->list); 418 cdev->kobj.ktype = &ktype_cdev_default; 419 kobject_init(&cdev->kobj); 420 cdev->ops = fops; 421 } 422 423 static struct kobject *base_probe(dev_t dev, int *part, void *data) 424 { 425 if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0) 426 /* Make old-style 2.4 aliases work */ 427 request_module("char-major-%d", MAJOR(dev)); 428 return NULL; 429 } 430 431 void __init chrdev_init(void) 432 { 433 /* 434 * Keep cdev_subsys around because (and only because) the kobj_map code 435 * depends on the rwsem it contains. We don't make it public in sysfs, 436 * however. 437 */ 438 subsystem_init(&cdev_subsys); 439 cdev_map = kobj_map_init(base_probe, &cdev_subsys); 440 } 441 442 443 /* Let modules do char dev stuff */ 444 EXPORT_SYMBOL(register_chrdev_region); 445 EXPORT_SYMBOL(unregister_chrdev_region); 446 EXPORT_SYMBOL(alloc_chrdev_region); 447 EXPORT_SYMBOL(cdev_init); 448 EXPORT_SYMBOL(cdev_alloc); 449 EXPORT_SYMBOL(cdev_get); 450 EXPORT_SYMBOL(cdev_put); 451 EXPORT_SYMBOL(cdev_del); 452 EXPORT_SYMBOL(cdev_add); 453 EXPORT_SYMBOL(register_chrdev); 454 EXPORT_SYMBOL(unregister_chrdev); 455
This page was automatically generated by LXR 0.3.1. • Linux is a registered trademark of Linus Torvalds