linux/drivers/hwmon/hwmon.c
<<
>>
Prefs
   1/*
   2    hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
   3
   4    This file defines the sysfs class "hwmon", for use by sensors drivers.
   5
   6    Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
   7
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; version 2 of the License.
  11*/
  12
  13#include <linux/module.h>
  14#include <linux/device.h>
  15#include <linux/err.h>
  16#include <linux/kdev_t.h>
  17#include <linux/idr.h>
  18#include <linux/hwmon.h>
  19#include <linux/gfp.h>
  20#include <linux/spinlock.h>
  21
  22#define HWMON_ID_PREFIX "hwmon"
  23#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
  24
  25static struct class *hwmon_class;
  26
  27static DEFINE_IDR(hwmon_idr);
  28static DEFINE_SPINLOCK(idr_lock);
  29
  30/**
  31 * hwmon_device_register - register w/ hwmon
  32 * @dev: the device to register
  33 *
  34 * hwmon_device_unregister() must be called when the device is no
  35 * longer needed.
  36 *
  37 * Returns the pointer to the new device.
  38 */
  39struct device *hwmon_device_register(struct device *dev)
  40{
  41        struct device *hwdev;
  42        int id, err;
  43
  44again:
  45        if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
  46                return ERR_PTR(-ENOMEM);
  47
  48        spin_lock(&idr_lock);
  49        err = idr_get_new(&hwmon_idr, NULL, &id);
  50        spin_unlock(&idr_lock);
  51
  52        if (unlikely(err == -EAGAIN))
  53                goto again;
  54        else if (unlikely(err))
  55                return ERR_PTR(err);
  56
  57        id = id & MAX_ID_MASK;
  58        hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
  59                              HWMON_ID_FORMAT, id);
  60
  61        if (IS_ERR(hwdev)) {
  62                spin_lock(&idr_lock);
  63                idr_remove(&hwmon_idr, id);
  64                spin_unlock(&idr_lock);
  65        }
  66
  67        return hwdev;
  68}
  69
  70/**
  71 * hwmon_device_unregister - removes the previously registered class device
  72 *
  73 * @dev: the class device to destroy
  74 */
  75void hwmon_device_unregister(struct device *dev)
  76{
  77        int id;
  78
  79        if (likely(sscanf(dev->bus_id, HWMON_ID_FORMAT, &id) == 1)) {
  80                device_unregister(dev);
  81                spin_lock(&idr_lock);
  82                idr_remove(&hwmon_idr, id);
  83                spin_unlock(&idr_lock);
  84        } else
  85                dev_dbg(dev->parent,
  86                        "hwmon_device_unregister() failed: bad class ID!\n");
  87}
  88
  89static int __init hwmon_init(void)
  90{
  91        hwmon_class = class_create(THIS_MODULE, "hwmon");
  92        if (IS_ERR(hwmon_class)) {
  93                printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
  94                return PTR_ERR(hwmon_class);
  95        }
  96        return 0;
  97}
  98
  99static void __exit hwmon_exit(void)
 100{
 101        class_destroy(hwmon_class);
 102}
 103
 104subsys_initcall(hwmon_init);
 105module_exit(hwmon_exit);
 106
 107EXPORT_SYMBOL_GPL(hwmon_device_register);
 108EXPORT_SYMBOL_GPL(hwmon_device_unregister);
 109
 110MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
 111MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
 112MODULE_LICENSE("GPL");
 113
 114
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.