diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 11:26:46 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 11:26:46 -0700 |
| commit | 477f70cd2a67904e04c2c2b9bd0fa2e95222f2f6 (patch) | |
| tree | 1897dd1de49e1ea24897163533e2d8ead5dad0ad /drivers/gpu/drm/drm_lease.c | |
| parent | 835d31d319d9c8c4eb6cac074643360ba0ecab10 (diff) | |
| parent | 8f0284f190e6a0aa09015090568c03f18288231a (diff) | |
Merge tag 'drm-next-2021-08-31-1' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"Highlights:
- i915 has seen a lot of refactoring and uAPI cleanups due to a
change in the upstream direction going forward
This has all been audited with known userspace, but there may be
some pitfalls that were missed.
- i915 now uses common TTM to enable discrete memory on DG1/2 GPUs
- i915 enables Jasper and Elkhart Lake by default and has preliminary
XeHP/DG2 support
- amdgpu adds support for Cyan Skillfish
- lots of implicit fencing rules documented and fixed up in drivers
- msm now uses the core scheduler
- the irq midlayer has been removed for non-legacy drivers
- the sysfb code now works on more than x86.
Otherwise the usual smattering of stuff everywhere, panels, bridges,
refactorings.
Detailed summary:
core:
- extract i915 eDP backlight into core
- DP aux bus support
- drm_device.irq_enabled removed
- port drivers to native irq interfaces
- export gem shadow plane handling for vgem
- print proper driver name in framebuffer registration
- driver fixes for implicit fencing rules
- ARM fixed rate compression modifier added
- updated fb damage handling
- rmfb ioctl logging/docs
- drop drm_gem_object_put_locked
- define DRM_FORMAT_MAX_PLANES
- add gem fb vmap/vunmap helpers
- add lockdep_assert(once) helpers
- mark drm irq midlayer as legacy
- use offset adjusted bo mapping conversion
vgaarb:
- cleanups
fbdev:
- extend efifb handling to all arches
- div by 0 fixes for multiple drivers
udmabuf:
- add hugepage mapping support
dma-buf:
- non-dynamic exporter fixups
- document implicit fencing rules
amdgpu:
- Initial Cyan Skillfish support
- switch virtual DCE over to vkms based atomic
- VCN/JPEG power down fixes
- NAVI PCIE link handling fixes
- AMD HDMI freesync fixes
- Yellow Carp + Beige Goby fixes
- Clockgating/S0ix/SMU/EEPROM fixes
- embed hw fence in job
- rework dma-resv handling
- ensure eviction to system ram
amdkfd:
- uapi: SVM address range query added
- sysfs leak fix
- GPUVM TLB optimizations
- vmfault/migration counters
i915:
- Enable JSL and EHL by default
- preliminary XeHP/DG2 support
- remove all CNL support (never shipped)
- move to TTM for discrete memory support
- allow mixed object mmap handling
- GEM uAPI spring cleaning
- add I915_MMAP_OBJECT_FIXED
- reinstate ADL-P mmap ioctls
- drop a bunch of unused by userspace features
- disable and remove GPU relocations
- revert some i915 misfeatures
- major refactoring of GuC for Gen11+
- execbuffer object locking separate step
- reject caching/set-domain on discrete
- Enable pipe DMC loading on XE-LPD and ADL-P
- add PSF GV point support
- Refactor and fix DDI buffer translations
- Clean up FBC CFB allocation code
- Finish INTEL_GEN() and friends macro conversions
nouveau:
- add eDP backlight support
- implicit fence fix
msm:
- a680/7c3 support
- drm/scheduler conversion
panfrost:
- rework GPU reset
virtio:
- fix fencing for planes
ast:
- add detect support
bochs:
- move to tiny GPU driver
vc4:
- use hotplug irqs
- HDMI codec support
vmwgfx:
- use internal vmware device headers
ingenic:
- demidlayering irq
rcar-du:
- shutdown fixes
- convert to bridge connector helpers
zynqmp-dsub:
- misc fixes
mgag200:
- convert PLL handling to atomic
mediatek:
- MT8133 AAL support
- gem mmap object support
- MT8167 support
etnaviv:
- NXP Layerscape LS1028A SoC support
- GEM mmap cleanups
tegra:
- new user API
exynos:
- missing unlock fix
- build warning fix
- use refcount_t"
* tag 'drm-next-2021-08-31-1' of git://anongit.freedesktop.org/drm/drm: (1318 commits)
drm/amd/display: Move AllowDRAMSelfRefreshOrDRAMClockChangeInVblank to bounding box
drm/amd/display: Remove duplicate dml init
drm/amd/display: Update bounding box states (v2)
drm/amd/display: Update number of DCN3 clock states
drm/amdgpu: disable GFX CGCG in aldebaran
drm/amdgpu: Clear RAS interrupt status on aldebaran
drm/amdgpu: Add support for RAS XGMI err query
drm/amdkfd: Account for SH/SE count when setting up cu masks.
drm/amdgpu: rename amdgpu_bo_get_preferred_pin_domain
drm/amdgpu: drop redundant cancel_delayed_work_sync call
drm/amdgpu: add missing cleanups for more ASICs on UVD/VCE suspend
drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend
drm/amdkfd: map SVM range with correct access permission
drm/amdkfd: check access permisson to restore retry fault
drm/amdgpu: Update RAS XGMI Error Query
drm/amdgpu: Add driver infrastructure for MCA RAS
drm/amd/display: Add Logging for HDMI color depth information
drm/amd/amdgpu: consolidate PSP TA init shared buf functions
drm/amd/amdgpu: add name field back to ras_common_if
drm/amdgpu: Fix build with missing pm_suspend_target_state module export
...
Diffstat (limited to 'drivers/gpu/drm/drm_lease.c')
| -rw-r--r-- | drivers/gpu/drm/drm_lease.c | 263 |
1 files changed, 120 insertions, 143 deletions
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 00fb433bcef1..dee4f24a1808 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -15,19 +15,62 @@ #include "drm_crtc_internal.h" #include "drm_internal.h" +/** + * DOC: drm leasing + * + * DRM leases provide information about whether a DRM master may control a DRM + * mode setting object. This enables the creation of multiple DRM masters that + * manage subsets of display resources. + * + * The original DRM master of a device 'owns' the available drm resources. It + * may create additional DRM masters and 'lease' resources which it controls + * to the new DRM master. This gives the new DRM master control over the + * leased resources until the owner revokes the lease, or the new DRM master + * is closed. Some helpful terminology: + * + * - An 'owner' is a &struct drm_master that is not leasing objects from + * another &struct drm_master, and hence 'owns' the objects. The owner can be + * identified as the &struct drm_master for which &drm_master.lessor is NULL. + * + * - A 'lessor' is a &struct drm_master which is leasing objects to one or more + * other &struct drm_master. Currently, lessees are not allowed to + * create sub-leases, hence the lessor is the same as the owner. + * + * - A 'lessee' is a &struct drm_master which is leasing objects from some + * other &struct drm_master. Each lessee only leases resources from a single + * lessor recorded in &drm_master.lessor, and holds the set of objects that + * it is leasing in &drm_master.leases. + * + * - A 'lease' is a contract between the lessor and lessee that identifies + * which resources may be controlled by the lessee. All of the resources + * that are leased must be owned by or leased to the lessor, and lessors are + * not permitted to lease the same object to multiple lessees. + * + * The set of objects any &struct drm_master 'controls' is limited to the set + * of objects it leases (for lessees) or all objects (for owners). + * + * Objects not controlled by a &struct drm_master cannot be modified through + * the various state manipulating ioctls, and any state reported back to user + * space will be edited to make them appear idle and/or unusable. For + * instance, connectors always report 'disconnected', while encoders + * report no possible crtcs or clones. + * + * Since each lessee may lease objects from a single lessor, display resource + * leases form a tree of &struct drm_master. As lessees are currently not + * allowed to create sub-leases, the tree depth is limited to 1. All of + * these get activated simultaneously when the top level device owner changes + * through the SETMASTER or DROPMASTER IOCTL, so &drm_device.master points to + * the owner at the top of the lease tree (i.e. the &struct drm_master for which + * &drm_master.lessor is NULL). The full list of lessees that are leasing + * objects from the owner can be searched via the owner's + * &drm_master.lessee_idr. + */ + #define drm_for_each_lessee(lessee, lessor) \ list_for_each_entry((lessee), &(lessor)->lessees, lessee_list) static uint64_t drm_lease_idr_object; -/** - * drm_lease_owner - return ancestor owner drm_master - * @master: drm_master somewhere within tree of lessees and lessors - * - * RETURN: - * - * drm_master at the top of the tree (i.e, with lessor NULL - */ struct drm_master *drm_lease_owner(struct drm_master *master) { while (master->lessor != NULL) @@ -35,16 +78,6 @@ struct drm_master *drm_lease_owner(struct drm_master *master) return master; } -/** - * _drm_find_lessee - find lessee by id (idr_mutex held) - * @master: drm_master of lessor - * @lessee_id: id - * - * RETURN: - * - * drm_master of the lessee if valid, NULL otherwise - */ - static struct drm_master* _drm_find_lessee(struct drm_master *master, int lessee_id) { @@ -52,17 +85,6 @@ _drm_find_lessee(struct drm_master *master, int lessee_id) return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id); } -/** - * _drm_lease_held_master - check to see if an object is leased (or owned) by master (idr_mutex held) - * @master: the master to check the lease status of - * @id: the id to check - * - * Checks if the specified master holds a lease on the object. Return - * value: - * - * true 'master' holds a lease on (or owns) the object - * false 'master' does not hold a lease. - */ static int _drm_lease_held_master(struct drm_master *master, int id) { lockdep_assert_held(&master->dev->mode_config.idr_mutex); @@ -71,17 +93,7 @@ static int _drm_lease_held_master(struct drm_master *master, int id) return true; } -/** - * _drm_has_leased - check to see if an object has been leased (idr_mutex held) - * @master: the master to check the lease status of - * @id: the id to check - * - * Checks if any lessee of 'master' holds a lease on 'id'. Return - * value: - * - * true Some lessee holds a lease on the object. - * false No lessee has a lease on the object. - */ +/* Checks if the given object has been leased to some lessee of drm_master */ static bool _drm_has_leased(struct drm_master *master, int id) { struct drm_master *lessee; @@ -93,58 +105,51 @@ static bool _drm_has_leased(struct drm_master *master, int id) return false; } -/** - * _drm_lease_held - check drm_mode_object lease status (idr_mutex held) - * @file_priv: the master drm_file - * @id: the object id - * - * Checks if the specified master holds a lease on the object. Return - * value: - * - * true 'master' holds a lease on (or owns) the object - * false 'master' does not hold a lease. - */ +/* Called with idr_mutex held */ bool _drm_lease_held(struct drm_file *file_priv, int id) { - if (!file_priv || !file_priv->master) + bool ret; + struct drm_master *master; + + if (!file_priv) + return true; + + master = drm_file_get_master(file_priv); + if (!master) return true; + ret = _drm_lease_held_master(master, id); + drm_master_put(&master); - return _drm_lease_held_master(file_priv->master, id); + return ret; } -/** - * drm_lease_held - check drm_mode_object lease status (idr_mutex not held) - * @file_priv: the master drm_file - * @id: the object id - * - * Checks if the specified master holds a lease on the object. Return - * value: - * - * true 'master' holds a lease on (or owns) the object - * false 'master' does not hold a lease. - */ bool drm_lease_held(struct drm_file *file_priv, int id) { struct drm_master *master; bool ret; - if (!file_priv || !file_priv->master || !file_priv->master->lessor) + if (!file_priv) return true; - master = file_priv->master; + master = drm_file_get_master(file_priv); + if (!master) + return true; + if (!master->lessor) { + ret = true; + goto out; + } mutex_lock(&master->dev->mode_config.idr_mutex); ret = _drm_lease_held_master(master, id); mutex_unlock(&master->dev->mode_config.idr_mutex); + +out: + drm_master_put(&master); return ret; } -/** - * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held) - * @file_priv: requestor file - * @crtcs_in: bitmask of crtcs to check - * - * Reconstructs a crtc mask based on the crtcs which are visible - * through the specified file. +/* + * Given a bitmask of crtcs to check, reconstructs a crtc mask based on the + * crtcs which are visible through the specified file. */ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in) { @@ -154,10 +159,16 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in) int count_in, count_out; uint32_t crtcs_out = 0; - if (!file_priv || !file_priv->master || !file_priv->master->lessor) + if (!file_priv) return crtcs_in; - master = file_priv->master; + master = drm_file_get_master(file_priv); + if (!master) + return crtcs_in; + if (!master->lessor) { + crtcs_out = crtcs_in; + goto out; + } dev = master->dev; count_in = count_out = 0; @@ -176,14 +187,13 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in) count_in++; } mutex_unlock(&master->dev->mode_config.idr_mutex); + +out: + drm_master_put(&master); return crtcs_out; } /* - * drm_lease_create - create a new drm_master with leased objects (idr_mutex not held) - * @lessor: lease holder (or owner) of objects - * @leases: objects to lease to the new drm_master - * * Uses drm_master_create to allocate a new drm_master, then checks to * make sure all of the desired objects can be leased, atomically * leasing them to the new drmmaster. @@ -252,15 +262,6 @@ out_lessee: return ERR_PTR(error); } -/** - * drm_lease_destroy - a master is going away (idr_mutex not held) - * @master: the drm_master being destroyed - * - * All lessees will have been destroyed as they - * hold a reference on their lessor. Notify any - * lessor for this master so that it can check - * the list of lessees. - */ void drm_lease_destroy(struct drm_master *master) { struct drm_device *dev = master->dev; @@ -294,10 +295,6 @@ void drm_lease_destroy(struct drm_master *master) DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id); } -/** - * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held) - * @top: the master losing its lease - */ static void _drm_lease_revoke(struct drm_master *top) { int object; @@ -336,10 +333,6 @@ static void _drm_lease_revoke(struct drm_master *top) } } -/** - * drm_lease_revoke - revoke access to all leased objects (idr_mutex not held) - * @top: the master losing its lease - */ void drm_lease_revoke(struct drm_master *top) { mutex_lock(&top->dev->mode_config.idr_mutex); @@ -471,12 +464,7 @@ out_free_objects: return ret; } -/** - * drm_mode_create_lease_ioctl - create a new lease - * @dev: the drm device - * @data: pointer to struct drm_mode_create_lease - * @lessor_priv: the file being manipulated - * +/* * The master associated with the specified file will have a lease * created containing the objects specified in the ioctl structure. * A file descriptor will be allocated for that and returned to the @@ -489,7 +477,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, size_t object_count; int ret = 0; struct idr leases; - struct drm_master *lessor = lessor_priv->master; + struct drm_master *lessor; struct drm_master *lessee = NULL; struct file *lessee_file = NULL; struct file *lessor_file = lessor_priv->filp; @@ -501,12 +489,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP; - /* Do not allow sub-leases */ - if (lessor->lessor) { - DRM_DEBUG_LEASE("recursive leasing not allowed\n"); - return -EINVAL; - } - /* need some objects */ if (cl->object_count == 0) { DRM_DEBUG_LEASE("no objects in lease\n"); @@ -518,12 +500,22 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, return -EINVAL; } + lessor = drm_file_get_master(lessor_priv); + /* Do not allow sub-leases */ + if (lessor->lessor) { + DRM_DEBUG_LEASE("recursive leasing not allowed\n"); + ret = -EINVAL; + goto out_lessor; + } + object_count = cl->object_count; object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), array_size(object_count, sizeof(__u32))); - if (IS_ERR(object_ids)) - return PTR_ERR(object_ids); + if (IS_ERR(object_ids)) { + ret = PTR_ERR(object_ids); + goto out_lessor; + } idr_init(&leases); @@ -534,14 +526,15 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, if (ret) { DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret); idr_destroy(&leases); - return ret; + goto out_lessor; } /* Allocate a file descriptor for the lease */ fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK)); if (fd < 0) { idr_destroy(&leases); - return fd; + ret = fd; + goto out_lessor; } DRM_DEBUG_LEASE("Creating lease\n"); @@ -577,6 +570,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, /* Hook up the fd */ fd_install(fd, lessee_file); + drm_master_put(&lessor); DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); return 0; @@ -586,29 +580,19 @@ out_lessee: out_leases: put_unused_fd(fd); +out_lessor: + drm_master_put(&lessor); DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret); return ret; } -/** - * drm_mode_list_lessees_ioctl - list lessee ids - * @dev: the drm device - * @data: pointer to struct drm_mode_list_lessees - * @lessor_priv: the file being manipulated - * - * Starting from the master associated with the specified file, - * the master with the provided lessee_id is found, and then - * an array of lessee ids associated with leases from that master - * are returned. - */ - int drm_mode_list_lessees_ioctl(struct drm_device *dev, void *data, struct drm_file *lessor_priv) { struct drm_mode_list_lessees *arg = data; __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr); __u32 count_lessees = arg->count_lessees; - struct drm_master *lessor = lessor_priv->master, *lessee; + struct drm_master *lessor, *lessee; int count; int ret = 0; @@ -619,6 +603,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP; + lessor = drm_file_get_master(lessor_priv); DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id); mutex_lock(&dev->mode_config.idr_mutex); @@ -642,26 +627,19 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev, arg->count_lessees = count; mutex_unlock(&dev->mode_config.idr_mutex); + drm_master_put(&lessor); return ret; } -/** - * drm_mode_get_lease_ioctl - list leased objects - * @dev: the drm device - * @data: pointer to struct drm_mode_get_lease - * @lessee_priv: the file being manipulated - * - * Return the list of leased objects for the specified lessee - */ - +/* Return the list of leased objects for the specified lessee */ int drm_mode_get_lease_ioctl(struct drm_device *dev, void *data, struct drm_file *lessee_priv) { struct drm_mode_get_lease *arg = data; __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr); __u32 count_objects = arg->count_objects; - struct drm_master *lessee = lessee_priv->master; + struct drm_master *lessee; struct idr *object_idr; int count; void *entry; @@ -675,6 +653,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP; + lessee = drm_file_get_master(lessee_priv); DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id); mutex_lock(&dev->mode_config.idr_mutex); @@ -702,16 +681,12 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev, arg->count_objects = count; mutex_unlock(&dev->mode_config.idr_mutex); + drm_master_put(&lessee); return ret; } -/** - * drm_mode_revoke_lease_ioctl - revoke lease - * @dev: the drm device - * @data: pointer to struct drm_mode_revoke_lease - * @lessor_priv: the file being manipulated - * +/* * This removes all of the objects from the lease without * actually getting rid of the lease itself; that way all * references to it still work correctly @@ -720,7 +695,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev, void *data, struct drm_file *lessor_priv) { struct drm_mode_revoke_lease *arg = data; - struct drm_master *lessor = lessor_priv->master; + struct drm_master *lessor; struct drm_master *lessee; int ret = 0; @@ -730,6 +705,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP; + lessor = drm_file_get_master(lessor_priv); mutex_lock(&dev->mode_config.idr_mutex); lessee = _drm_find_lessee(lessor, arg->lessee_id); @@ -750,6 +726,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev, fail: mutex_unlock(&dev->mode_config.idr_mutex); + drm_master_put(&lessor); return ret; } |
