.. | .. |
---|
28 | 28 | * OTHER DEALINGS IN THE SOFTWARE. |
---|
29 | 29 | */ |
---|
30 | 30 | |
---|
31 | | -#include <linux/vmalloc.h> |
---|
32 | | -#include <linux/slab.h> |
---|
33 | | -#include <linux/log2.h> |
---|
34 | 31 | #include <linux/export.h> |
---|
| 32 | +#include <linux/log2.h> |
---|
| 33 | +#include <linux/mm.h> |
---|
| 34 | +#include <linux/mman.h> |
---|
| 35 | +#include <linux/nospec.h> |
---|
| 36 | +#include <linux/pci.h> |
---|
| 37 | +#include <linux/slab.h> |
---|
| 38 | +#include <linux/uaccess.h> |
---|
| 39 | +#include <linux/vmalloc.h> |
---|
| 40 | + |
---|
35 | 41 | #include <asm/shmparam.h> |
---|
36 | | -#include <drm/drmP.h> |
---|
| 42 | + |
---|
| 43 | +#include <drm/drm_agpsupport.h> |
---|
| 44 | +#include <drm/drm_device.h> |
---|
| 45 | +#include <drm/drm_drv.h> |
---|
| 46 | +#include <drm/drm_file.h> |
---|
| 47 | +#include <drm/drm_print.h> |
---|
| 48 | + |
---|
37 | 49 | #include "drm_legacy.h" |
---|
38 | 50 | |
---|
39 | | -#include <linux/nospec.h> |
---|
40 | 51 | |
---|
41 | 52 | static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, |
---|
42 | 53 | struct drm_local_map *map) |
---|
43 | 54 | { |
---|
44 | 55 | struct drm_map_list *entry; |
---|
| 56 | + |
---|
45 | 57 | list_for_each_entry(entry, &dev->maplist, head) { |
---|
46 | 58 | /* |
---|
47 | 59 | * Because the kernel-userspace ABI is fixed at a 32-bit offset |
---|
.. | .. |
---|
91 | 103 | |
---|
92 | 104 | if (!use_hashed_handle) { |
---|
93 | 105 | int ret; |
---|
| 106 | + |
---|
94 | 107 | hash->key = user_token >> PAGE_SHIFT; |
---|
95 | 108 | ret = drm_ht_insert_item(&dev->map_hash, hash); |
---|
96 | 109 | if (ret != -EINVAL) |
---|
.. | .. |
---|
123 | 136 | shift, add); |
---|
124 | 137 | } |
---|
125 | 138 | |
---|
126 | | -/** |
---|
| 139 | +/* |
---|
127 | 140 | * Core function to create a range of memory available for mapping by a |
---|
128 | 141 | * non-root process. |
---|
129 | 142 | * |
---|
.. | .. |
---|
138 | 151 | { |
---|
139 | 152 | struct drm_local_map *map; |
---|
140 | 153 | struct drm_map_list *list; |
---|
141 | | - drm_dma_handle_t *dmah; |
---|
142 | 154 | unsigned long user_token; |
---|
143 | 155 | int ret; |
---|
144 | 156 | |
---|
.. | .. |
---|
313 | 325 | * As we're limiting the address to 2^32-1 (or less), |
---|
314 | 326 | * casting it down to 32 bits is no problem, but we |
---|
315 | 327 | * need to point to a 64bit variable first. */ |
---|
316 | | - dmah = drm_pci_alloc(dev, map->size, map->size); |
---|
317 | | - if (!dmah) { |
---|
| 328 | + map->handle = dma_alloc_coherent(&dev->pdev->dev, |
---|
| 329 | + map->size, |
---|
| 330 | + &map->offset, |
---|
| 331 | + GFP_KERNEL); |
---|
| 332 | + if (!map->handle) { |
---|
318 | 333 | kfree(map); |
---|
319 | 334 | return -ENOMEM; |
---|
320 | 335 | } |
---|
321 | | - map->handle = dmah->vaddr; |
---|
322 | | - map->offset = (unsigned long)dmah->busaddr; |
---|
323 | | - kfree(dmah); |
---|
324 | 336 | break; |
---|
325 | 337 | default: |
---|
326 | 338 | kfree(map); |
---|
.. | .. |
---|
377 | 389 | } |
---|
378 | 390 | EXPORT_SYMBOL(drm_legacy_addmap); |
---|
379 | 391 | |
---|
380 | | -/** |
---|
| 392 | +struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, |
---|
| 393 | + unsigned int token) |
---|
| 394 | +{ |
---|
| 395 | + struct drm_map_list *_entry; |
---|
| 396 | + |
---|
| 397 | + list_for_each_entry(_entry, &dev->maplist, head) |
---|
| 398 | + if (_entry->user_token == token) |
---|
| 399 | + return _entry->map; |
---|
| 400 | + return NULL; |
---|
| 401 | +} |
---|
| 402 | +EXPORT_SYMBOL(drm_legacy_findmap); |
---|
| 403 | + |
---|
| 404 | +/* |
---|
381 | 405 | * Ioctl to specify a range of memory that is available for mapping by a |
---|
382 | 406 | * non-root process. |
---|
383 | 407 | * |
---|
.. | .. |
---|
400 | 424 | |
---|
401 | 425 | if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && |
---|
402 | 426 | !drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
403 | | - return -EINVAL; |
---|
| 427 | + return -EOPNOTSUPP; |
---|
404 | 428 | |
---|
405 | 429 | err = drm_addmap_core(dev, map->offset, map->size, map->type, |
---|
406 | 430 | map->flags, &maplist); |
---|
.. | .. |
---|
446 | 470 | |
---|
447 | 471 | if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && |
---|
448 | 472 | !drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
449 | | - return -EINVAL; |
---|
| 473 | + return -EOPNOTSUPP; |
---|
450 | 474 | |
---|
451 | 475 | idx = map->offset; |
---|
452 | 476 | if (idx < 0) |
---|
.. | .. |
---|
478 | 502 | return 0; |
---|
479 | 503 | } |
---|
480 | 504 | |
---|
481 | | -/** |
---|
| 505 | +/* |
---|
482 | 506 | * Remove a map private from list and deallocate resources if the mapping |
---|
483 | 507 | * isn't in use. |
---|
484 | 508 | * |
---|
485 | 509 | * Searches the map on drm_device::maplist, removes it from the list, see if |
---|
486 | | - * its being used, and free any associate resource (such as MTRR's) if it's not |
---|
| 510 | + * it's being used, and free any associated resource (such as MTRR's) if it's not |
---|
487 | 511 | * being on use. |
---|
488 | 512 | * |
---|
489 | 513 | * \sa drm_legacy_addmap |
---|
.. | .. |
---|
491 | 515 | int drm_legacy_rmmap_locked(struct drm_device *dev, struct drm_local_map *map) |
---|
492 | 516 | { |
---|
493 | 517 | struct drm_map_list *r_list = NULL, *list_t; |
---|
494 | | - drm_dma_handle_t dmah; |
---|
495 | 518 | int found = 0; |
---|
496 | 519 | struct drm_master *master; |
---|
497 | 520 | |
---|
.. | .. |
---|
514 | 537 | switch (map->type) { |
---|
515 | 538 | case _DRM_REGISTERS: |
---|
516 | 539 | iounmap(map->handle); |
---|
517 | | - /* FALLTHROUGH */ |
---|
| 540 | + fallthrough; |
---|
518 | 541 | case _DRM_FRAME_BUFFER: |
---|
519 | 542 | arch_phys_wc_del(map->mtrr); |
---|
520 | 543 | break; |
---|
.. | .. |
---|
532 | 555 | case _DRM_SCATTER_GATHER: |
---|
533 | 556 | break; |
---|
534 | 557 | case _DRM_CONSISTENT: |
---|
535 | | - dmah.vaddr = map->handle; |
---|
536 | | - dmah.busaddr = map->offset; |
---|
537 | | - dmah.size = map->size; |
---|
538 | | - __drm_legacy_pci_free(dev, &dmah); |
---|
| 558 | + dma_free_coherent(&dev->pdev->dev, |
---|
| 559 | + map->size, |
---|
| 560 | + map->handle, |
---|
| 561 | + map->offset); |
---|
539 | 562 | break; |
---|
540 | 563 | } |
---|
541 | 564 | kfree(map); |
---|
.. | .. |
---|
573 | 596 | mutex_unlock(&dev->struct_mutex); |
---|
574 | 597 | } |
---|
575 | 598 | |
---|
| 599 | +void drm_legacy_rmmaps(struct drm_device *dev) |
---|
| 600 | +{ |
---|
| 601 | + struct drm_map_list *r_list, *list_temp; |
---|
| 602 | + |
---|
| 603 | + list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) |
---|
| 604 | + drm_legacy_rmmap(dev, r_list->map); |
---|
| 605 | +} |
---|
| 606 | + |
---|
576 | 607 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on |
---|
577 | 608 | * the last close of the device, and this is necessary for cleanup when things |
---|
578 | 609 | * exit uncleanly. Therefore, having userland manually remove mappings seems |
---|
.. | .. |
---|
598 | 629 | |
---|
599 | 630 | if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && |
---|
600 | 631 | !drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
601 | | - return -EINVAL; |
---|
| 632 | + return -EOPNOTSUPP; |
---|
602 | 633 | |
---|
603 | 634 | mutex_lock(&dev->struct_mutex); |
---|
604 | 635 | list_for_each_entry(r_list, &dev->maplist, head) { |
---|
.. | .. |
---|
610 | 641 | } |
---|
611 | 642 | } |
---|
612 | 643 | |
---|
613 | | - /* List has wrapped around to the head pointer, or its empty we didn't |
---|
| 644 | + /* List has wrapped around to the head pointer, or it's empty we didn't |
---|
614 | 645 | * find anything. |
---|
615 | 646 | */ |
---|
616 | 647 | if (list_empty(&dev->maplist) || !map) { |
---|
.. | .. |
---|
631 | 662 | return ret; |
---|
632 | 663 | } |
---|
633 | 664 | |
---|
634 | | -/** |
---|
| 665 | +/* |
---|
635 | 666 | * Cleanup after an error on one of the addbufs() functions. |
---|
636 | 667 | * |
---|
637 | 668 | * \param dev DRM device. |
---|
.. | .. |
---|
666 | 697 | } |
---|
667 | 698 | |
---|
668 | 699 | #if IS_ENABLED(CONFIG_AGP) |
---|
669 | | -/** |
---|
| 700 | +/* |
---|
670 | 701 | * Add AGP buffers for DMA transfers. |
---|
671 | 702 | * |
---|
672 | 703 | * \param dev struct drm_device to which the buffers are to be added. |
---|
.. | .. |
---|
862 | 893 | struct drm_buf **temp_buflist; |
---|
863 | 894 | |
---|
864 | 895 | if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) |
---|
865 | | - return -EINVAL; |
---|
| 896 | + return -EOPNOTSUPP; |
---|
866 | 897 | |
---|
867 | 898 | if (!dma) |
---|
868 | 899 | return -EINVAL; |
---|
.. | .. |
---|
1066 | 1097 | struct drm_buf **temp_buflist; |
---|
1067 | 1098 | |
---|
1068 | 1099 | if (!drm_core_check_feature(dev, DRIVER_SG)) |
---|
1069 | | - return -EINVAL; |
---|
| 1100 | + return -EOPNOTSUPP; |
---|
1070 | 1101 | |
---|
1071 | 1102 | if (!dma) |
---|
1072 | 1103 | return -EINVAL; |
---|
.. | .. |
---|
1202 | 1233 | return 0; |
---|
1203 | 1234 | } |
---|
1204 | 1235 | |
---|
1205 | | -/** |
---|
| 1236 | +/* |
---|
1206 | 1237 | * Add buffers for DMA transfers (ioctl). |
---|
1207 | 1238 | * |
---|
1208 | 1239 | * \param inode device inode. |
---|
.. | .. |
---|
1223 | 1254 | int ret; |
---|
1224 | 1255 | |
---|
1225 | 1256 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1226 | | - return -EINVAL; |
---|
| 1257 | + return -EOPNOTSUPP; |
---|
1227 | 1258 | |
---|
1228 | 1259 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
---|
1229 | | - return -EINVAL; |
---|
| 1260 | + return -EOPNOTSUPP; |
---|
1230 | 1261 | |
---|
1231 | 1262 | #if IS_ENABLED(CONFIG_AGP) |
---|
1232 | 1263 | if (request->flags & _DRM_AGP_BUFFER) |
---|
.. | .. |
---|
1243 | 1274 | return ret; |
---|
1244 | 1275 | } |
---|
1245 | 1276 | |
---|
1246 | | -/** |
---|
| 1277 | +/* |
---|
1247 | 1278 | * Get information about the buffer mappings. |
---|
1248 | 1279 | * |
---|
1249 | 1280 | * This was originally mean for debugging purposes, or by a sophisticated |
---|
.. | .. |
---|
1269 | 1300 | int count; |
---|
1270 | 1301 | |
---|
1271 | 1302 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1272 | | - return -EINVAL; |
---|
| 1303 | + return -EOPNOTSUPP; |
---|
1273 | 1304 | |
---|
1274 | 1305 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
---|
1275 | | - return -EINVAL; |
---|
| 1306 | + return -EOPNOTSUPP; |
---|
1276 | 1307 | |
---|
1277 | 1308 | if (!dma) |
---|
1278 | 1309 | return -EINVAL; |
---|
.. | .. |
---|
1295 | 1326 | if (*p >= count) { |
---|
1296 | 1327 | for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { |
---|
1297 | 1328 | struct drm_buf_entry *from = &dma->bufs[i]; |
---|
| 1329 | + |
---|
1298 | 1330 | if (from->buf_count) { |
---|
1299 | 1331 | if (f(data, count, from) < 0) |
---|
1300 | 1332 | return -EFAULT; |
---|
.. | .. |
---|
1331 | 1363 | struct drm_file *file_priv) |
---|
1332 | 1364 | { |
---|
1333 | 1365 | struct drm_buf_info *request = data; |
---|
| 1366 | + |
---|
1334 | 1367 | return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf); |
---|
1335 | 1368 | } |
---|
1336 | 1369 | |
---|
1337 | | -/** |
---|
| 1370 | +/* |
---|
1338 | 1371 | * Specifies a low and high water mark for buffer allocation |
---|
1339 | 1372 | * |
---|
1340 | 1373 | * \param inode device inode. |
---|
.. | .. |
---|
1357 | 1390 | struct drm_buf_entry *entry; |
---|
1358 | 1391 | |
---|
1359 | 1392 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1360 | | - return -EINVAL; |
---|
| 1393 | + return -EOPNOTSUPP; |
---|
1361 | 1394 | |
---|
1362 | 1395 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
---|
1363 | | - return -EINVAL; |
---|
| 1396 | + return -EOPNOTSUPP; |
---|
1364 | 1397 | |
---|
1365 | 1398 | if (!dma) |
---|
1366 | 1399 | return -EINVAL; |
---|
.. | .. |
---|
1383 | 1416 | return 0; |
---|
1384 | 1417 | } |
---|
1385 | 1418 | |
---|
1386 | | -/** |
---|
| 1419 | +/* |
---|
1387 | 1420 | * Unreserve the buffers in list, previously reserved using drmDMA. |
---|
1388 | 1421 | * |
---|
1389 | 1422 | * \param inode device inode. |
---|
.. | .. |
---|
1405 | 1438 | struct drm_buf *buf; |
---|
1406 | 1439 | |
---|
1407 | 1440 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1408 | | - return -EINVAL; |
---|
| 1441 | + return -EOPNOTSUPP; |
---|
1409 | 1442 | |
---|
1410 | 1443 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
---|
1411 | | - return -EINVAL; |
---|
| 1444 | + return -EOPNOTSUPP; |
---|
1412 | 1445 | |
---|
1413 | 1446 | if (!dma) |
---|
1414 | 1447 | return -EINVAL; |
---|
.. | .. |
---|
1435 | 1468 | return 0; |
---|
1436 | 1469 | } |
---|
1437 | 1470 | |
---|
1438 | | -/** |
---|
| 1471 | +/* |
---|
1439 | 1472 | * Maps all of the DMA buffers into client-virtual space (ioctl). |
---|
1440 | 1473 | * |
---|
1441 | 1474 | * \param inode device inode. |
---|
.. | .. |
---|
1461 | 1494 | int i; |
---|
1462 | 1495 | |
---|
1463 | 1496 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1464 | | - return -EINVAL; |
---|
| 1497 | + return -EOPNOTSUPP; |
---|
1465 | 1498 | |
---|
1466 | 1499 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
---|
1467 | | - return -EINVAL; |
---|
| 1500 | + return -EOPNOTSUPP; |
---|
1468 | 1501 | |
---|
1469 | 1502 | if (!dma) |
---|
1470 | 1503 | return -EINVAL; |
---|
.. | .. |
---|
1542 | 1575 | struct drm_file *file_priv) |
---|
1543 | 1576 | { |
---|
1544 | 1577 | struct drm_buf_map *request = data; |
---|
| 1578 | + |
---|
1545 | 1579 | return __drm_legacy_mapbufs(dev, data, &request->count, |
---|
1546 | 1580 | &request->virtual, map_one_buf, |
---|
1547 | 1581 | file_priv); |
---|
.. | .. |
---|
1551 | 1585 | struct drm_file *file_priv) |
---|
1552 | 1586 | { |
---|
1553 | 1587 | if (!drm_core_check_feature(dev, DRIVER_LEGACY)) |
---|
1554 | | - return -EINVAL; |
---|
| 1588 | + return -EOPNOTSUPP; |
---|
1555 | 1589 | |
---|
1556 | 1590 | if (dev->driver->dma_ioctl) |
---|
1557 | 1591 | return dev->driver->dma_ioctl(dev, data, file_priv); |
---|