![]() |
|
|||
0001 /* 0002 * Copyright 2014 Advanced Micro Devices, Inc. 0003 * All Rights Reserved. 0004 * 0005 * Permission is hereby granted, free of charge, to any person obtaining a 0006 * copy of this software and associated documentation files (the 0007 * "Software"), to deal in the Software without restriction, including 0008 * without limitation the rights to use, copy, modify, merge, publish, 0009 * distribute, sub license, and/or sell copies of the Software, and to 0010 * permit persons to whom the Software is furnished to do so, subject to 0011 * the following conditions: 0012 * 0013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0014 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0015 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 0016 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 0017 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 0018 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 0019 * USE OR OTHER DEALINGS IN THE SOFTWARE. 0020 * 0021 * The above copyright notice and this permission notice (including the 0022 * next paragraph) shall be included in all copies or substantial portions 0023 * of the Software. 0024 * 0025 */ 0026 /* 0027 * Authors: 0028 * Christian König <christian.koenig@amd.com> 0029 */ 0030 0031 #include <linux/firmware.h> 0032 #include <linux/module.h> 0033 #include <linux/mmu_notifier.h> 0034 0035 #include <drm/drm.h> 0036 0037 #include "radeon.h" 0038 0039 /** 0040 * radeon_mn_invalidate - callback to notify about mm change 0041 * 0042 * @mn: our notifier 0043 * @range: the VMA under invalidation 0044 * @cur_seq: Value to pass to mmu_interval_set_seq() 0045 * 0046 * We block for all BOs between start and end to be idle and 0047 * unmap them by move them into system domain again. 0048 */ 0049 static bool radeon_mn_invalidate(struct mmu_interval_notifier *mn, 0050 const struct mmu_notifier_range *range, 0051 unsigned long cur_seq) 0052 { 0053 struct radeon_bo *bo = container_of(mn, struct radeon_bo, notifier); 0054 struct ttm_operation_ctx ctx = { false, false }; 0055 long r; 0056 0057 if (!bo->tbo.ttm || !radeon_ttm_tt_is_bound(bo->tbo.bdev, bo->tbo.ttm)) 0058 return true; 0059 0060 if (!mmu_notifier_range_blockable(range)) 0061 return false; 0062 0063 r = radeon_bo_reserve(bo, true); 0064 if (r) { 0065 DRM_ERROR("(%ld) failed to reserve user bo\n", r); 0066 return true; 0067 } 0068 0069 r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP, 0070 false, MAX_SCHEDULE_TIMEOUT); 0071 if (r <= 0) 0072 DRM_ERROR("(%ld) failed to wait for user bo\n", r); 0073 0074 radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_CPU); 0075 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); 0076 if (r) 0077 DRM_ERROR("(%ld) failed to validate user bo\n", r); 0078 0079 radeon_bo_unreserve(bo); 0080 return true; 0081 } 0082 0083 static const struct mmu_interval_notifier_ops radeon_mn_ops = { 0084 .invalidate = radeon_mn_invalidate, 0085 }; 0086 0087 /** 0088 * radeon_mn_register - register a BO for notifier updates 0089 * 0090 * @bo: radeon buffer object 0091 * @addr: userptr addr we should monitor 0092 * 0093 * Registers an MMU notifier for the given BO at the specified address. 0094 * Returns 0 on success, -ERRNO if anything goes wrong. 0095 */ 0096 int radeon_mn_register(struct radeon_bo *bo, unsigned long addr) 0097 { 0098 int ret; 0099 0100 ret = mmu_interval_notifier_insert(&bo->notifier, current->mm, addr, 0101 radeon_bo_size(bo), &radeon_mn_ops); 0102 if (ret) 0103 return ret; 0104 0105 /* 0106 * FIXME: radeon appears to allow get_user_pages to run during 0107 * invalidate_range_start/end, which is not a safe way to read the 0108 * PTEs. It should use the mmu_interval_read_begin() scheme around the 0109 * get_user_pages to ensure that the PTEs are read properly 0110 */ 0111 mmu_interval_read_begin(&bo->notifier); 0112 return 0; 0113 } 0114 0115 /** 0116 * radeon_mn_unregister - unregister a BO for notifier updates 0117 * 0118 * @bo: radeon buffer object 0119 * 0120 * Remove any registration of MMU notifier updates from the buffer object. 0121 */ 0122 void radeon_mn_unregister(struct radeon_bo *bo) 0123 { 0124 if (!bo->notifier.mm) 0125 return; 0126 mmu_interval_notifier_remove(&bo->notifier); 0127 bo->notifier.mm = NULL; 0128 }
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |