Skip to content

Commit 93ff818

Browse files
committed
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
2 parents 89cbec7 + 3941dae commit 93ff818

File tree

1 file changed

+46
-63
lines changed

1 file changed

+46
-63
lines changed

drivers/gpu/drm/drm_dp_aux_dev.c

Lines changed: 46 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/kernel.h>
3333
#include <linux/module.h>
3434
#include <linux/uaccess.h>
35+
#include <linux/uio.h>
3536
#include <drm/drm_dp_helper.h>
3637
#include <drm/drm_crtc.h>
3738
#include <drm/drmP.h>
@@ -140,101 +141,83 @@ static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence)
140141
return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET);
141142
}
142143

143-
static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count,
144-
loff_t *offset)
144+
static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
145145
{
146-
size_t bytes_pending, num_bytes_processed = 0;
147-
struct drm_dp_aux_dev *aux_dev = file->private_data;
146+
struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
147+
loff_t pos = iocb->ki_pos;
148148
ssize_t res = 0;
149149

150150
if (!atomic_inc_not_zero(&aux_dev->usecount))
151151
return -ENODEV;
152152

153-
bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - (*offset));
154-
155-
if (!access_ok(VERIFY_WRITE, buf, bytes_pending)) {
156-
res = -EFAULT;
157-
goto out;
158-
}
153+
iov_iter_truncate(to, AUX_MAX_OFFSET - pos);
159154

160-
while (bytes_pending > 0) {
161-
uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
162-
ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));
155+
while (iov_iter_count(to)) {
156+
uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
157+
ssize_t todo = min(iov_iter_count(to), sizeof(buf));
163158

164159
if (signal_pending(current)) {
165-
res = num_bytes_processed ?
166-
num_bytes_processed : -ERESTARTSYS;
167-
goto out;
160+
res = -ERESTARTSYS;
161+
break;
168162
}
169163

170-
res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo);
171-
if (res <= 0) {
172-
res = num_bytes_processed ? num_bytes_processed : res;
173-
goto out;
174-
}
175-
if (__copy_to_user(buf + num_bytes_processed, localbuf, res)) {
176-
res = num_bytes_processed ?
177-
num_bytes_processed : -EFAULT;
178-
goto out;
164+
res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
165+
if (res <= 0)
166+
break;
167+
168+
if (copy_to_iter(buf, res, to) != res) {
169+
res = -EFAULT;
170+
break;
179171
}
180-
bytes_pending -= res;
181-
*offset += res;
182-
num_bytes_processed += res;
183-
res = num_bytes_processed;
172+
173+
pos += res;
184174
}
185175

186-
out:
176+
if (pos != iocb->ki_pos)
177+
res = pos - iocb->ki_pos;
178+
iocb->ki_pos = pos;
179+
187180
atomic_dec(&aux_dev->usecount);
188181
wake_up_atomic_t(&aux_dev->usecount);
189182
return res;
190183
}
191184

192-
static ssize_t auxdev_write(struct file *file, const char __user *buf,
193-
size_t count, loff_t *offset)
185+
static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
194186
{
195-
size_t bytes_pending, num_bytes_processed = 0;
196-
struct drm_dp_aux_dev *aux_dev = file->private_data;
187+
struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
188+
loff_t pos = iocb->ki_pos;
197189
ssize_t res = 0;
198190

199191
if (!atomic_inc_not_zero(&aux_dev->usecount))
200192
return -ENODEV;
201193

202-
bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - *offset);
203-
204-
if (!access_ok(VERIFY_READ, buf, bytes_pending)) {
205-
res = -EFAULT;
206-
goto out;
207-
}
194+
iov_iter_truncate(from, AUX_MAX_OFFSET - pos);
208195

209-
while (bytes_pending > 0) {
210-
uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
211-
ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));
196+
while (iov_iter_count(from)) {
197+
uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
198+
ssize_t todo = min(iov_iter_count(from), sizeof(buf));
212199

213200
if (signal_pending(current)) {
214-
res = num_bytes_processed ?
215-
num_bytes_processed : -ERESTARTSYS;
216-
goto out;
201+
res = -ERESTARTSYS;
202+
break;
217203
}
218204

219-
if (__copy_from_user(localbuf,
220-
buf + num_bytes_processed, todo)) {
221-
res = num_bytes_processed ?
222-
num_bytes_processed : -EFAULT;
223-
goto out;
205+
if (!copy_from_iter_full(buf, todo, from)) {
206+
res = -EFAULT;
207+
break;
224208
}
225209

226-
res = drm_dp_dpcd_write(aux_dev->aux, *offset, localbuf, todo);
227-
if (res <= 0) {
228-
res = num_bytes_processed ? num_bytes_processed : res;
229-
goto out;
230-
}
231-
bytes_pending -= res;
232-
*offset += res;
233-
num_bytes_processed += res;
234-
res = num_bytes_processed;
210+
res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
211+
if (res <= 0)
212+
break;
213+
214+
pos += res;
235215
}
236216

237-
out:
217+
if (pos != iocb->ki_pos)
218+
res = pos - iocb->ki_pos;
219+
iocb->ki_pos = pos;
220+
238221
atomic_dec(&aux_dev->usecount);
239222
wake_up_atomic_t(&aux_dev->usecount);
240223
return res;
@@ -251,8 +234,8 @@ static int auxdev_release(struct inode *inode, struct file *file)
251234
static const struct file_operations auxdev_fops = {
252235
.owner = THIS_MODULE,
253236
.llseek = auxdev_llseek,
254-
.read = auxdev_read,
255-
.write = auxdev_write,
237+
.read_iter = auxdev_read_iter,
238+
.write_iter = auxdev_write_iter,
256239
.open = auxdev_open,
257240
.release = auxdev_release,
258241
};

0 commit comments

Comments
 (0)