}
/*
- * Pass incoming event to all connected clients. Note that we are
- * caleld under a spinlock with interrupts off so we don't need
- * to use rcu_read_lock() here. Writers will be using syncronize_sched()
- * instead of synchrnoize_rcu().
+ * Pass incoming event to all connected clients.
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
event.code = code;
event.value = value;
+ rcu_read_lock();
+
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event);
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
wake_up_interruptible(&evdev->wait);
}
return error;
rcu_assign_pointer(evdev->grab, client);
- /*
- * We don't use synchronize_rcu() here because read-side
- * critical section is protected by a spinlock instead
- * of rcu_read_lock().
- */
- synchronize_sched();
+ synchronize_rcu();
return 0;
}
return -EINVAL;
rcu_assign_pointer(evdev->grab, NULL);
- synchronize_sched();
+ synchronize_rcu();
input_release_device(&evdev->handle);
return 0;
spin_lock(&evdev->client_lock);
list_add_tail_rcu(&client->node, &evdev->client_list);
spin_unlock(&evdev->client_lock);
- synchronize_sched();
+ synchronize_rcu();
}
static void evdev_detach_client(struct evdev *evdev,
spin_lock(&evdev->client_lock);
list_del_rcu(&client->node);
spin_unlock(&evdev->client_lock);
- synchronize_sched();
+ synchronize_rcu();
}
static int evdev_open_device(struct evdev *evdev)
if (!evdev->exist)
retval = -ENODEV;
- else if (!evdev->open++)
+ else if (!evdev->open++) {
retval = input_open_device(&evdev->handle);
+ if (retval)
+ evdev->open--;
+ }
mutex_unlock(&evdev->mutex);
return retval;
#elif defined(CONFIG_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
-# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
+# define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
#ifdef CONFIG_COMPAT
#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
#ifdef __BIG_ENDIAN
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
int len, i;
if (compat) {
- len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+ len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
if (len > maxlen)
len = maxlen;
sizeof(compat_long_t)))
return -EFAULT;
} else {
- len = NBITS(maxbit) * sizeof(long);
+ len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
unsigned int maxlen, void __user *p, int compat)
{
int len = compat ?
- NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
- NBITS(maxbit) * sizeof(long);
+ BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) :
+ BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, void __user *p, int compat)
{
- int len = NBITS(maxbit) * sizeof(long);
+ int len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;