[media] media: ti-vpe: vpdma: Make list post atomic operation
authorNikhil Devshatwar <nikhil.nd@ti.com>
Fri, 18 Nov 2016 23:20:23 +0000 (21:20 -0200)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Tue, 22 Nov 2016 09:49:16 +0000 (07:49 -0200)
Writing to the "VPDMA list attribute" register is considered as a list
post. This informs the VPDMA firmware to load the list from the address
which should be taken from the "VPDMA list address" register.

As these two register writes are dependent, it is important that the two
writes happen in atomic manner. This ensures multiple slices (which share
same VPDMA) can post lists asynchronously and all of them point to the
correct addresses.

Slightly modified to implementation for the original patch to use
spin_lock instead of mutex as the list post is also called from
interrupt context.

Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
Signed-off-by: Benoit Parrot <bparrot@ti.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/platform/ti-vpe/vpdma.c
drivers/media/platform/ti-vpe/vpdma.h

index 7808c9c1828bd3818a39579f274bffd25daa764c..ffc281d2b0656e6cef8d556a7fb4e9ab26901d47 100644 (file)
@@ -491,6 +491,7 @@ int vpdma_submit_descs(struct vpdma_data *vpdma,
                        struct vpdma_desc_list *list, int list_num)
 {
        int list_size;
+       unsigned long flags;
 
        if (vpdma_list_busy(vpdma, list_num))
                return -EBUSY;
@@ -498,12 +499,14 @@ int vpdma_submit_descs(struct vpdma_data *vpdma,
        /* 16-byte granularity */
        list_size = (list->next - list->buf.addr) >> 4;
 
+       spin_lock_irqsave(&vpdma->lock, flags);
        write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr);
 
        write_reg(vpdma, VPDMA_LIST_ATTR,
                        (list_num << VPDMA_LIST_NUM_SHFT) |
                        (list->type << VPDMA_LIST_TYPE_SHFT) |
                        list_size);
+       spin_unlock_irqrestore(&vpdma->lock, flags);
 
        return 0;
 }
@@ -1090,6 +1093,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev,
 
        vpdma->pdev = pdev;
        vpdma->cb = cb;
+       spin_lock_init(&vpdma->lock);
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma");
        if (res == NULL) {
index 4dafc1bcf1167bb5206adc7374ba9fee93ea32d8..f08f4370ce4a80624ee5a9b23ac9458590f5c84b 100644 (file)
@@ -35,6 +35,7 @@ struct vpdma_data {
 
        struct platform_device  *pdev;
 
+       spinlock_t              lock;
        /* callback to VPE driver when the firmware is loaded */
        void (*cb)(struct platform_device *pdev);
 };