summaryrefslogtreecommitdiff
path: root/drivers/char/ipmi/ipmi_devintf.c
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2006-03-26 13:37:21 +0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 20:56:56 +0400
commit50c812b2b9513e3df34eae8c30cb2c221b79b2cb (patch)
tree565f31d3b3234e5324ba9534b752ae426b4a8c92 /drivers/char/ipmi/ipmi_devintf.c
parentb0defcdbd2b7da7694e2645da92716cea0a3c0ff (diff)
downloadlinux-50c812b2b9513e3df34eae8c30cb2c221b79b2cb.tar.xz
[PATCH] ipmi: add full sysfs support
Add full driver model support for the IPMI driver. It links in the proper bus and device support. It adds an "ipmi" driver interface that has each BMC discovered by the driver (as a device). These BMCs appear in the devices/platform directory. If there are multiple interfaces to the same BMC, the driver should discover this and will only have one BMC entry. The BMC entry will have pointers to each interface device that connects to it. The device information (statistics and config information) has not yet been ported over to the driver model from proc, that will come later. This work was based on work by Yani Ioannou. I basically rewrote it using that code as a guide, but he still deserves credit :). [bunk@stusta.de: make ipmi_find_bmc_guid() static] Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Yani Ioannou <yani.ioannou@gmail.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_devintf.c')
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 7c0684deea06..932feedda262 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -90,7 +90,7 @@ static unsigned int ipmi_poll(struct file *file, poll_table *wait)
spin_lock_irqsave(&priv->recv_msg_lock, flags);
- if (! list_empty(&(priv->recv_msgs)))
+ if (!list_empty(&(priv->recv_msgs)))
mask |= (POLLIN | POLLRDNORM);
spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
@@ -789,21 +789,53 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" interface. Other values will set the major device number"
" to that value.");
+/* Keep track of the devices that are registered. */
+struct ipmi_reg_list {
+ dev_t dev;
+ struct list_head link;
+};
+static LIST_HEAD(reg_list);
+static DEFINE_MUTEX(reg_list_mutex);
+
static struct class *ipmi_class;
-static void ipmi_new_smi(int if_num)
+static void ipmi_new_smi(int if_num, struct device *device)
{
dev_t dev = MKDEV(ipmi_major, if_num);
+ struct ipmi_reg_list *entry;
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
- class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ printk(KERN_ERR "ipmi_devintf: Unable to create the"
+ " ipmi class device link\n");
+ return;
+ }
+ entry->dev = dev;
+
+ mutex_lock(&reg_list_mutex);
+ class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
+ list_add(&entry->link, &reg_list);
+ mutex_unlock(&reg_list_mutex);
}
static void ipmi_smi_gone(int if_num)
{
- class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
+ dev_t dev = MKDEV(ipmi_major, if_num);
+ struct ipmi_reg_list *entry;
+
+ mutex_lock(&reg_list_mutex);
+ list_for_each_entry(entry, &reg_list, link) {
+ if (entry->dev == dev) {
+ list_del(&entry->link);
+ kfree(entry);
+ break;
+ }
+ }
+ class_device_destroy(ipmi_class, dev);
+ mutex_unlock(&reg_list_mutex);
devfs_remove("ipmidev/%d", if_num);
}
@@ -856,6 +888,14 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
+ struct ipmi_reg_list *entry, *entry2;
+ mutex_lock(&reg_list_mutex);
+ list_for_each_entry_safe(entry, entry2, &reg_list, link) {
+ list_del(&entry->link);
+ class_device_destroy(ipmi_class, entry->dev);
+ kfree(entry);
+ }
+ mutex_unlock(&reg_list_mutex);
class_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);