Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: sentelic - fix left/right horizontal scroll mapping
  Input: pmouse - move Sentelic probe down the list
  Input: add compat support for sysfs and /proc capabilities output
  Input: i8042 - add Dritek quirk for Acer Aspire 5610.
  Input: xbox - do not use GFP_KERNEL under spinlock
  Input: psmouse - fix Synaptics detection when protocol is disabled
  Input: bcm5974 - report ABS_MT events
  Input: davinci_keyscan - add device_enable method to platform data
  Input: evdev - be less aggressive about sending SIGIO notifies
  Input: atkbd - fix canceling event_work in disconnect
  Input: serio - fix potential deadlock when unbinding drivers
  Input: gf2k - fix &&/|| confusion in gf2k_connect()
  • Loading branch information
Linus Torvalds committed Jan 15, 2010
2 parents 9fc8191 + c332e9f commit 3b3ef30
Show file tree
Hide file tree
Showing 14 changed files with 208 additions and 121 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-davinci/include/mach/keyscan.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum davinci_matrix_types {
};

struct davinci_ks_platform_data {
int (*device_enable)(struct device *dev);
unsigned short *keymap;
u32 keymapsize;
u8 rep:1;
Expand Down
3 changes: 2 additions & 1 deletion drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client,
client->head &= EVDEV_BUFFER_SIZE - 1;
spin_unlock(&client->buffer_lock);

kill_fasync(&client->fasync, SIGIO, POLL_IN);
if (event->type == EV_SYN)
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}

/*
Expand Down
86 changes: 71 additions & 15 deletions drivers/input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include <linux/smp_lock.h>
#include "input-compat.h"

MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
Expand Down Expand Up @@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
return error;
}

#ifdef CONFIG_COMPAT

static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
int len = 0;

if (INPUT_COMPAT_TEST) {
u32 dword = bits >> 32;
if (dword || !skip_empty)
len += snprintf(buf, buf_size, "%x ", dword);

dword = bits & 0xffffffffUL;
if (dword || !skip_empty || len)
len += snprintf(buf + len, max(buf_size - len, 0),
"%x", dword);
} else {
if (bits || !skip_empty)
len += snprintf(buf, buf_size, "%lx", bits);
}

return len;
}

#else /* !CONFIG_COMPAT */

static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
return bits || !skip_empty ?
snprintf(buf, buf_size, "%lx", bits) : 0;
}

#endif

#ifdef CONFIG_PROC_FS

Expand Down Expand Up @@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
unsigned long *bitmap, int max)
{
int i;

for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
bool skip_empty = true;
char buf[18];

seq_printf(seq, "B: %s=", name);
for (; i >= 0; i--)
seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");

for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
if (input_bits_to_string(buf, sizeof(buf),
bitmap[i], skip_empty)) {
skip_empty = false;
seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
}
}

/*
* If no output was produced print a single 0.
*/
if (skip_empty)
seq_puts(seq, "0");

seq_putc(seq, '\n');
}

Expand Down Expand Up @@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
{
int i;
int len = 0;
bool skip_empty = true;

for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
len += input_bits_to_string(buf + len, max(buf_size - len, 0),
bitmap[i], skip_empty);
if (len) {
skip_empty = false;
if (i > 0)
len += snprintf(buf + len, max(buf_size - len, 0), " ");
}
}

for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
if (bitmap[i])
break;

for (; i >= 0; i--)
len += snprintf(buf + len, max(buf_size - len, 0),
"%lx%s", bitmap[i], i > 0 ? " " : "");
/*
* If no output was produced print a single 0.
*/
if (len == 0)
len = snprintf(buf, buf_size, "%d", 0);

if (add_cr)
len += snprintf(buf + len, max(buf_size - len, 0), "\n");
Expand All @@ -1150,7 +1205,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
int len = input_print_bitmap(buf, PAGE_SIZE, \
input_dev->bm##bit, ev##_MAX, 1); \
input_dev->bm##bit, ev##_MAX, \
true); \
return min_t(int, len, PAGE_SIZE); \
} \
static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
Expand Down Expand Up @@ -1214,7 +1270,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,

len = input_print_bitmap(&env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen,
bitmap, max, 0);
bitmap, max, false);
if (len >= (sizeof(env->buf) - env->buflen))
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion drivers/input/joystick/gf2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
}

#ifdef RESET_WORKS
if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) &&
(gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
err = -ENODEV;
goto fail2;
Expand Down
4 changes: 2 additions & 2 deletions drivers/input/joystick/xpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb)
}

exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
__func__, retval);
Expand Down Expand Up @@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
xpad->odata[6] = 0x00;
xpad->odata[7] = 0x00;
xpad->irq_out->transfer_buffer_length = 8;
usb_submit_urb(xpad->irq_out, GFP_KERNEL);
usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
}

return 0;
Expand Down
69 changes: 33 additions & 36 deletions drivers/input/keyboard/atkbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,10 @@ struct atkbd {

struct delayed_work event_work;
unsigned long event_jiffies;
struct mutex event_mutex;
unsigned long event_mask;

/* Serializes reconnect(), attr->set() and event work */
struct mutex mutex;
};

/*
Expand Down Expand Up @@ -577,7 +579,7 @@ static void atkbd_event_work(struct work_struct *work)
{
struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);

mutex_lock(&atkbd->event_mutex);
mutex_lock(&atkbd->mutex);

if (!atkbd->enabled) {
/*
Expand All @@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work)
atkbd_set_repeat_rate(atkbd);
}

mutex_unlock(&atkbd->event_mutex);
mutex_unlock(&atkbd->mutex);
}

/*
Expand All @@ -612,7 +614,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)

atkbd->event_jiffies = jiffies;
set_bit(event_bit, &atkbd->event_mask);
wmb();
mb();
schedule_delayed_work(&atkbd->event_work, delay);
}

Expand Down Expand Up @@ -849,13 +851,20 @@ static void atkbd_disconnect(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);

sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);

atkbd_disable(atkbd);

/* make sure we don't have a command in flight */
input_unregister_device(atkbd->dev);

/*
* Make sure we don't have a command in flight.
* Note that since atkbd->enabled is false event work will keep
* rescheduling itself until it gets canceled and will not try
* accessing freed input device or serio port.
*/
cancel_delayed_work_sync(&atkbd->event_work);

sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
input_unregister_device(atkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(atkbd);
Expand Down Expand Up @@ -1087,7 +1096,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->event_mutex);
mutex_init(&atkbd->mutex);

switch (serio->id.type) {

Expand Down Expand Up @@ -1160,19 +1169,23 @@ static int atkbd_reconnect(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
int retval = -1;

if (!atkbd || !drv) {
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}

mutex_lock(&atkbd->mutex);

atkbd_disable(atkbd);

if (atkbd->write) {
if (atkbd_probe(atkbd))
return -1;
goto out;

if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
return -1;
goto out;

atkbd_activate(atkbd);

Expand All @@ -1190,8 +1203,11 @@ static int atkbd_reconnect(struct serio *serio)
}

atkbd_enable(atkbd);
retval = 0;

return 0;
out:
mutex_unlock(&atkbd->mutex);
return retval;
}

static struct serio_device_id atkbd_serio_ids[] = {
Expand Down Expand Up @@ -1235,47 +1251,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *))
{
struct serio *serio = to_serio_port(dev);
int retval;

retval = serio_pin_driver(serio);
if (retval)
return retval;

if (serio->drv != &atkbd_drv) {
retval = -ENODEV;
goto out;
}

retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
struct atkbd *atkbd = serio_get_drvdata(serio);

out:
serio_unpin_driver(serio);
return retval;
return handler(atkbd, buf);
}

static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
ssize_t (*handler)(struct atkbd *, const char *, size_t))
{
struct serio *serio = to_serio_port(dev);
struct atkbd *atkbd;
struct atkbd *atkbd = serio_get_drvdata(serio);
int retval;

retval = serio_pin_driver(serio);
retval = mutex_lock_interruptible(&atkbd->mutex);
if (retval)
return retval;

if (serio->drv != &atkbd_drv) {
retval = -ENODEV;
goto out;
}

atkbd = serio_get_drvdata(serio);
atkbd_disable(atkbd);
retval = handler(atkbd, buf, count);
atkbd_enable(atkbd);

out:
serio_unpin_driver(serio);
mutex_unlock(&atkbd->mutex);

return retval;
}

Expand Down
8 changes: 8 additions & 0 deletions drivers/input/keyboard/davinci_keyscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
int error, i;

if (pdata->device_enable) {
error = pdata->device_enable(dev);
if (error < 0) {
dev_dbg(dev, "device enable function failed\n");
return error;
}
}

if (!pdata->keymap) {
dev_dbg(dev, "no keymap from pdata\n");
return -EINVAL;
Expand Down
Loading

0 comments on commit 3b3ef30

Please sign in to comment.