- 30 7月, 2018 2 次提交
-
-
由 Jordan Crouse 提交于
Convert the existing GPU show function to use the GPU state to dump the information rather than reading it directly from the hardware. This will require an additional step to capture the state before dumping it for the existing nodes but it will greatly facilitate reusing the same code for dumping a previously captured state from a GPU hang. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Add the infrastructure to capture the current state of the GPU and store it in memory so that it can be dumped later. For now grab the same basic ringbuffer information and registers that are provided by the debugfs 'gpu' node but obviously this should be extended to capture a much larger set of GPU information. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 25 7月, 2018 2 次提交
-
-
由 Jordan Crouse 提交于
Experimentation shows that resuming power quickly after suspending ends up forcing a system hang for unknown reasons on 5xx targets. To avoid cycling the power too much (especially during init) turn up the autosuspend time for a5xx to 250ms and use pm_runtime_put_autosuspend() when applicable. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Daniel Mack 提交于
When a msm8016 based system is woken up from suspend, the firmware in the adreno device hangs. [ 83.903416] qcom-iommu-ctx 1f09000.iommu-ctx: Unhandled context fault: fsr=0x202, iova=0x0000000000000000, fsynr=0x2, cb=1 [ 85.853633] msm 1a00000.mdss: A306: hangcheck detected gpu lockup rb 0! [ 85.853661] msm 1a00000.mdss: A306: completed fence: 370 [ 85.859073] msm 1a00000.mdss: A306: submitted fence: 372 [ 85.865113] msm 1a00000.mdss: A306: hangcheck recover! Fix this by adding pm_runtime_force_suspend/pm_runtime_force_resume as sleep ops. Signed-off-by: NDaniel Mack <daniel@zonque.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 04 5月, 2018 1 次提交
-
-
由 Daniel Vetter 提交于
It's going away. v2: Try harder to find them all. Reviewed-by: NSean Paul <seanpaul@chromium.org> Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch> Cc: Rob Clark <robdclark@gmail.com> Cc: Jordan Crouse <jcrouse@codeaurora.org> Cc: Nicolas Dechesne <nicolas.dechesne@linaro.org> Cc: Archit Taneja <architt@codeaurora.org> Cc: Bjorn Andersson <bjorn.andersson@linaro.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20180503093107.25955-1-daniel.vetter@ffwll.ch
-
- 19 3月, 2018 3 次提交
-
-
由 Arnd Bergmann 提交于
The adreno driver stopped building when CONFIG_DEBUGFS is disabled: drivers/gpu/drm/msm/adreno/adreno_device.c: In function 'adreno_load_gpu': drivers/gpu/drm/msm/adreno/adreno_device.c:153:16: error: 'const struct msm_gpu_funcs' has no member named 'debugfs_init' if (gpu->funcs->debugfs_init) { ^~ drivers/gpu/drm/msm/adreno/adreno_device.c:154:13: error: 'const struct msm_gpu_funcs' has no member named 'debugfs_init' gpu->funcs->debugfs_init(gpu, dev->primary); ^~ This adds an #ifdef around the code that references the hidden pointer. Fixes: 331dc0bc ("drm/msm: add a5xx specific debugfs") Signed-off-by: NArnd Bergmann <arnd@arndb.de> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Bjorn Andersson 提交于
Interrupt commands causes the CP to trigger an interrupt as the command is processed, regardless of the GPU being done processing previous commands. This is seen by the interrupt being delivered before the fence is written on 8974 and is likely the cause of the additional CP_WAIT_FOR_IDLE workaround found for a306, which would cause the CP to wait for the GPU to go idle before triggering the interrupt. Instead we can set the (undocumented) BIT(31) of the CACHE_FLUSH_TS which will cause a special CACHE_FLUSH_TS interrupt to be triggered from the GPU as the write event is processed. Add CACHE_FLUSH_TS to the IRQ masks of A3xx and A4xx and remove the workaround for A306. Suggested-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NBjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Gustavo A. R. Silva 提交于
_minor_ is being dereferenced before it is null checked, hence there is a potential null pointer dereference. Fix this by moving the pointer dereference after _minor_ has been null checked. Fixes: 024ad8df763f ("drm/msm: add a5xx specific debugfs") Signed-off-by: NGustavo A. R. Silva <garsilva@embeddedor.com> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 20 2月, 2018 6 次提交
-
-
由 Jordan Crouse 提交于
Move a5xx specific code to load firmware into a buffer object to the generic Adreno code. This will come in useful for future targets. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
The number and type of firmware files required differs for each target. Instead of using a fixed struct member for each possible firmware file use a generic list of files that should be loaded on boot. Use some semi-target specific enums to help each target find the appropriate firmware(s) that it needs to load. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
The power management device on the a5xx cores is known as the GPMU (Graphics Power Management Unit). On a6xx cores the device was expanded and renamed as the GMU (Graphics Management Unit). Rename the 'gpmufw' name struct adreno_info as 'powerfw' to avoid confusion. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Steve Kowalik 提交于
drm_gem_object_{reference,unreference,unreference_unlocked} are deprecated functions, and merely alias to the get/put functions. Switch to the new names. Signed-off-by: NSteve Kowalik <steven@wedontsleep.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Rob Clark 提交于
This flags cause cmdstream to be executed from the ringbuffer (RB) instead of IB1. Normally not something you'd ever want to do, but it is super useful for firmware debugging. Hidden behind CAP_SYS_RAWIO and a default=n kconfig option which depends on EXPERT (and has a suitably scary warning), to prevent it from being used on accident. Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Rob Clark 提交于
Add some debugfs to dump out PFP and ME microcontroller state, as well as some of the queues (MEQ and ROQ). Also add a debugfs file to trigger a GPU reset (and reloading the firmware on next submit). Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 13 2月, 2018 1 次提交
-
-
由 Bjorn Andersson 提交于
In order to implement support for grabbing core dumps in remoteproc it's necessary to know the relocated base of the image, as the offsets from the virtual memory base might not be based on the physical address. Return the adjusted physical base address to the caller. Acked-by: NAndy Gross <andy.gross@linaro.org> Signed-off-by: NBjorn Andersson <bjorn.andersson@linaro.org>
-
- 11 1月, 2018 1 次提交
-
-
由 Jordan Crouse 提交于
Add support for devfreq to dynamically control the GPU frequency. By default try to use the 'simple_ondemand' governor which can adjust the frequency based on GPU load. v2: Fix __aeabi_uldivmod issue from the 0 day bot and use devfreq_recommended_opp() as suggested by Rob. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 10 1月, 2018 7 次提交
-
-
由 Jordan Crouse 提交于
Even though the default countable for CP0 is CP_ALWAYS_COUNT (0), program the selector during HW initialization in an effort to be up front about which counters are programmed and why. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Some 5xx based chipsets have different bins for GPU clock speeds. Read the fuses (if applicable) and set the appropriate OPP table. This will only work with OPP v2 tables - the bin will be ignored for legacy pwrlevel tables. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Move the clock parsing to adreno_gpu_init() to allow for target specific probing and manipulation of the clock tables. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
We don't need to convert the chipid to an intermediate value and then back again into a struct adreno_rev. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Remove the downstream bus scaling code. It isn't needed for for compatibility with a downstream or vendor kernel. Get it out of the way to clear space for devfreq support. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Calling dev_pm_opp_find_freq_floor() returns the matched frequency in 'freq'. We don't need to call dev_pm_opp_get_freq() again to get the frequency value. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
We need to call dev_pm_opp_put() to put back the reference for the OPP struct after calling the various dev_pm_opp_get_* functions. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 03 1月, 2018 1 次提交
-
-
由 Archit Taneja 提交于
The msm/kms driver should work even if there is no GPU device specified in DT. Currently, we get a NULL dereference crash in adreno_load_gpu since the driver assumes that priv->gpu_pdev is non-NULL. Perform an additional check on priv->gpu_pdev before trying to retrieve the msm_gpu pointer from it. v2: Incorporate Jordan's comments: - Simplify the check to share the same error message. - Use dev_err_once() to avoid an error message every time we open the drm device fd. Fixes: eec874ce (drm/msm/adreno: load gpu at probe/bind time) Signed-off-by: NArchit Taneja <architt@codeaurora.org> Acked-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 14 12月, 2017 3 次提交
-
-
由 Nicolas Dechesne 提交于
* some a5xx files were missing * fixup for an existing typo Signed-off-by: NNicolas Dechesne <nicolas.dechesne@linaro.org> Reviewed-by: NRob Clark <robdclark@gmail.com> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Nicolas Dechesne 提交于
The preferred location for Adreno firmware files is now in qcom/ subfolder, especially now that we are adding some of them in linux-firmware. Reported-by: NBen Hutchings <ben@decadent.org.uk> Signed-off-by: NNicolas Dechesne <nicolas.dechesne@linaro.org> Reviewed-by: NRob Clark <robdclark@gmail.com> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Colin Ian King 提交于
Trivial fix to spelling mistake in DRM_DEV_ERROR error message Signed-off-by: NColin Ian King <colin.king@canonical.com> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 22 11月, 2017 1 次提交
-
-
由 Kees Cook 提交于
This converts all remaining cases of the old setup_timer() API into using timer_setup(), where the callback argument is the structure already holding the struct timer_list. These should have no behavioral changes, since they just change which pointer is passed into the callback with the same available pointers after conversion. It handles the following examples, in addition to some other variations. Casting from unsigned long: void my_callback(unsigned long data) { struct something *ptr = (struct something *)data; ... } ... setup_timer(&ptr->my_timer, my_callback, ptr); and forced object casts: void my_callback(struct something *ptr) { ... } ... setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr); become: void my_callback(struct timer_list *t) { struct something *ptr = from_timer(ptr, t, my_timer); ... } ... timer_setup(&ptr->my_timer, my_callback, 0); Direct function assignments: void my_callback(unsigned long data) { struct something *ptr = (struct something *)data; ... } ... ptr->my_timer.function = my_callback; have a temporary cast added, along with converting the args: void my_callback(struct timer_list *t) { struct something *ptr = from_timer(ptr, t, my_timer); ... } ... ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback; And finally, callbacks without a data assignment: void my_callback(unsigned long data) { ... } ... setup_timer(&ptr->my_timer, my_callback, 0); have their argument renamed to verify they're unused during conversion: void my_callback(struct timer_list *unused) { ... } ... timer_setup(&ptr->my_timer, my_callback, 0); The conversion is done with the following Coccinelle script: spatch --very-quiet --all-includes --include-headers \ -I ./arch/x86/include -I ./arch/x86/include/generated \ -I ./include -I ./arch/x86/include/uapi \ -I ./arch/x86/include/generated/uapi -I ./include/uapi \ -I ./include/generated/uapi --include ./include/linux/kconfig.h \ --dir . \ --cocci-file ~/src/data/timer_setup.cocci @fix_address_of@ expression e; @@ setup_timer( -&(e) +&e , ...) // Update any raw setup_timer() usages that have a NULL callback, but // would otherwise match change_timer_function_usage, since the latter // will update all function assignments done in the face of a NULL // function initialization in setup_timer(). @change_timer_function_usage_NULL@ expression _E; identifier _timer; type _cast_data; @@ ( -setup_timer(&_E->_timer, NULL, _E); +timer_setup(&_E->_timer, NULL, 0); | -setup_timer(&_E->_timer, NULL, (_cast_data)_E); +timer_setup(&_E->_timer, NULL, 0); | -setup_timer(&_E._timer, NULL, &_E); +timer_setup(&_E._timer, NULL, 0); | -setup_timer(&_E._timer, NULL, (_cast_data)&_E); +timer_setup(&_E._timer, NULL, 0); ) @change_timer_function_usage@ expression _E; identifier _timer; struct timer_list _stl; identifier _callback; type _cast_func, _cast_data; @@ ( -setup_timer(&_E->_timer, _callback, _E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, &_callback, _E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, _callback, (_cast_data)_E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, &_callback, (_cast_data)_E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, (_cast_func)_callback, _E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, (_cast_func)&_callback, _E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E._timer, _callback, (_cast_data)_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, _callback, (_cast_data)&_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, &_callback, (_cast_data)_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, &_callback, (_cast_data)&_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E); +timer_setup(&_E._timer, _callback, 0); | _E->_timer@_stl.function = _callback; | _E->_timer@_stl.function = &_callback; | _E->_timer@_stl.function = (_cast_func)_callback; | _E->_timer@_stl.function = (_cast_func)&_callback; | _E._timer@_stl.function = _callback; | _E._timer@_stl.function = &_callback; | _E._timer@_stl.function = (_cast_func)_callback; | _E._timer@_stl.function = (_cast_func)&_callback; ) // callback(unsigned long arg) @change_callback_handle_cast depends on change_timer_function_usage@ identifier change_timer_function_usage._callback; identifier change_timer_function_usage._timer; type _origtype; identifier _origarg; type _handletype; identifier _handle; @@ void _callback( -_origtype _origarg +struct timer_list *t ) { ( ... when != _origarg _handletype *_handle = -(_handletype *)_origarg; +from_timer(_handle, t, _timer); ... when != _origarg | ... when != _origarg _handletype *_handle = -(void *)_origarg; +from_timer(_handle, t, _timer); ... when != _origarg | ... when != _origarg _handletype *_handle; ... when != _handle _handle = -(_handletype *)_origarg; +from_timer(_handle, t, _timer); ... when != _origarg | ... when != _origarg _handletype *_handle; ... when != _handle _handle = -(void *)_origarg; +from_timer(_handle, t, _timer); ... when != _origarg ) } // callback(unsigned long arg) without existing variable @change_callback_handle_cast_no_arg depends on change_timer_function_usage && !change_callback_handle_cast@ identifier change_timer_function_usage._callback; identifier change_timer_function_usage._timer; type _origtype; identifier _origarg; type _handletype; @@ void _callback( -_origtype _origarg +struct timer_list *t ) { + _handletype *_origarg = from_timer(_origarg, t, _timer); + ... when != _origarg - (_handletype *)_origarg + _origarg ... when != _origarg } // Avoid already converted callbacks. @match_callback_converted depends on change_timer_function_usage && !change_callback_handle_cast && !change_callback_handle_cast_no_arg@ identifier change_timer_function_usage._callback; identifier t; @@ void _callback(struct timer_list *t) { ... } // callback(struct something *handle) @change_callback_handle_arg depends on change_timer_function_usage && !match_callback_converted && !change_callback_handle_cast && !change_callback_handle_cast_no_arg@ identifier change_timer_function_usage._callback; identifier change_timer_function_usage._timer; type _handletype; identifier _handle; @@ void _callback( -_handletype *_handle +struct timer_list *t ) { + _handletype *_handle = from_timer(_handle, t, _timer); ... } // If change_callback_handle_arg ran on an empty function, remove // the added handler. @unchange_callback_handle_arg depends on change_timer_function_usage && change_callback_handle_arg@ identifier change_timer_function_usage._callback; identifier change_timer_function_usage._timer; type _handletype; identifier _handle; identifier t; @@ void _callback(struct timer_list *t) { - _handletype *_handle = from_timer(_handle, t, _timer); } // We only want to refactor the setup_timer() data argument if we've found // the matching callback. This undoes changes in change_timer_function_usage. @unchange_timer_function_usage depends on change_timer_function_usage && !change_callback_handle_cast && !change_callback_handle_cast_no_arg && !change_callback_handle_arg@ expression change_timer_function_usage._E; identifier change_timer_function_usage._timer; identifier change_timer_function_usage._callback; type change_timer_function_usage._cast_data; @@ ( -timer_setup(&_E->_timer, _callback, 0); +setup_timer(&_E->_timer, _callback, (_cast_data)_E); | -timer_setup(&_E._timer, _callback, 0); +setup_timer(&_E._timer, _callback, (_cast_data)&_E); ) // If we fixed a callback from a .function assignment, fix the // assignment cast now. @change_timer_function_assignment depends on change_timer_function_usage && (change_callback_handle_cast || change_callback_handle_cast_no_arg || change_callback_handle_arg)@ expression change_timer_function_usage._E; identifier change_timer_function_usage._timer; identifier change_timer_function_usage._callback; type _cast_func; typedef TIMER_FUNC_TYPE; @@ ( _E->_timer.function = -_callback +(TIMER_FUNC_TYPE)_callback ; | _E->_timer.function = -&_callback +(TIMER_FUNC_TYPE)_callback ; | _E->_timer.function = -(_cast_func)_callback; +(TIMER_FUNC_TYPE)_callback ; | _E->_timer.function = -(_cast_func)&_callback +(TIMER_FUNC_TYPE)_callback ; | _E._timer.function = -_callback +(TIMER_FUNC_TYPE)_callback ; | _E._timer.function = -&_callback; +(TIMER_FUNC_TYPE)_callback ; | _E._timer.function = -(_cast_func)_callback +(TIMER_FUNC_TYPE)_callback ; | _E._timer.function = -(_cast_func)&_callback +(TIMER_FUNC_TYPE)_callback ; ) // Sometimes timer functions are called directly. Replace matched args. @change_timer_function_calls depends on change_timer_function_usage && (change_callback_handle_cast || change_callback_handle_cast_no_arg || change_callback_handle_arg)@ expression _E; identifier change_timer_function_usage._timer; identifier change_timer_function_usage._callback; type _cast_data; @@ _callback( ( -(_cast_data)_E +&_E->_timer | -(_cast_data)&_E +&_E._timer | -_E +&_E->_timer ) ) // If a timer has been configured without a data argument, it can be // converted without regard to the callback argument, since it is unused. @match_timer_function_unused_data@ expression _E; identifier _timer; identifier _callback; @@ ( -setup_timer(&_E->_timer, _callback, 0); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, _callback, 0L); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E->_timer, _callback, 0UL); +timer_setup(&_E->_timer, _callback, 0); | -setup_timer(&_E._timer, _callback, 0); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, _callback, 0L); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_E._timer, _callback, 0UL); +timer_setup(&_E._timer, _callback, 0); | -setup_timer(&_timer, _callback, 0); +timer_setup(&_timer, _callback, 0); | -setup_timer(&_timer, _callback, 0L); +timer_setup(&_timer, _callback, 0); | -setup_timer(&_timer, _callback, 0UL); +timer_setup(&_timer, _callback, 0); | -setup_timer(_timer, _callback, 0); +timer_setup(_timer, _callback, 0); | -setup_timer(_timer, _callback, 0L); +timer_setup(_timer, _callback, 0); | -setup_timer(_timer, _callback, 0UL); +timer_setup(_timer, _callback, 0); ) @change_callback_unused_data depends on match_timer_function_unused_data@ identifier match_timer_function_unused_data._callback; type _origtype; identifier _origarg; @@ void _callback( -_origtype _origarg +struct timer_list *unused ) { ... when != _origarg } Signed-off-by: NKees Cook <keescook@chromium.org>
-
- 28 10月, 2017 9 次提交
-
-
由 Jordan Crouse 提交于
Implement preemption for A5XX targets - this allows multiple ringbuffers for different priorities with automatic preemption of a lower priority ringbuffer if a higher one is ready. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
We use a global ringbuffer size and block size for all targets and at least for 5XX preemption we need to know the value the RB_CNTL in several locations so it makes sense to calculate it once and use it everywhere. The only monkey wrench is that we need to disable the RPTR shadow for A430 targets but that only needs to be done once and doesn't affect A5XX so we can or in the value at init time. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Add a shadow pointer to track the current command being written into the ring. Don't commit it as 'cur' until the command is submitted. Because 'cur' is used to construct the software copy of the wptr this ensures that somebody peeking in on the ring doesn't assume that a command is inflight while it is being written. This isn't a huge deal with a single ring (though technically the hangcheck could assume the system is prematurely busy when it isn't) but it will be rather important for preemption where the decision to preempt is based on a non-empty ringbuffer. Without a shadow an aggressive preemption scheme could assume that the ringbuffer is non empty and switch to it before the CPU is done writing the command and boom. Even though preemption won't be supported for all targets because of the way the code is organized it is simpler to make this generic for all targets. The extra load for non-preemption targets should be minimal. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
In order to manage ringbuffer priority to its fullest userspace should know how many ringbuffers it has to work with. Add a parameter to return the number of active rings. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Add the infrastructure to support the idea of multiple ringbuffers. Assign each ringbuffer an id and use that as an index for the various ring specific operations. The biggest delta is to support legacy fences. Each fence gets its own sequence number but the legacy functions expect to use a unique integer. To handle this we return a unique identifier for each submission but map it to a specific ring/sequence under the covers. Newer users use a dma_fence pointer anyway so they don't care about the actual sequence ID or ring. The actual mechanics for multiple ringbuffers are very target specific so this code just allows for the possibility but still only defines one ringbuffer for each target family. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
When we move to multiple ringbuffers we're going to store the data in the memptrs on a per-ring basis. In order to prepare for that move the current memptrs from the adreno namespace into msm_gpu. This is way cleaner and immediately lets us kill off some sub functions so there is much less cost later when we do move to per-ring structs. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Rob Clark 提交于
When firmware was added to linux-firmware, it was put in a qcom sub- directory, unlike what we'd been using before. For a300_pfp.fw and a300_pm4.fw symlinks were created, but we'd prefer not to have to do this in the future. So add support to look in both places when loading firmware. Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Rob Clark 提交于
Prep work for the next patch. Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Rob Clark 提交于
Previously, in an effort to defer initializing the gpu until firmware was available (ie. rootfs mounted), the gpu was not loaded at when the subdevice was bound. Which resulted that clks/etc were requested in a place that devm couldn't really help unwind if something failed. Instead move request_firmware() to gpu->hw_init() and construct the gpu earlier in adreno_bind(). To avoid the rest of the driver needing to be aware of a gpu that hasn't managed to load firmware and hw_init() yet, stash the gpu ptr in the adreno device's drvdata, and don't set priv->gpu() until hw_init() succeeds. Signed-off-by: NRob Clark <robdclark@gmail.com>
-
- 23 8月, 2017 3 次提交
-
-
由 Arnd Bergmann 提交于
A cleanup left behind an unused variable that we have to remove in order to avoid this harmless warning: drivers/gpu/drm/msm/adreno/a5xx_gpu.c: In function 'a5xx_zap_shader_init': drivers/gpu/drm/msm/adreno/a5xx_gpu.c:493:19: error: unused variable 'a5xx_gpu' [-Werror=unused-variable] Fixes: 8d6f0827 ("drm/msm: Remove uneeded platform dev members") Signed-off-by: NArnd Bergmann <arnd@arndb.de> Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Nearly all of the buffer allocations for kernel allocate an buffer object, virtual address and GPU iova at the same time. Make a helper function to handle the details. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> [dropped msm_fbdev conversion to new helper, since it interferes with display-handover work, where we want to separate allocation and mapping] Signed-off-by: NRob Clark <robdclark@gmail.com>
-
由 Jordan Crouse 提交于
Currently the GPU MMU is attached in the adreno_gpu code but as more and more of the GPU initialization moves to the generic GPU path we have a need to map and use GPU memory earlier and earlier. There isn't any reason to defer attaching the MMU until later so attach it right after the address space is created so it can be used immediately. Signed-off-by: NJordan Crouse <jcrouse@codeaurora.org> Signed-off-by: NRob Clark <robdclark@gmail.com>
-