lkml.org 
[lkml]   [2017]   [Aug]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.18 44/50] drm/msm: Ensure that the hardware write pointer is valid
    Date
    3.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Jordan Crouse <jcrouse@codeaurora.org>


    [ Upstream commit 88b333b0ed790f9433ff542b163bf972953b74d3 ]

    Currently the value written to CP_RB_WPTR is calculated on the fly as
    (rb->next - rb->start). But as the code is designed rb->next is wrapped
    before writing the commands so if a series of commands happened to
    fit perfectly in the ringbuffer, rb->next would end up being equal to
    rb->size / 4 and thus result in an out of bounds address to CP_RB_WPTR.

    The easiest way to fix this is to mask WPTR when writing it to the
    hardware; it makes the hardware happy and the rest of the ringbuffer
    math appears to work and there isn't any point in upsetting anything.

    Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
    [squash in is_power_of_2() check]
    Signed-off-by: Rob Clark <robdclark@gmail.com>

    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/gpu/drm/msm/adreno/adreno_gpu.c | 9 ++++++++-
    drivers/gpu/drm/msm/msm_ringbuffer.c | 3 ++-
    2 files changed, 10 insertions(+), 2 deletions(-)

    --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
    +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
    @@ -199,7 +199,14 @@ void adreno_flush(struct msm_gpu *gpu)
    void adreno_idle(struct msm_gpu *gpu)
    {
    struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
    - uint32_t wptr = get_wptr(gpu->rb);
    + uint32_t wptr;
    +
    + /*
    + * Mask wptr value that we calculate to fit in the HW range. This is
    + * to account for the possibility that the last command fit exactly into
    + * the ringbuffer and rb->next hasn't wrapped to zero yet
    + */
    + wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1);

    /* wait for CP to drain ringbuffer: */
    if (spin_until(adreno_gpu->memptrs->rptr == wptr))
    --- a/drivers/gpu/drm/msm/msm_ringbuffer.c
    +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c
    @@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_ne
    struct msm_ringbuffer *ring;
    int ret;

    - size = ALIGN(size, 4); /* size should be dword aligned */
    + if (WARN_ON(!is_power_of_2(size)))
    + return ERR_PTR(-EINVAL);

    ring = kzalloc(sizeof(*ring), GFP_KERNEL);
    if (!ring) {

    \
     
     \ /
      Last update: 2017-08-05 01:33    [W:3.589 / U:0.224 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site