Commit Graph

156 Commits

Author SHA1 Message Date
Colin Ian King
546907de99 drm/msm: a6xx: fix spelling mistake: "initalization" -> "initialization"
Trivial fix to spelling mistake in dev_err message and comment

Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-08-10 18:49:18 -04:00
Jordan Crouse
4b565ca5a2 drm/msm: Add A6XX device support
Add support for the A6XX family of Adreno GPUs. The biggest addition
is the GMU (Graphics Management Unit) which takes over most of the
power management of the GPU itself but in a ironic twist of fate
needs a goodly amount of management itself. Add support for the
A6XX core code, the GMU and the HFI (hardware firmware interface)
queue that the CPU uses to communicate with the GMU.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-08-10 18:49:18 -04:00
Rob Clark
2d75632253 drm/msm: update generated headers
Resync generated headers to pull in a6xx registers.

Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-08-10 18:49:18 -04:00
Jordan Crouse
2c087a3366 drm/msm/adreno: Load the firmware before bringing up the hardware
Failure to load firmware is the primary reason to fail adreno_load_gpu().
Try to load it first before going into the hardware initialization code and
unwinding it. This is important for a6xx because the GMU gets loaded from
the runtime power code and it is more costly to fail in that path because
of missing firmware.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-08-10 18:49:18 -04:00
Kees Cook
bec2dd6969 drm/msm/adreno: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this
switches to using a kasprintf()ed buffer. Return paths are updated
to free the allocation.

[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-08-05 10:07:09 -04:00
Arnd Bergmann
3530a17f4d drm/msm/gpu: avoid deprecated do_gettimeofday
All users of do_gettimeofday() have been removed, but this one recently
crept in, along with an incorrect printing of the microseconds portion.

This converts it to using ktime_get_real_timespec64() as a direct
replacement, and adds the leading zeroes. I considered using monotonic
times (ktime_get()) instead, but as this timestamp appears to only
be used for humans rather than compared with other timestamps, the
real time domain is probably good enough.

Fixes: e43b045e2c82 ("drm/msm/gpu: Capture the state of the GPU")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:50:12 -04:00
Jordan Crouse
cdb95931de drm/msm/gpu: Add the buffer objects from the submit to the crash dump
For hangs, dump copy out the contents of the buffer objects attached to the
guilty submission and print them in the crash dump report.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:50:10 -04:00
Jordan Crouse
50f8d21863 drm/msm/adreno: Add a5xx specific registers for the GPU state
HLSQ, SP and TP registers are only accessible from a special
aperture and to make matters worse the aperture is blocked from
the CPU on targets that can support secure rendering. Luckily the
GPU hardware has its own purpose built register dumper that can
access the registers from the aperture. Add a5xx specific code
to program the crashdumper and retrieve the wayward registers
and dump them for the crash state.

Also, remove a block of registers the regular CPU accessible
list that aren't useful for debug which helps reduce the size
of the crash state file by a goodly amount.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:50:06 -04:00
Jordan Crouse
43a56687d1 drm/msm/adreno: Add ringbuffer data to the GPU state
Add the contents of each ringbuffer to the GPU state and dump the
data in the crash file encoded with ascii85. To save space only
the used portions of the ringbuffer are dumped.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:50:03 -04:00
Jordan Crouse
bcf1d9fa5d drm/msm/adreno: Convert the show/crash file format
Convert the format of the 'show' debugfs file and the crash
dump to a  format resembling YAML. This should be easier to
parse and be more flexible for future changes and expansions.

v2: Use a standard .rst for the msm crashdump documentation

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:50:00 -04:00
Jordan Crouse
c0fec7f562 drm/msm/gpu: Capture the GPU state on a GPU hang
Capture the GPU state on a GPU hang and store it for later playback
via the devcoredump facility. Only one crash state is stored at a
time on the assumption that the first hang is usually the most
interesting. The existing crash state can be cleared after capturing
it and then a new one will be captured on the next hang.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:49:56 -04:00
Jordan Crouse
4f776f4511 drm/msm/gpu: Convert the GPU show function to use the GPU state
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:49:48 -04:00
Jordan Crouse
e00e473d98 drm/msm/gpu: Capture the state of the GPU
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-30 08:49:45 -04:00
Jordan Crouse
64709686db drm/msm/gpu: Increase the pm runtime autosuspend for 5xx
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-25 07:51:04 -04:00
Daniel Mack
6666e1a66f drm/msm/adreno: Add power management functions for system sleep
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: Daniel Mack <daniel@zonque.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-07-25 07:51:04 -04:00
Maarten Lankhorst
94cc2fde36 Merge remote-tracking branch 'drm/drm-next' into drm-misc-next
drm-misc-next is still based on v4.16-rc7, and was getting a bit stale.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
2018-05-11 18:08:10 +02:00
Daniel Vetter
9e1de90021 drm/msm: Don't setup control node debugfs files
It's going away.

v2: Try harder to find them all.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel 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
2018-05-03 21:26:10 +02:00
Linus Torvalds
92589cbdda remoteproc updates for v4.17
This adds support for generating coredumps for remoteprocs using
 devcoredump, adds the Qualcomm sysmon driver for intra-remoteproc crash
 handling and a number of fixes in Qualcomm and IMX drivers.
 -----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAlrL5dgbHGJqb3JuLmFu
 ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3FufUP/ifQ+QbDzYzBI4CHfbef
 hls8bplN9GlW4acJuhVRe8ikGz6vHZdyH88KJJX+IHekDXFqk10rWEgcyfV0h5mU
 qOrhiW7hjfm2Mhs0MvNg9rKxbFrD5wAeJBJn8ukTB4z4jc9iFPazVu37V3ul/wVR
 yMM4zI6kA54UwsLunqLEapb1thgLO4P99tvA+vdR8ekz/j0AVHB7HiHVLY1JX5Gu
 D679icQSWOSsSQaRR7G0E97ZKZF6XaM6+aJV3eZol1HQw8k3I/Vbudi2wIKj0Ia8
 jLO5JyCpgeSAAjPCZLrB5XyUXl/vU7PSPKTPyOnv2lK1wQgKsmHX80HfeAt1ISNn
 4nY/Oy651/rjBN3FR9HQvQoqCDF08GG5YRDmUZCg0kS/OStrbJT4eCm+hklvanmK
 O98LEWm5+FLqk+9Wau1DXGa0raXon2REIJxQSDnBUODZSqTQBS1iQmdtdYtrZxRp
 17LtCABCSBMbAI8VE6eb/5jj/z07aI0pBwKEYEWOOG2xsF6q1GGZAXRxnmMUOWAv
 bwSgiNqNbbYUdYMjVYDxDtWIp3/Dy8VQ3N3Fz61SieS0GjJxDy/SyNByzVL4eEjk
 yYj+N74Dxgms1V/xknQmJn4ktwqaVxapnj52WF1WaEtIcm5WvPFZUVNSFvWMlbcD
 rAiTKkpFC0CkINlM+dk3Ti/a
 =cxV7
 -----END PGP SIGNATURE-----

Merge tag 'rproc-v4.17' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:

 - add support for generating coredumps for remoteprocs using
   devcoredump

 - add the Qualcomm sysmon driver for intra-remoteproc crash handling

 - a number of fixes in Qualcomm and IMX drivers

* tag 'rproc-v4.17' of git://github.com/andersson/remoteproc:
  remoteproc: fix null pointer dereference on glink only platforms
  soc: qcom: qmi: add CONFIG_NET dependency
  remoteproc: imx_rproc: Slightly simplify code in 'imx_rproc_probe()'
  remoteproc: imx_rproc: Re-use existing error handling path in 'imx_rproc_probe()'
  remoteproc: imx_rproc: Fix an error handling path in 'imx_rproc_probe()'
  samples: Introduce Qualcomm QMI sample client
  remoteproc: qcom: Introduce sysmon
  remoteproc: Pass type of shutdown to subdev remove
  remoteproc: qcom: Register segments for core dump
  soc: qcom: mdt-loader: Return relocation base
  remoteproc: Rename "load_rsc_table" to "parse_fw"
  remoteproc: Add remote processor coredump support
  remoteproc: Remove null character write of shared mem
2018-04-10 12:09:27 -07:00
Arnd Bergmann
288e5c8898 drm/msm: fix building without debugfs
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: 331dc0bc19 ("drm/msm: add a5xx specific debugfs")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-03-19 06:33:39 -04:00
Bjorn Andersson
79d57bf6fa drm/msm: Trigger fence completion from GPU
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-03-19 06:33:36 -04:00
Gustavo A. R. Silva
5abc7dd7b5 drm/msm/adreno/a5xx_debugfs: fix potential NULL pointer dereference
_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: Gustavo A. R. Silva <garsilva@embeddedor.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-03-19 06:33:34 -04:00
Jordan Crouse
9de43e79c1 drm/msm/adreno: Use generic function to load firmware to a buffer object
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:22 -05:00
Jordan Crouse
c5e3548c29 drm/msm/adreno: Define a list of firmware files to load per target
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:22 -05:00
Jordan Crouse
f306953fdb drm/msm/adreno: Rename gpmufw to powerfw
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:22 -05:00
Steve Kowalik
dc9a9b3205 drm/msm: Replace gem_object deprecated functions
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: Steve Kowalik <steven@wedontsleep.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:21 -05:00
Rob Clark
6a8bd08d04 drm/msm: add sudo flag to submit ioctl
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: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:20 -05:00
Rob Clark
331dc0bc19 drm/msm: add a5xx specific debugfs
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: Rob Clark <robdclark@gmail.com>
2018-02-20 10:41:20 -05:00
Bjorn Andersson
4dd27f544c soc: qcom: mdt-loader: Return relocation base
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: Andy Gross <andy.gross@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-12 11:05:38 -08:00
Jordan Crouse
f91c14ab44 drm/msm: Add devfreq support for the GPU
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 14:30:03 -05:00
Jordan Crouse
c09513cfeb drm/msm/adreno: a5xx: Explicitly program the CP0 performance counter
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:42 -05:00
Jordan Crouse
f56d9df656 drm/msm/adreno: Read the speed bins for a5xx targets
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:42 -05:00
Jordan Crouse
999ae6edc1 drm/msm/adreno: Move clock parsing to adreno_gpu_init()
Move the clock parsing to adreno_gpu_init() to allow for target
specific probing and manipulation of the clock tables.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:42 -05:00
Jordan Crouse
728bde66df drm/msm/adreno: Cleanup chipid parsing
We don't need to convert the chipid to an intermediate value and
then back again into a struct adreno_rev.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:42 -05:00
Jordan Crouse
1babd706b4 drm/msm/gpu: Remove unused bus scaling code
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:42 -05:00
Jordan Crouse
156a537d05 drm/msm/adreno: Remove a useless call to dev_pm_opp_get_freq()
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:41 -05:00
Jordan Crouse
aa2a2ab7b7 drm/msm/adreno: Call dev_pm_opp_put()
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-10 08:58:41 -05:00
Archit Taneja
9dcfbc182f drm/msm: Fix NULL deref in adreno_load_gpu
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: eec874ce5f (drm/msm/adreno: load gpu at probe/bind time)

Signed-off-by: Archit Taneja <architt@codeaurora.org>
Acked-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2018-01-03 09:36:17 -05:00
Nicolas Dechesne
ad40dfdcfd drm/msm: add missing MODULE_FIRMWARE declarations
* some a5xx files were missing
* fixup for an existing typo

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-13 11:08:18 -05:00
Nicolas Dechesne
73fc251f66 drm/msm: update adreno firmware path in MODULE_FIRMWARE
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: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-13 11:08:07 -05:00
Colin Ian King
3a9016ba0e drm/msm: fix spelling mistake: "ringubffer" -> "ringbuffer"
Trivial fix to spelling mistake in DRM_DEV_ERROR error message

Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-13 11:01:20 -05:00
Kees Cook
e99e88a9d2 treewide: setup_timer() -> timer_setup()
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: Kees Cook <keescook@chromium.org>
2017-11-21 15:57:07 -08:00
Jordan Crouse
b1fc2839d2 drm/msm: Implement preemption for A5XX targets
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:38 -04:00
Jordan Crouse
4d87fc32df drm/msm: Make the value of RB_CNTL (almost) generic
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:38 -04:00
Jordan Crouse
4c7085a5d5 drm/msm: Shadow current pointer in the ring until command is complete
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:37 -04:00
Jordan Crouse
a6e29a0eea drm/msm: Add a parameter query for the number of ringbuffers
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:37 -04:00
Jordan Crouse
f97decac5f drm/msm: Support multiple ringbuffers
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:36 -04:00
Jordan Crouse
cd414f3d93 drm/msm: Move memptrs to msm_gpu
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:36 -04:00
Rob Clark
2c41ef1b6f drm/msm/adreno: deal with linux-firmware fw paths
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: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:31 -04:00
Rob Clark
e8f3de96a9 drm/msm/adreno: split out helper to load fw
Prep work for the next patch.

Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:31 -04:00
Rob Clark
eec874ce5f drm/msm/adreno: load gpu at probe/bind time
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: Rob Clark <robdclark@gmail.com>
2017-10-28 11:01:31 -04:00