diff options
Diffstat (limited to 'drivers/misc/mei/main.c')
-rw-r--r-- | drivers/misc/mei/main.c | 106 |
1 files changed, 43 insertions, 63 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 80f9afcb1382..52635b063873 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -65,7 +65,7 @@ static int mei_open(struct inode *inode, struct file *file) | |||
65 | goto err_unlock; | 65 | goto err_unlock; |
66 | } | 66 | } |
67 | 67 | ||
68 | cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY); | 68 | cl = mei_cl_alloc_linked(dev); |
69 | if (IS_ERR(cl)) { | 69 | if (IS_ERR(cl)) { |
70 | err = PTR_ERR(cl); | 70 | err = PTR_ERR(cl); |
71 | goto err_unlock; | 71 | goto err_unlock; |
@@ -159,27 +159,22 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
159 | goto out; | 159 | goto out; |
160 | } | 160 | } |
161 | 161 | ||
162 | if (ubuf == NULL) { | ||
163 | rets = -EMSGSIZE; | ||
164 | goto out; | ||
165 | } | ||
166 | |||
162 | if (cl == &dev->iamthif_cl) { | 167 | if (cl == &dev->iamthif_cl) { |
163 | rets = mei_amthif_read(dev, file, ubuf, length, offset); | 168 | rets = mei_amthif_read(dev, file, ubuf, length, offset); |
164 | goto out; | 169 | goto out; |
165 | } | 170 | } |
166 | 171 | ||
167 | cb = mei_cl_read_cb(cl, file); | 172 | cb = mei_cl_read_cb(cl, file); |
168 | if (cb) { | 173 | if (cb) |
169 | /* read what left */ | 174 | goto copy_buffer; |
170 | if (cb->buf_idx > *offset) | 175 | |
171 | goto copy_buffer; | 176 | if (*offset > 0) |
172 | /* offset is beyond buf_idx we have no more data return 0 */ | ||
173 | if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { | ||
174 | rets = 0; | ||
175 | goto free; | ||
176 | } | ||
177 | /* Offset needs to be cleaned for contiguous reads*/ | ||
178 | if (cb->buf_idx == 0 && *offset > 0) | ||
179 | *offset = 0; | ||
180 | } else if (*offset > 0) { | ||
181 | *offset = 0; | 177 | *offset = 0; |
182 | } | ||
183 | 178 | ||
184 | err = mei_cl_read_start(cl, length, file); | 179 | err = mei_cl_read_start(cl, length, file); |
185 | if (err && err != -EBUSY) { | 180 | if (err && err != -EBUSY) { |
@@ -214,11 +209,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
214 | 209 | ||
215 | cb = mei_cl_read_cb(cl, file); | 210 | cb = mei_cl_read_cb(cl, file); |
216 | if (!cb) { | 211 | if (!cb) { |
217 | if (mei_cl_is_fixed_address(cl) && dev->allow_fixed_address) { | ||
218 | cb = mei_cl_read_cb(cl, NULL); | ||
219 | if (cb) | ||
220 | goto copy_buffer; | ||
221 | } | ||
222 | rets = 0; | 212 | rets = 0; |
223 | goto out; | 213 | goto out; |
224 | } | 214 | } |
@@ -231,10 +221,10 @@ copy_buffer: | |||
231 | goto free; | 221 | goto free; |
232 | } | 222 | } |
233 | 223 | ||
234 | cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld\n", | 224 | cl_dbg(dev, cl, "buf.size = %zu buf.idx = %zu offset = %lld\n", |
235 | cb->buf.size, cb->buf_idx); | 225 | cb->buf.size, cb->buf_idx, *offset); |
236 | if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { | 226 | if (*offset >= cb->buf_idx) { |
237 | rets = -EMSGSIZE; | 227 | rets = 0; |
238 | goto free; | 228 | goto free; |
239 | } | 229 | } |
240 | 230 | ||
@@ -250,11 +240,13 @@ copy_buffer: | |||
250 | 240 | ||
251 | rets = length; | 241 | rets = length; |
252 | *offset += length; | 242 | *offset += length; |
253 | if ((unsigned long)*offset < cb->buf_idx) | 243 | /* not all data was read, keep the cb */ |
244 | if (*offset < cb->buf_idx) | ||
254 | goto out; | 245 | goto out; |
255 | 246 | ||
256 | free: | 247 | free: |
257 | mei_io_cb_free(cb); | 248 | mei_io_cb_free(cb); |
249 | *offset = 0; | ||
258 | 250 | ||
259 | out: | 251 | out: |
260 | cl_dbg(dev, cl, "end mei read rets = %d\n", rets); | 252 | cl_dbg(dev, cl, "end mei read rets = %d\n", rets); |
@@ -275,9 +267,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
275 | size_t length, loff_t *offset) | 267 | size_t length, loff_t *offset) |
276 | { | 268 | { |
277 | struct mei_cl *cl = file->private_data; | 269 | struct mei_cl *cl = file->private_data; |
278 | struct mei_cl_cb *write_cb = NULL; | 270 | struct mei_cl_cb *cb; |
279 | struct mei_device *dev; | 271 | struct mei_device *dev; |
280 | unsigned long timeout = 0; | ||
281 | int rets; | 272 | int rets; |
282 | 273 | ||
283 | if (WARN_ON(!cl || !cl->dev)) | 274 | if (WARN_ON(!cl || !cl->dev)) |
@@ -313,52 +304,31 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
313 | goto out; | 304 | goto out; |
314 | } | 305 | } |
315 | 306 | ||
316 | if (cl == &dev->iamthif_cl) { | ||
317 | write_cb = mei_amthif_find_read_list_entry(dev, file); | ||
318 | |||
319 | if (write_cb) { | ||
320 | timeout = write_cb->read_time + | ||
321 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); | ||
322 | |||
323 | if (time_after(jiffies, timeout)) { | ||
324 | *offset = 0; | ||
325 | mei_io_cb_free(write_cb); | ||
326 | write_cb = NULL; | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | *offset = 0; | 307 | *offset = 0; |
332 | write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); | 308 | cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); |
333 | if (!write_cb) { | 309 | if (!cb) { |
334 | rets = -ENOMEM; | 310 | rets = -ENOMEM; |
335 | goto out; | 311 | goto out; |
336 | } | 312 | } |
337 | 313 | ||
338 | rets = copy_from_user(write_cb->buf.data, ubuf, length); | 314 | rets = copy_from_user(cb->buf.data, ubuf, length); |
339 | if (rets) { | 315 | if (rets) { |
340 | dev_dbg(dev->dev, "failed to copy data from userland\n"); | 316 | dev_dbg(dev->dev, "failed to copy data from userland\n"); |
341 | rets = -EFAULT; | 317 | rets = -EFAULT; |
318 | mei_io_cb_free(cb); | ||
342 | goto out; | 319 | goto out; |
343 | } | 320 | } |
344 | 321 | ||
345 | if (cl == &dev->iamthif_cl) { | 322 | if (cl == &dev->iamthif_cl) { |
346 | rets = mei_amthif_write(cl, write_cb); | 323 | rets = mei_amthif_write(cl, cb); |
347 | 324 | if (!rets) | |
348 | if (rets) { | 325 | rets = length; |
349 | dev_err(dev->dev, | 326 | goto out; |
350 | "amthif write failed with status = %d\n", rets); | ||
351 | goto out; | ||
352 | } | ||
353 | mutex_unlock(&dev->device_lock); | ||
354 | return length; | ||
355 | } | 327 | } |
356 | 328 | ||
357 | rets = mei_cl_write(cl, write_cb, false); | 329 | rets = mei_cl_write(cl, cb, false); |
358 | out: | 330 | out: |
359 | mutex_unlock(&dev->device_lock); | 331 | mutex_unlock(&dev->device_lock); |
360 | if (rets < 0) | ||
361 | mei_io_cb_free(write_cb); | ||
362 | return rets; | 332 | return rets; |
363 | } | 333 | } |
364 | 334 | ||
@@ -393,12 +363,22 @@ static int mei_ioctl_connect_client(struct file *file, | |||
393 | 363 | ||
394 | /* find ME client we're trying to connect to */ | 364 | /* find ME client we're trying to connect to */ |
395 | me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid); | 365 | me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid); |
396 | if (!me_cl || | 366 | if (!me_cl) { |
397 | (me_cl->props.fixed_address && !dev->allow_fixed_address)) { | ||
398 | dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n", | 367 | dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n", |
399 | &data->in_client_uuid); | 368 | &data->in_client_uuid); |
400 | mei_me_cl_put(me_cl); | 369 | rets = -ENOTTY; |
401 | return -ENOTTY; | 370 | goto end; |
371 | } | ||
372 | |||
373 | if (me_cl->props.fixed_address) { | ||
374 | bool forbidden = dev->override_fixed_address ? | ||
375 | !dev->allow_fixed_address : !dev->hbm_f_fa_supported; | ||
376 | if (forbidden) { | ||
377 | dev_dbg(dev->dev, "Connection forbidden to FW Client UUID = %pUl\n", | ||
378 | &data->in_client_uuid); | ||
379 | rets = -ENOTTY; | ||
380 | goto end; | ||
381 | } | ||
402 | } | 382 | } |
403 | 383 | ||
404 | dev_dbg(dev->dev, "Connect to FW Client ID = %d\n", | 384 | dev_dbg(dev->dev, "Connect to FW Client ID = %d\n", |
@@ -454,7 +434,7 @@ end: | |||
454 | * | 434 | * |
455 | * Return: 0 on success , <0 on error | 435 | * Return: 0 on success , <0 on error |
456 | */ | 436 | */ |
457 | static int mei_ioctl_client_notify_request(struct file *file, u32 request) | 437 | static int mei_ioctl_client_notify_request(const struct file *file, u32 request) |
458 | { | 438 | { |
459 | struct mei_cl *cl = file->private_data; | 439 | struct mei_cl *cl = file->private_data; |
460 | 440 | ||
@@ -473,7 +453,7 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request) | |||
473 | * | 453 | * |
474 | * Return: 0 on success , <0 on error | 454 | * Return: 0 on success , <0 on error |
475 | */ | 455 | */ |
476 | static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get) | 456 | static int mei_ioctl_client_notify_get(const struct file *file, u32 *notify_get) |
477 | { | 457 | { |
478 | struct mei_cl *cl = file->private_data; | 458 | struct mei_cl *cl = file->private_data; |
479 | bool notify_ev; | 459 | bool notify_ev; |