Re: [BUG REPORT] media: coda: mpeg4 decode corruption on i.MX6qp only

From: Philipp Zabel
Date: Thu Feb 11 2021 - 09:36:08 EST


Hi Sven,

On Wed, Feb 10, 2021 at 01:29:29PM -0500, Sven Van Asbroeck wrote:
> Found it!
>
> The i.MX6QuadPlus has two pairs of PREs, which use the extended
> section of the iRAM. The Classic does not have any PREs or extended
> iRAM:
>
> pre1: pre@21c8000 {
> compatible = "fsl,imx6qp-pre";
> <snip>
> fsl,iram = <&ocram2>;
> };
>
> pre3: pre@21ca000 {
> compatible = "fsl,imx6qp-pre";
> <snip>
> fsl,iram = <&ocram3>;
> };
>
> The CODA (VPU) driver uses the common section of iRAM:
>
> vpu: vpu@2040000 {
> compatible = "cnm,coda960";
> <snip>
> iram = <&ocram>;
> };
>
> The VPU or the PREs are overrunning their assigned iRAM area. How do I
> know? Because if I change the PRE iRAM order, the problem disappears!
>
> PRE1: ocram2 change to ocram3
> PRE2: ocram2 change to ocram3
> PRE3: ocram3 change to ocram2
> PRE4: ocram3 change to ocram2

Thank you for debugging this. Given that CODA uses the OCRAM address
range 0x900000-0x940000 and the PREs use OCRAM2 at 0x940000-0x960000
and OCRAM3 at 0x960000-0x980000, it seems unlikely that the PREs would
overrun into the CODA iRAM. But maybe there is some stride related
overflow that causes it to write at negative offsets or some other kind
of oversight.

Could you check /sys/kernel/debug/dri/?/state while running the error case?

Another thing that might help to identify who is writing where might be to
clear the whole OCRAM region and dump it after running only decode or only
PRE/PRG scanout, for example:

----------8<----------
/* Clear OCRAM */
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#define OCRAM_START 0x900000
#define OCRAM_SIZE 0x80000

int main(int argc, char *argv[])
{
int fd = open("/dev/mem", O_RDWR | O_SYNC);
void *map = mmap(NULL, OCRAM_SIZE, PROT_WRITE, MAP_SHARED, fd, OCRAM_START);
if (map == MAP_FAILED)
return EXIT_FAILURE;
memset(map, 0, OCRAM_SIZE);
munmap(map, OCRAM_SIZE);
close(fd);
return EXIT_SUCCESS;
}
---------->8----------

----------8<----------
/* Dump OCRAM to stdout */
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

#define OCRAM_START 0x900000
#define OCRAM_SIZE 0x80000

int main(int argc, char *argv[])
{
int fd = open("/dev/mem", O_RDONLY | O_SYNC);
void *map = mmap(NULL, OCRAM_SIZE, PROT_READ, MAP_SHARED, fd, OCRAM_START);
if (map == MAP_FAILED)
return EXIT_FAILURE;
write(1, map, OCRAM_SIZE);
munmap(map, OCRAM_SIZE);
close(fd);
return EXIT_SUCCESS;
}
---------->8----------

regards
Philipp