diff options
| author | Joel Becker <joel.becker@oracle.com> | 2010-04-30 13:37:29 -0700 | 
|---|---|---|
| committer | Joel Becker <joel.becker@oracle.com> | 2010-04-30 13:37:29 -0700 | 
| commit | f9221fd80343285514568da6c5dbda0f87109de8 (patch) | |
| tree | 3a2f0077ebea9d094bdeedb319c97cb591d51c51 /drivers/input/sparse-keymap.c | |
| parent | a36d515c7a2dfacebcf41729f6812dbc424ebcf0 (diff) | |
| parent | a9743fcdc0eb43d028b71267438076e1b0112ba0 (diff) | |
Merge branch 'skip_delete_inode' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2-mark into ocfs2-fixes
Diffstat (limited to 'drivers/input/sparse-keymap.c')
| -rw-r--r-- | drivers/input/sparse-keymap.c | 53 | 
1 files changed, 34 insertions, 19 deletions
| diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index e6bde55e5203..014248344763 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -15,6 +15,7 @@  #include <linux/input.h>  #include <linux/input/sparse-keymap.h> +#include <linux/slab.h>  MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");  MODULE_DESCRIPTION("Generic support for sparse keymaps"); @@ -67,12 +68,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev,  				    unsigned int scancode,  				    unsigned int *keycode)  { -	const struct key_entry *key = -			sparse_keymap_entry_from_scancode(dev, scancode); +	const struct key_entry *key; -	if (key && key->type == KE_KEY) { -		*keycode = key->keycode; -		return 0; +	if (dev->keycode) { +		key = sparse_keymap_entry_from_scancode(dev, scancode); +		if (key && key->type == KE_KEY) { +			*keycode = key->keycode; +			return 0; +		}  	}  	return -EINVAL; @@ -85,17 +88,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev,  	struct key_entry *key;  	int old_keycode; -	if (keycode < 0 || keycode > KEY_MAX) -		return -EINVAL; - -	key = sparse_keymap_entry_from_scancode(dev, scancode); -	if (key && key->type == KE_KEY) { -		old_keycode = key->keycode; -		key->keycode = keycode; -		set_bit(keycode, dev->keybit); -		if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) -			clear_bit(old_keycode, dev->keybit); -		return 0; +	if (dev->keycode) { +		key = sparse_keymap_entry_from_scancode(dev, scancode); +		if (key && key->type == KE_KEY) { +			old_keycode = key->keycode; +			key->keycode = keycode; +			set_bit(keycode, dev->keybit); +			if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) +				clear_bit(old_keycode, dev->keybit); +			return 0; +		}  	}  	return -EINVAL; @@ -163,7 +165,7 @@ int sparse_keymap_setup(struct input_dev *dev,  	return 0;   err_out: -	kfree(keymap); +	kfree(map);  	return error;  } @@ -175,14 +177,27 @@ EXPORT_SYMBOL(sparse_keymap_setup);   *   * This function is used to free memory allocated by sparse keymap   * in an input device that was set up by sparse_keymap_setup(). + * NOTE: It is safe to cal this function while input device is + * still registered (however the drivers should care not to try to + * use freed keymap and thus have to shut off interrups/polling + * before freeing the keymap).   */  void sparse_keymap_free(struct input_dev *dev)  { +	unsigned long flags; + +	/* +	 * Take event lock to prevent racing with input_get_keycode() +	 * and input_set_keycode() if we are called while input device +	 * is still registered. +	 */ +	spin_lock_irqsave(&dev->event_lock, flags); +  	kfree(dev->keycode);  	dev->keycode = NULL;  	dev->keycodemax = 0; -	dev->getkeycode = NULL; -	dev->setkeycode = NULL; + +	spin_unlock_irqrestore(&dev->event_lock, flags);  }  EXPORT_SYMBOL(sparse_keymap_free); | 
