aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-15 14:47:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-15 14:47:27 -0400
commit93ff81859733d9697a5a0cc4707e52fb17056abb (patch)
tree9bca6d06cf5dbd0feee592abecdc6e14f9a5dc92
parent89cbec71fead552fdd1fa38c57186669dfbba734 (diff)
parent3941dae15ed90437396389e8bb7d2d5b3e63ba4a (diff)
Merge branch 'work.__copy_to_user' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more __copy_.._user elimination from Al Viro. * 'work.__copy_to_user' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: drm_dp_aux_dev: switch to read_iter/write_iter
-rw-r--r--drivers/gpu/drm/drm_dp_aux_dev.c109
1 files changed, 46 insertions, 63 deletions
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index ec1ed94b2390..d34e5096887a 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -32,6 +32,7 @@
32#include <linux/kernel.h> 32#include <linux/kernel.h>
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/uaccess.h> 34#include <linux/uaccess.h>
35#include <linux/uio.h>
35#include <drm/drm_dp_helper.h> 36#include <drm/drm_dp_helper.h>
36#include <drm/drm_crtc.h> 37#include <drm/drm_crtc.h>
37#include <drm/drmP.h> 38#include <drm/drmP.h>
@@ -140,101 +141,83 @@ static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence)
140 return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET); 141 return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET);
141} 142}
142 143
143static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count, 144static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
144 loff_t *offset)
145{ 145{
146 size_t bytes_pending, num_bytes_processed = 0; 146 struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
147 struct drm_dp_aux_dev *aux_dev = file->private_data; 147 loff_t pos = iocb->ki_pos;
148 ssize_t res = 0; 148 ssize_t res = 0;
149 149
150 if (!atomic_inc_not_zero(&aux_dev->usecount)) 150 if (!atomic_inc_not_zero(&aux_dev->usecount))
151 return -ENODEV; 151 return -ENODEV;
152 152
153 bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - (*offset)); 153 iov_iter_truncate(to, AUX_MAX_OFFSET - pos);
154
155 if (!access_ok(VERIFY_WRITE, buf, bytes_pending)) {
156 res = -EFAULT;
157 goto out;
158 }
159 154
160 while (bytes_pending > 0) { 155 while (iov_iter_count(to)) {
161 uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 156 uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
162 ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 157 ssize_t todo = min(iov_iter_count(to), sizeof(buf));
163 158
164 if (signal_pending(current)) { 159 if (signal_pending(current)) {
165 res = num_bytes_processed ? 160 res = -ERESTARTSYS;
166 num_bytes_processed : -ERESTARTSYS; 161 break;
167 goto out;
168 } 162 }
169 163
170 res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo); 164 res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
171 if (res <= 0) { 165 if (res <= 0)
172 res = num_bytes_processed ? num_bytes_processed : res; 166 break;
173 goto out; 167
174 } 168 if (copy_to_iter(buf, res, to) != res) {
175 if (__copy_to_user(buf + num_bytes_processed, localbuf, res)) { 169 res = -EFAULT;
176 res = num_bytes_processed ? 170 break;
177 num_bytes_processed : -EFAULT;
178 goto out;
179 } 171 }
180 bytes_pending -= res; 172
181 *offset += res; 173 pos += res;
182 num_bytes_processed += res;
183 res = num_bytes_processed;
184 } 174 }
185 175
186out: 176 if (pos != iocb->ki_pos)
177 res = pos - iocb->ki_pos;
178 iocb->ki_pos = pos;
179
187 atomic_dec(&aux_dev->usecount); 180 atomic_dec(&aux_dev->usecount);
188 wake_up_atomic_t(&aux_dev->usecount); 181 wake_up_atomic_t(&aux_dev->usecount);
189 return res; 182 return res;
190} 183}
191 184
192static ssize_t auxdev_write(struct file *file, const char __user *buf, 185static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
193 size_t count, loff_t *offset)
194{ 186{
195 size_t bytes_pending, num_bytes_processed = 0; 187 struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
196 struct drm_dp_aux_dev *aux_dev = file->private_data; 188 loff_t pos = iocb->ki_pos;
197 ssize_t res = 0; 189 ssize_t res = 0;
198 190
199 if (!atomic_inc_not_zero(&aux_dev->usecount)) 191 if (!atomic_inc_not_zero(&aux_dev->usecount))
200 return -ENODEV; 192 return -ENODEV;
201 193
202 bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - *offset); 194 iov_iter_truncate(from, AUX_MAX_OFFSET - pos);
203
204 if (!access_ok(VERIFY_READ, buf, bytes_pending)) {
205 res = -EFAULT;
206 goto out;
207 }
208 195
209 while (bytes_pending > 0) { 196 while (iov_iter_count(from)) {
210 uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 197 uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
211 ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 198 ssize_t todo = min(iov_iter_count(from), sizeof(buf));
212 199
213 if (signal_pending(current)) { 200 if (signal_pending(current)) {
214 res = num_bytes_processed ? 201 res = -ERESTARTSYS;
215 num_bytes_processed : -ERESTARTSYS; 202 break;
216 goto out;
217 } 203 }
218 204
219 if (__copy_from_user(localbuf, 205 if (!copy_from_iter_full(buf, todo, from)) {
220 buf + num_bytes_processed, todo)) { 206 res = -EFAULT;
221 res = num_bytes_processed ? 207 break;
222 num_bytes_processed : -EFAULT;
223 goto out;
224 } 208 }
225 209
226 res = drm_dp_dpcd_write(aux_dev->aux, *offset, localbuf, todo); 210 res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
227 if (res <= 0) { 211 if (res <= 0)
228 res = num_bytes_processed ? num_bytes_processed : res; 212 break;
229 goto out; 213
230 } 214 pos += res;
231 bytes_pending -= res;
232 *offset += res;
233 num_bytes_processed += res;
234 res = num_bytes_processed;
235 } 215 }
236 216
237out: 217 if (pos != iocb->ki_pos)
218 res = pos - iocb->ki_pos;
219 iocb->ki_pos = pos;
220
238 atomic_dec(&aux_dev->usecount); 221 atomic_dec(&aux_dev->usecount);
239 wake_up_atomic_t(&aux_dev->usecount); 222 wake_up_atomic_t(&aux_dev->usecount);
240 return res; 223 return res;
@@ -251,8 +234,8 @@ static int auxdev_release(struct inode *inode, struct file *file)
251static const struct file_operations auxdev_fops = { 234static const struct file_operations auxdev_fops = {
252 .owner = THIS_MODULE, 235 .owner = THIS_MODULE,
253 .llseek = auxdev_llseek, 236 .llseek = auxdev_llseek,
254 .read = auxdev_read, 237 .read_iter = auxdev_read_iter,
255 .write = auxdev_write, 238 .write_iter = auxdev_write_iter,
256 .open = auxdev_open, 239 .open = auxdev_open,
257 .release = auxdev_release, 240 .release = auxdev_release,
258}; 241};