[PATCH] drm/radeon: fix atombios on big endian

Alex Deucher alexdeucher at gmail.com
Tue Oct 31 21:40:01 UTC 2017


On Mon, Oct 30, 2017 at 6:56 AM, Roman Kapl <rka at sysgo.com> wrote:
> The function for byteswapping the data send to/from atombios was buggy for
> num_bytes not divisible by four. The function must be aware of the fact
> that after byte-swapping the u32 units, valid bytes might end up after the
> num_bytes boundary.
>
> This patch was tested on kernel 3.12 and allowed us to sucesfully use
> DisplayPort on and Radeon SI card. Namely it fixed the link training and
> EDID readout.
>
> The function is patched both in radeon and amd drivers, since the functions
> and the fixes are identical.
>
> Signed-off-by: Roman Kapl <rka at sysgo.com>

Applied.  thanks!

Alex

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 38 +++++++++++++---------------
>  drivers/gpu/drm/radeon/atombios_dp.c         | 38 +++++++++++++---------------
>  2 files changed, 36 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> index ce443586a0c7..cc4e18dcd8b6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> @@ -1766,34 +1766,32 @@ bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev)
>                 return true;
>  }
>
> -/* Atom needs data in little endian format
> - * so swap as appropriate when copying data to
> - * or from atom. Note that atom operates on
> - * dw units.
> +/* Atom needs data in little endian format so swap as appropriate when copying
> + * data to or from atom. Note that atom operates on dw units.
> + *
> + * Use to_le=true when sending data to atom and provide at least
> + * ALIGN(num_bytes,4) bytes in the dst buffer.
> + *
> + * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4)
> + * byes in the src buffer.
>   */
>  void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
>  {
>  #ifdef __BIG_ENDIAN
> -       u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
> -       u32 *dst32, *src32;
> +       u32 src_tmp[5], dst_tmp[5];
>         int i;
> +       u8 align_num_bytes = ALIGN(num_bytes, 4);
>
> -       memcpy(src_tmp, src, num_bytes);
> -       src32 = (u32 *)src_tmp;
> -       dst32 = (u32 *)dst_tmp;
>         if (to_le) {
> -               for (i = 0; i < ((num_bytes + 3) / 4); i++)
> -                       dst32[i] = cpu_to_le32(src32[i]);
> -               memcpy(dst, dst_tmp, num_bytes);
> +               memcpy(src_tmp, src, num_bytes);
> +               for (i = 0; i < align_num_bytes / 4; i++)
> +                       dst_tmp[i] = cpu_to_le32(src_tmp[i]);
> +               memcpy(dst, dst_tmp, align_num_bytes);
>         } else {
> -               u8 dws = num_bytes & ~3;
> -               for (i = 0; i < ((num_bytes + 3) / 4); i++)
> -                       dst32[i] = le32_to_cpu(src32[i]);
> -               memcpy(dst, dst_tmp, dws);
> -               if (num_bytes % 4) {
> -                       for (i = 0; i < (num_bytes % 4); i++)
> -                               dst[dws+i] = dst_tmp[dws+i];
> -               }
> +               memcpy(src_tmp, src, align_num_bytes);
> +               for (i = 0; i < align_num_bytes / 4; i++)
> +                       dst_tmp[i] = le32_to_cpu(src_tmp[i]);
> +               memcpy(dst, dst_tmp, num_bytes);
>         }
>  #else
>         memcpy(dst, src, num_bytes);
> diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
> index 432cb46f6a34..fd7682bf335d 100644
> --- a/drivers/gpu/drm/radeon/atombios_dp.c
> +++ b/drivers/gpu/drm/radeon/atombios_dp.c
> @@ -45,34 +45,32 @@ static char *pre_emph_names[] = {
>
>  /***** radeon AUX functions *****/
>
> -/* Atom needs data in little endian format
> - * so swap as appropriate when copying data to
> - * or from atom. Note that atom operates on
> - * dw units.
> +/* Atom needs data in little endian format so swap as appropriate when copying
> + * data to or from atom. Note that atom operates on dw units.
> + *
> + * Use to_le=true when sending data to atom and provide at least
> + * ALIGN(num_bytes,4) bytes in the dst buffer.
> + *
> + * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4)
> + * byes in the src buffer.
>   */
>  void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
>  {
>  #ifdef __BIG_ENDIAN
> -       u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
> -       u32 *dst32, *src32;
> +       u32 src_tmp[5], dst_tmp[5];
>         int i;
> +       u8 align_num_bytes = ALIGN(num_bytes, 4);
>
> -       memcpy(src_tmp, src, num_bytes);
> -       src32 = (u32 *)src_tmp;
> -       dst32 = (u32 *)dst_tmp;
>         if (to_le) {
> -               for (i = 0; i < ((num_bytes + 3) / 4); i++)
> -                       dst32[i] = cpu_to_le32(src32[i]);
> -               memcpy(dst, dst_tmp, num_bytes);
> +               memcpy(src_tmp, src, num_bytes);
> +               for (i = 0; i < align_num_bytes / 4; i++)
> +                       dst_tmp[i] = cpu_to_le32(src_tmp[i]);
> +               memcpy(dst, dst_tmp, align_num_bytes);
>         } else {
> -               u8 dws = num_bytes & ~3;
> -               for (i = 0; i < ((num_bytes + 3) / 4); i++)
> -                       dst32[i] = le32_to_cpu(src32[i]);
> -               memcpy(dst, dst_tmp, dws);
> -               if (num_bytes % 4) {
> -                       for (i = 0; i < (num_bytes % 4); i++)
> -                               dst[dws+i] = dst_tmp[dws+i];
> -               }
> +               memcpy(src_tmp, src, align_num_bytes);
> +               for (i = 0; i < align_num_bytes / 4; i++)
> +                       dst_tmp[i] = le32_to_cpu(src_tmp[i]);
> +               memcpy(dst, dst_tmp, num_bytes);
>         }
>  #else
>         memcpy(dst, src, num_bytes);
> --
> 2.11.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list