#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
-#include <linux/suspend.h>
#include <linux/slab.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
SERIO_UNREGISTER_PORT,
};
-static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED; /* protects serio_event_list */
+static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited);
do {
serio_handle_events();
wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze(PF_FREEZE);
} while (!signal_pending(current));
printk(KERN_DEBUG "serio: kseriod exiting\n");
return sprintf(buf, "%s\n", serio->name);
}
-static ssize_t serio_show_driver(struct device *dev, char *buf)
-{
- return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
-}
-
static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
static struct device_attribute serio_device_attrs[] = {
__ATTR(description, S_IRUGO, serio_show_description, NULL),
- __ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver),
+ __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
__ATTR_NULL
};
try_module_get(THIS_MODULE);
spin_lock_init(&serio->lock);
+ init_MUTEX(&serio->drv_sem);
list_add_tail(&serio->node, &serio_list);
snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
serio->dev.bus = &serio_bus;
up(&serio_sem);
}
-/* called from serio_driver->connect/disconnect methods under serio_sem */
-int serio_open(struct serio *serio, struct serio_driver *drv)
+static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{
+ down(&serio->drv_sem);
serio_pause_rx(serio);
serio->drv = drv;
serio_continue_rx(serio);
+ up(&serio->drv_sem);
+}
+
+/* called from serio_driver->connect/disconnect methods under serio_sem */
+int serio_open(struct serio *serio, struct serio_driver *drv)
+{
+ serio_set_drv(serio, drv);
if (serio->open && serio->open(serio)) {
- serio_pause_rx(serio);
- serio->drv = NULL;
- serio_continue_rx(serio);
+ serio_set_drv(serio, NULL);
return -1;
}
return 0;
if (serio->close)
serio->close(serio);
- serio_pause_rx(serio);
- serio->drv = NULL;
- serio_continue_rx(serio);
+ serio_set_drv(serio, NULL);
}
irqreturn_t serio_interrupt(struct serio *serio,