cregit-Linux how code gets into the kernel

Release 4.7 drivers/char/misc.c

Directory: drivers/char
/*
 * linux/drivers/char/misc.c
 *
 * Generic misc open routine by Johan Myreen
 *
 * Based on code from Linus
 *
 * Teemu Rantanen's Microsoft Busmouse support and Derrick Cole's
 *   changes incorporated into 0.97pl4
 *   by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
 *   See busmouse.c for particulars.
 *
 * Made things a lot mode modular - easy to compile in just one or two
 * of the misc drivers, as they are now completely independent. Linus.
 *
 * Support for loadable modules. 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
 *
 * Fixed a failing symbol register to free the device registration
 *              Alan Cox <alan@lxorguk.ukuu.org.uk> 21-Jan-96
 *
 * Dynamic minors and /proc/mice by Alessandro Rubini. 26-Mar-96
 *
 * Renamed to misc and miscdevice to be more accurate. Alan Cox 26-Mar-96
 *
 * Handling of mouse minor numbers for kerneld:
 *  Idea by Jacques Gelinas <jack@solucorp.qc.ca>,
 *  adapted by Bjorn Ekwall <bj0rn@blox.se>
 *  corrected by Alan Cox <alan@lxorguk.ukuu.org.uk>
 *
 * Changes for kmod (from kerneld):
 *      Cyrus Durgin <cider@speakeasy.org>
 *
 * Added devfs support. Richard Gooch <rgooch@atnf.csiro.au>  10-Jan-1998
 */

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

/*
 * Head entry for the doubly linked miscdevice list
 */
static LIST_HEAD(misc_list);
static DEFINE_MUTEX(misc_mtx);

/*
 * Assigned numbers, used for dynamic minors
 */

#define DYNAMIC_MINORS 64 
/* like dynamic majors */
static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);

#ifdef CONFIG_PROC_FS

static void *misc_seq_start(struct seq_file *seq, loff_t *pos) { mutex_lock(&misc_mtx); return seq_list_start(&misc_list, *pos); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger1753.12%233.33%
pre-gitpre-git825.00%233.33%
pavel emelianovpavel emelianov515.62%116.67%
matthias kaehlckematthias kaehlcke26.25%116.67%
Total32100.00%6100.00%


static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { return seq_list_next(v, &misc_list, pos); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger2580.65%133.33%
pavel emelianovpavel emelianov516.13%133.33%
pre-gitpre-git13.23%133.33%
Total31100.00%3100.00%


static void misc_seq_stop(struct seq_file *seq, void *v) { mutex_unlock(&misc_mtx); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger1990.48%150.00%
matthias kaehlckematthias kaehlcke29.52%150.00%
Total21100.00%2100.00%


static int misc_seq_show(struct seq_file *seq, void *v) { const struct miscdevice *p = list_entry(v, struct miscdevice, list); seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : ""); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger3054.55%125.00%
pre-gitpre-git1730.91%250.00%
pavel emelianovpavel emelianov814.55%125.00%
Total55100.00%4100.00%

static const struct seq_operations misc_seq_ops = { .start = misc_seq_start, .next = misc_seq_next, .stop = misc_seq_stop, .show = misc_seq_show, };
static int misc_seq_open(struct inode *inode, struct file *file) { return seq_open(file, &misc_seq_ops); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger2288.00%133.33%
pre-gitpre-git312.00%266.67%
Total25100.00%3100.00%

static const struct file_operations misc_proc_fops = { .owner = THIS_MODULE, .open = misc_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; #endif
static int misc_open(struct inode * inode, struct file * file) { int minor = iminor(inode); struct miscdevice *c; int err = -ENODEV; const struct file_operations *new_fops = NULL; mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { new_fops = fops_get(c->fops); break; } } if (!new_fops) { mutex_unlock(&misc_mtx); request_module("char-major-%d-%d", MISC_MAJOR, minor); mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { new_fops = fops_get(c->fops); break; } } if (!new_fops) goto fail; } /* * Place the miscdevice in the file's * private_data so it can be used by the * file operations, including f_op->open below */ file->private_data = c; err = 0; replace_fops(file, new_fops); if (file->f_op->open) err = file->f_op->open(inode,file); fail: mutex_unlock(&misc_mtx); return err; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git13870.77%1157.89%
stephen hemmingerstephen hemminger3216.41%15.26%
matthias kaehlckematthias kaehlcke84.10%15.26%
tom van braeckeltom van braeckel73.59%15.26%
al viroal viro52.56%210.53%
mikael petterssonmikael pettersson31.54%15.26%
linus torvaldslinus torvalds10.51%15.26%
arjan van de venarjan van de ven10.51%15.26%
Total195100.00%19100.00%

static struct class *misc_class; static const struct file_operations misc_fops = { .owner = THIS_MODULE, .open = misc_open, .llseek = noop_llseek, }; /** * misc_register - register a miscellaneous device * @misc: device structure * * Register a miscellaneous device with the kernel. If the minor * number is set to %MISC_DYNAMIC_MINOR a minor number is assigned * and placed in the minor field of the structure. For other cases * the minor number requested is used. * * The structure passed is linked into the kernel and may not be * destroyed until it has been unregistered. By default, an open() * syscall to the device sets file->private_data to point to the * structure. Drivers don't need open in fops for this. * * A zero is returned on success and a negative errno code for * failure. */
int misc_register(struct miscdevice * misc) { dev_t dev; int err = 0; bool is_dynamic = (misc->minor == MISC_DYNAMIC_MINOR); INIT_LIST_HEAD(&misc->list); mutex_lock(&misc_mtx); if (is_dynamic) { int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); if (i >= DYNAMIC_MINORS) { err = -EBUSY; goto out; } misc->minor = DYNAMIC_MINORS - i - 1; set_bit(i, misc_minors); } else { struct miscdevice *c; list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { err = -EBUSY; goto out; } } } dev = MKDEV(MISC_MAJOR, misc->minor); misc->this_device = device_create_with_groups(misc_class, misc->parent, dev, misc, misc->groups, "%s", misc->name); if (IS_ERR(misc->this_device)) { if (is_dynamic) { int i = DYNAMIC_MINORS - misc->minor - 1; if (i < DYNAMIC_MINORS && i >= 0) clear_bit(i, misc_minors); misc->minor = MISC_DYNAMIC_MINOR; } err = PTR_ERR(misc->this_device); goto out; } /* * Add it to the front, so that later devices can "override" * earlier defaults */ list_add(&misc->list, &misc_list); out: mutex_unlock(&misc_mtx); return err; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5220.47%521.74%
thadeu lima de souza cascardothadeu lima de souza cascardo4517.72%28.70%
stephen hemmingerstephen hemminger3614.17%28.70%
dae s. kimdae s. kim3212.60%14.35%
greg kroah-hartmangreg kroah-hartman2710.63%521.74%
vladimir zapolskiyvladimir zapolskiy249.45%14.35%
elad wexlerelad wexler124.72%14.35%
neil hormanneil horman83.15%14.35%
robert loverobert love62.36%14.35%
takashi iwaitakashi iwai51.97%14.35%
matthias kaehlckematthias kaehlcke41.57%14.35%
andrew mortonandrew morton20.79%14.35%
kay sieverskay sievers10.39%14.35%
Total254100.00%23100.00%

/** * misc_deregister - unregister a miscellaneous device * @misc: device to unregister * * Unregister a miscellaneous device that was previously * successfully registered with misc_register(). */
void misc_deregister(struct miscdevice *misc) { int i = DYNAMIC_MINORS - misc->minor - 1; if (WARN_ON(list_empty(&misc->list))) return; mutex_lock(&misc_mtx); list_del(&misc->list); device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); if (i < DYNAMIC_MINORS && i >= 0) clear_bit(i, misc_minors); mutex_unlock(&misc_mtx); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git4147.67%323.08%
greg kroah-hartmangreg kroah-hartman1618.60%430.77%
thadeu lima de souza cascardothadeu lima de souza cascardo1112.79%215.38%
stephen hemmingerstephen hemminger1011.63%17.69%
matthias kaehlckematthias kaehlcke44.65%17.69%
akinobu mitaakinobu mita33.49%17.69%
rafael j. wysockirafael j. wysocki11.16%17.69%
Total86100.00%13100.00%

EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister);
static char *misc_devnode(struct device *dev, umode_t *mode) { struct miscdevice *c = dev_get_drvdata(dev); if (mode && c->mode) *mode = c->mode; if (c->nodename) return kstrdup(c->nodename, GFP_KERNEL); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
kay sieverskay sievers5998.33%266.67%
al viroal viro11.67%133.33%
Total60100.00%3100.00%


static int __init misc_init(void) { int err; struct proc_dir_entry *ret; ret = proc_create("misc", 0, NULL, &misc_proc_fops); misc_class = class_create(THIS_MODULE, "misc"); err = PTR_ERR(misc_class); if (IS_ERR(misc_class)) goto fail_remove; err = -EIO; if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) goto fail_printk; misc_class->devnode = misc_devnode; return 0; fail_printk: printk("unable to get major %d for misc devices\n", MISC_MAJOR); class_destroy(misc_class); fail_remove: if (ret) remove_proc_entry("misc", NULL); return err; }

Contributors

PersonTokensPropCommitsCommitProp
denis v. lunevdenis v. lunev3933.62%15.26%
pre-gitpre-git3429.31%947.37%
greg kroah-hartmangreg kroah-hartman1815.52%315.79%
sudip mukherjeesudip mukherjee119.48%15.26%
kay sieverskay sievers65.17%210.53%
chris wrightchris wright43.45%15.26%
stephen hemmingerstephen hemminger32.59%15.26%
andrew mortonandrew morton10.86%15.26%
Total116100.00%19100.00%

subsys_initcall(misc_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git37034.91%2739.13%
stephen hemmingerstephen hemminger26124.62%34.35%
greg kroah-hartmangreg kroah-hartman726.79%710.14%
kay sieverskay sievers666.23%22.90%
thadeu lima de souza cascardothadeu lima de souza cascardo615.75%22.90%
denis v. lunevdenis v. lunev393.68%11.45%
dae s. kimdae s. kim323.02%11.45%
matthias kaehlckematthias kaehlcke252.36%11.45%
vladimir zapolskiyvladimir zapolskiy242.26%11.45%
pavel emelianovpavel emelianov181.70%11.45%
elad wexlerelad wexler121.13%11.45%
sudip mukherjeesudip mukherjee111.04%11.45%
neil hormanneil horman80.75%11.45%
tom van braeckeltom van braeckel70.66%11.45%
andrew mortonandrew morton70.66%22.90%
al viroal viro60.57%34.35%
robert loverobert love60.57%11.45%
arnd bergmannarnd bergmann50.47%11.45%
takashi iwaitakashi iwai50.47%11.45%
art haasart haas40.38%11.45%
chris wrightchris wright40.38%11.45%
mikael petterssonmikael pettersson30.28%11.45%
arjan van de venarjan van de ven30.28%22.90%
tejun heotejun heo30.28%11.45%
akinobu mitaakinobu mita30.28%11.45%
rafael j. wysockirafael j. wysocki20.19%11.45%
tal shorertal shorer10.09%11.45%
linus torvaldslinus torvalds10.09%11.45%
james morrisjames morris10.09%11.45%
Total1060100.00%69100.00%
Directory: drivers/char
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}