This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DM355 Wait-For-Interrupt Sleep problem

I am trying to implement sleep on DM355 using DVSDK 3.1. I have found some code here:

http://www.mail-archive.com/davinci-linux-open-source@linux.davincidsp.com/msg04407.html

I had to clean it up a bit. However, there seems to be a problem with DVSDK 3.1.

To put the board to sleep I run: echo "standby" > /sys/power/state

If my understanding is correct, before calling "my" (not actually, I took it from the link above) code, the kernel  attempts to notify the drivers about a pending suspend command. The problem is appears with drivers/media/video/davinci_display.c.This driver has one standalone structure (in my case located at address 0xC02AB188):

file: drivers/media/video/davinci_display.c
static struct device_driver davinci_driver = {
    .name = DAVINCI_DISPLAY_DRIVER,
    .bus = &platform_bus_type,
    .probe = davinci_probe,
    .remove = davinci_remove,
};

However the kernel is trying to find a parent of this structure and call a pointer located in the parent:

file: drivers/base/platform.c
static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
{
    struct platform_driver *pdrv = to_platform_driver(dev->driver);
    struct platform_device *pdev = to_platform_device(dev);
    int ret = 0;

    if (dev->driver && pdrv->suspend)
        ret = pdrv->suspend(pdev, mesg);

    return ret;
}

In this platform_legacy_suspend function dev->driver points (address 0xC02AB188) to the structure defined above in davinci_display.c.

However the first line in the function is trying to find a container of struct device_driver as if davinci_display.c had it defined as following:

 

static struct platform_driver some_name {
    // ...
    .driver = {
        .name = DAVINCI_DISPLAY_DRIVER,
        .bus = &platform_bus_type,
        .probe = davinci_probe,

        .remove = davinci_remove,
    },
};

Since the parent (container of struct device_driver)  does not exist, the first line in platform_legacy_suspend() produced a pointer (address 0xC02AB174) outside of the structure.

Now, .suspend field in this non-existing structure contains some garbage data which is interpreted as a pointer to a suspend function (address is  0x000CA800). Obviously this is invalid address for a function and the kernel gives an Oops.

What is going on here? Is the driver structure defined incorrectly?

Thank you.

  • I think the problem is that the driver were not updated to what kernel expects them to be.

    PSP team should look into the Documentation/driver-model/platform.txt for information on how to use platform_driver and platform_device and update the drivers accordingly.

    Drivers (davinci_display.c, for example) use structure that were compatible with older kernels. I know it matched the kernel used in IPNC camera. However, newer kernel in DVSDK 3.1 expects a slightly different structure. Here is what I changed it to:

    static struct platform_driver davinci_driver = {
        .remove = __exit_p(davinci_remove),
        .driver = {
            .name = DAVINCI_DISPLAY_DRIVER,
        }
    };

    This is not a hot-plug device and the registration is done using:

    platform_driver_probe(&davinci_driver, davinci_probe);

    In this case after the device is registered the kernel can remove the davinci_probe() function and free up some more memory. And everybody would agree that more memory is good.

    Regards,

    Genna