diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_devintf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_devintf.c | 48 |
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) | |||
90 | 90 | ||
91 | spin_lock_irqsave(&priv->recv_msg_lock, flags); | 91 | spin_lock_irqsave(&priv->recv_msg_lock, flags); |
92 | 92 | ||
93 | if (! list_empty(&(priv->recv_msgs))) | 93 | if (!list_empty(&(priv->recv_msgs))) |
94 | mask |= (POLLIN | POLLRDNORM); | 94 | mask |= (POLLIN | POLLRDNORM); |
95 | 95 | ||
96 | spin_unlock_irqrestore(&priv->recv_msg_lock, flags); | 96 | 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" | |||
789 | " interface. Other values will set the major device number" | 789 | " interface. Other values will set the major device number" |
790 | " to that value."); | 790 | " to that value."); |
791 | 791 | ||
792 | /* Keep track of the devices that are registered. */ | ||
793 | struct ipmi_reg_list { | ||
794 | dev_t dev; | ||
795 | struct list_head link; | ||
796 | }; | ||
797 | static LIST_HEAD(reg_list); | ||
798 | static DEFINE_MUTEX(reg_list_mutex); | ||
799 | |||
792 | static struct class *ipmi_class; | 800 | static struct class *ipmi_class; |
793 | 801 | ||
794 | static void ipmi_new_smi(int if_num) | 802 | static void ipmi_new_smi(int if_num, struct device *device) |
795 | { | 803 | { |
796 | dev_t dev = MKDEV(ipmi_major, if_num); | 804 | dev_t dev = MKDEV(ipmi_major, if_num); |
805 | struct ipmi_reg_list *entry; | ||
797 | 806 | ||
798 | devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, | 807 | devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, |
799 | "ipmidev/%d", if_num); | 808 | "ipmidev/%d", if_num); |
800 | 809 | ||
801 | class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num); | 810 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
811 | if (!entry) { | ||
812 | printk(KERN_ERR "ipmi_devintf: Unable to create the" | ||
813 | " ipmi class device link\n"); | ||
814 | return; | ||
815 | } | ||
816 | entry->dev = dev; | ||
817 | |||
818 | mutex_lock(®_list_mutex); | ||
819 | class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num); | ||
820 | list_add(&entry->link, ®_list); | ||
821 | mutex_unlock(®_list_mutex); | ||
802 | } | 822 | } |
803 | 823 | ||
804 | static void ipmi_smi_gone(int if_num) | 824 | static void ipmi_smi_gone(int if_num) |
805 | { | 825 | { |
806 | class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num)); | 826 | dev_t dev = MKDEV(ipmi_major, if_num); |
827 | struct ipmi_reg_list *entry; | ||
828 | |||
829 | mutex_lock(®_list_mutex); | ||
830 | list_for_each_entry(entry, ®_list, link) { | ||
831 | if (entry->dev == dev) { | ||
832 | list_del(&entry->link); | ||
833 | kfree(entry); | ||
834 | break; | ||
835 | } | ||
836 | } | ||
837 | class_device_destroy(ipmi_class, dev); | ||
838 | mutex_unlock(®_list_mutex); | ||
807 | devfs_remove("ipmidev/%d", if_num); | 839 | devfs_remove("ipmidev/%d", if_num); |
808 | } | 840 | } |
809 | 841 | ||
@@ -856,6 +888,14 @@ module_init(init_ipmi_devintf); | |||
856 | 888 | ||
857 | static __exit void cleanup_ipmi(void) | 889 | static __exit void cleanup_ipmi(void) |
858 | { | 890 | { |
891 | struct ipmi_reg_list *entry, *entry2; | ||
892 | mutex_lock(®_list_mutex); | ||
893 | list_for_each_entry_safe(entry, entry2, ®_list, link) { | ||
894 | list_del(&entry->link); | ||
895 | class_device_destroy(ipmi_class, entry->dev); | ||
896 | kfree(entry); | ||
897 | } | ||
898 | mutex_unlock(®_list_mutex); | ||
859 | class_destroy(ipmi_class); | 899 | class_destroy(ipmi_class); |
860 | ipmi_smi_watcher_unregister(&smi_watcher); | 900 | ipmi_smi_watcher_unregister(&smi_watcher); |
861 | devfs_remove(DEVICE_NAME); | 901 | devfs_remove(DEVICE_NAME); |