diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2009-06-22 13:42:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-22 14:32:23 -0400 |
commit | eca41044268887838fa122aa24475df8f23d614c (patch) | |
tree | 9cf22d5b96037273f6aa30fb9eb61ff4f9f04b7b /drivers/char | |
parent | 52e3632ea603ef92757d5d0dedcd9fc8643445e3 (diff) |
n_r3964: fix lock imbalance
There is omitted BKunL in r3964_read.
Centralize the paths to one point with one unlock.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/n_r3964.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index d2e93e343226..2e99158ebb8a 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1062,7 +1062,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1062 | struct r3964_client_info *pClient; | 1062 | struct r3964_client_info *pClient; |
1063 | struct r3964_message *pMsg; | 1063 | struct r3964_message *pMsg; |
1064 | struct r3964_client_message theMsg; | 1064 | struct r3964_client_message theMsg; |
1065 | int count; | 1065 | int ret; |
1066 | 1066 | ||
1067 | TRACE_L("read()"); | 1067 | TRACE_L("read()"); |
1068 | 1068 | ||
@@ -1074,8 +1074,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1074 | if (pMsg == NULL) { | 1074 | if (pMsg == NULL) { |
1075 | /* no messages available. */ | 1075 | /* no messages available. */ |
1076 | if (file->f_flags & O_NONBLOCK) { | 1076 | if (file->f_flags & O_NONBLOCK) { |
1077 | unlock_kernel(); | 1077 | ret = -EAGAIN; |
1078 | return -EAGAIN; | 1078 | goto unlock; |
1079 | } | 1079 | } |
1080 | /* block until there is a message: */ | 1080 | /* block until there is a message: */ |
1081 | wait_event_interruptible(pInfo->read_wait, | 1081 | wait_event_interruptible(pInfo->read_wait, |
@@ -1085,29 +1085,31 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1085 | /* If we still haven't got a message, we must have been signalled */ | 1085 | /* If we still haven't got a message, we must have been signalled */ |
1086 | 1086 | ||
1087 | if (!pMsg) { | 1087 | if (!pMsg) { |
1088 | unlock_kernel(); | 1088 | ret = -EINTR; |
1089 | return -EINTR; | 1089 | goto unlock; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | /* deliver msg to client process: */ | 1092 | /* deliver msg to client process: */ |
1093 | theMsg.msg_id = pMsg->msg_id; | 1093 | theMsg.msg_id = pMsg->msg_id; |
1094 | theMsg.arg = pMsg->arg; | 1094 | theMsg.arg = pMsg->arg; |
1095 | theMsg.error_code = pMsg->error_code; | 1095 | theMsg.error_code = pMsg->error_code; |
1096 | count = sizeof(struct r3964_client_message); | 1096 | ret = sizeof(struct r3964_client_message); |
1097 | 1097 | ||
1098 | kfree(pMsg); | 1098 | kfree(pMsg); |
1099 | TRACE_M("r3964_read - msg kfree %p", pMsg); | 1099 | TRACE_M("r3964_read - msg kfree %p", pMsg); |
1100 | 1100 | ||
1101 | if (copy_to_user(buf, &theMsg, count)) { | 1101 | if (copy_to_user(buf, &theMsg, ret)) { |
1102 | unlock_kernel(); | 1102 | ret = -EFAULT; |
1103 | return -EFAULT; | 1103 | goto unlock; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | TRACE_PS("read - return %d", count); | 1106 | TRACE_PS("read - return %d", ret); |
1107 | return count; | 1107 | goto unlock; |
1108 | } | 1108 | } |
1109 | ret = -EPERM; | ||
1110 | unlock: | ||
1109 | unlock_kernel(); | 1111 | unlock_kernel(); |
1110 | return -EPERM; | 1112 | return ret; |
1111 | } | 1113 | } |
1112 | 1114 | ||
1113 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | 1115 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |