diff options
author | Mariusz Gorski <marius.gorski@gmail.com> | 2014-11-04 22:47:19 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-05 14:58:07 -0800 |
commit | f4757af8516d95aaf9c6a1238887c34914e54622 (patch) | |
tree | 6cf53a8bc7b6d7b5c30ffa4512952407a7a1d7fe /drivers/staging/panel | |
parent | 54fbb2da8d4cef4f57d0cf70b84471dd61a7af5f (diff) | |
download | talos-obmc-linux-f4757af8516d95aaf9c6a1238887c34914e54622.tar.gz talos-obmc-linux-f4757af8516d95aaf9c6a1238887c34914e54622.zip |
staging: panel: Fix single-open policy race condition
Fix the implementation of a single-open policy for both
devices (lcd and keypad) by using atomic_t instead of plain ints.
Signed-off-by: Mariusz Gorski <marius.gorski@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/panel')
-rw-r--r-- | drivers/staging/panel/panel.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 98556ce8af6a..d30ccb594785 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -404,8 +404,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; #endif /* DEFAULT_PROFILE == 0 */ /* global variables */ -static int keypad_open_cnt; /* #times opened */ -static int lcd_open_cnt; /* #times opened */ + +/* Device single-open policy control */ +static atomic_t lcd_available = ATOMIC_INIT(1); +static atomic_t keypad_available = ATOMIC_INIT(1); + static struct pardevice *pprt; static int lcd_initialized; @@ -1347,7 +1350,7 @@ static ssize_t lcd_write(struct file *file, static int lcd_open(struct inode *inode, struct file *file) { - if (lcd_open_cnt) + if (!atomic_dec_and_test(&lcd_available)) return -EBUSY; /* open only once at a time */ if (file->f_mode & FMODE_READ) /* device is write-only */ @@ -1357,13 +1360,12 @@ static int lcd_open(struct inode *inode, struct file *file) lcd_clear_display(); lcd_must_clear = 0; } - lcd_open_cnt++; return nonseekable_open(inode, file); } static int lcd_release(struct inode *inode, struct file *file) { - lcd_open_cnt--; + atomic_inc(&lcd_available); return 0; } @@ -1627,20 +1629,19 @@ static ssize_t keypad_read(struct file *file, static int keypad_open(struct inode *inode, struct file *file) { - if (keypad_open_cnt) + if (!atomic_dec_and_test(&keypad_available)) return -EBUSY; /* open only once at a time */ if (file->f_mode & FMODE_WRITE) /* device is read-only */ return -EPERM; keypad_buflen = 0; /* flush the buffer on opening */ - keypad_open_cnt++; return 0; } static int keypad_release(struct inode *inode, struct file *file) { - keypad_open_cnt--; + atomic_inc(&keypad_available); return 0; } @@ -1663,7 +1664,7 @@ static void keypad_send_key(const char *string, int max_len) return; /* send the key to the device only if a process is attached to it. */ - if (keypad_open_cnt > 0) { + if (!atomic_read(&keypad_available)) { while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { keypad_buffer[(keypad_start + keypad_buflen++) % KEYPAD_BUFFER] = *string++; |