Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm/gem: Add metadata

The EXT_external_objects extension is a bit awkward as it doesn't pass
explicit modifiers, leaving the importer to guess with incomplete
information. In the case of vk (turnip) exporting and gl (freedreno)
importing, the "OPTIMAL_TILING_EXT" layout depends on VkImageCreateInfo
flags (among other things), which the importer does not know. Which
unfortunately leaves us with the need for a metadata back-channel.

The contents of the metadata are defined by userspace. The
EXT_external_objects extension is only required to work between
compatible versions of gl and vk drivers, as defined by device and
driver UUIDs.

v2: add missing metadata kfree
v3: Rework to move copy_from/to_user out from under gem obj lock
to avoid angering lockdep about deadlocks against fs-reclaim

Signed-off-by: Rob Clark <robdclark@chromium.org>
Patchwork: https://patchwork.freedesktop.org/patch/566157/

+98 -1
+91 -1
drivers/gpu/drm/msm/msm_drv.c
··· 37 37 * - 1.9.0 - Add MSM_SUBMIT_FENCE_SN_IN 38 38 * - 1.10.0 - Add MSM_SUBMIT_BO_NO_IMPLICIT 39 39 * - 1.11.0 - Add wait boost (MSM_WAIT_FENCE_BOOST, MSM_PREP_BOOST) 40 + * - 1.12.0 - Add MSM_INFO_SET_METADATA and MSM_INFO_GET_METADATA 40 41 */ 41 42 #define MSM_VERSION_MAJOR 1 42 - #define MSM_VERSION_MINOR 11 43 + #define MSM_VERSION_MINOR 12 43 44 #define MSM_VERSION_PATCHLEVEL 0 44 45 45 46 static void msm_deinit_vram(struct drm_device *ddev); ··· 547 546 return msm_gem_set_iova(obj, ctx->aspace, iova); 548 547 } 549 548 549 + static int msm_ioctl_gem_info_set_metadata(struct drm_gem_object *obj, 550 + __user void *metadata, 551 + u32 metadata_size) 552 + { 553 + struct msm_gem_object *msm_obj = to_msm_bo(obj); 554 + void *buf; 555 + int ret; 556 + 557 + /* Impose a moderate upper bound on metadata size: */ 558 + if (metadata_size > 128) { 559 + return -EOVERFLOW; 560 + } 561 + 562 + /* Use a temporary buf to keep copy_from_user() outside of gem obj lock: */ 563 + buf = memdup_user(metadata, metadata_size); 564 + if (IS_ERR(buf)) 565 + return PTR_ERR(buf); 566 + 567 + ret = msm_gem_lock_interruptible(obj); 568 + if (ret) 569 + goto out; 570 + 571 + msm_obj->metadata = 572 + krealloc(msm_obj->metadata, metadata_size, GFP_KERNEL); 573 + msm_obj->metadata_size = metadata_size; 574 + memcpy(msm_obj->metadata, buf, metadata_size); 575 + 576 + msm_gem_unlock(obj); 577 + 578 + out: 579 + kfree(buf); 580 + 581 + return ret; 582 + } 583 + 584 + static int msm_ioctl_gem_info_get_metadata(struct drm_gem_object *obj, 585 + __user void *metadata, 586 + u32 *metadata_size) 587 + { 588 + struct msm_gem_object *msm_obj = to_msm_bo(obj); 589 + void *buf; 590 + int ret, len; 591 + 592 + if (!metadata) { 593 + /* 594 + * Querying the size is inherently racey, but 595 + * EXT_external_objects expects the app to confirm 596 + * via device and driver UUIDs that the exporter and 597 + * importer versions match. All we can do from the 598 + * kernel side is check the length under obj lock 599 + * when userspace tries to retrieve the metadata 600 + */ 601 + *metadata_size = msm_obj->metadata_size; 602 + return 0; 603 + } 604 + 605 + ret = msm_gem_lock_interruptible(obj); 606 + if (ret) 607 + return ret; 608 + 609 + /* Avoid copy_to_user() under gem obj lock: */ 610 + len = msm_obj->metadata_size; 611 + buf = kmemdup(msm_obj->metadata, len, GFP_KERNEL); 612 + 613 + msm_gem_unlock(obj); 614 + 615 + if (*metadata_size < len) { 616 + ret = -ETOOSMALL; 617 + } else if (copy_to_user(metadata, buf, len)) { 618 + ret = -EFAULT; 619 + } else { 620 + *metadata_size = len; 621 + } 622 + 623 + kfree(buf); 624 + 625 + return 0; 626 + } 627 + 550 628 static int msm_ioctl_gem_info(struct drm_device *dev, void *data, 551 629 struct drm_file *file) 552 630 { ··· 648 568 break; 649 569 case MSM_INFO_SET_NAME: 650 570 case MSM_INFO_GET_NAME: 571 + case MSM_INFO_SET_METADATA: 572 + case MSM_INFO_GET_METADATA: 651 573 break; 652 574 default: 653 575 return -EINVAL; ··· 711 629 msm_obj->name, args->len)) 712 630 ret = -EFAULT; 713 631 } 632 + break; 633 + case MSM_INFO_SET_METADATA: 634 + ret = msm_ioctl_gem_info_set_metadata( 635 + obj, u64_to_user_ptr(args->value), args->len); 636 + break; 637 + case MSM_INFO_GET_METADATA: 638 + ret = msm_ioctl_gem_info_get_metadata( 639 + obj, u64_to_user_ptr(args->value), &args->len); 714 640 break; 715 641 } 716 642
+1
drivers/gpu/drm/msm/msm_gem.c
··· 1058 1058 1059 1059 drm_gem_object_release(obj); 1060 1060 1061 + kfree(msm_obj->metadata); 1061 1062 kfree(msm_obj); 1062 1063 } 1063 1064
+4
drivers/gpu/drm/msm/msm_gem.h
··· 108 108 109 109 char name[32]; /* Identifier to print for the debugfs files */ 110 110 111 + /* userspace metadata backchannel */ 112 + void *metadata; 113 + u32 metadata_size; 114 + 111 115 /** 112 116 * pin_count: Number of times the pages are pinned 113 117 *
+2
include/uapi/drm/msm_drm.h
··· 139 139 #define MSM_INFO_GET_NAME 0x03 /* get debug name, returned by pointer */ 140 140 #define MSM_INFO_SET_IOVA 0x04 /* set the iova, passed by value */ 141 141 #define MSM_INFO_GET_FLAGS 0x05 /* get the MSM_BO_x flags */ 142 + #define MSM_INFO_SET_METADATA 0x06 /* set userspace metadata */ 143 + #define MSM_INFO_GET_METADATA 0x07 /* get userspace metadata */ 142 144 143 145 struct drm_msm_gem_info { 144 146 __u32 handle; /* in */