Commit 0872dc04 authored by Tomi Valkeinen's avatar Tomi Valkeinen Committed by Mauro Carvalho Chehab

media: ti: cal: combine wdma irq handling

Instead of handling the WDMA START and END interrupts separately, we
need to handle both at the same time to better manage the inherent race
conditions related to CAL interrupts.

Change the code so that we have a single function,
cal_irq_handle_wdma(), which gets two booleans, start and end, as
parameters, which allows us to manage the race conditions in the
following patch.
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent ebdb28a5
...@@ -715,22 +715,33 @@ static inline void cal_irq_wdma_end(struct cal_ctx *ctx) ...@@ -715,22 +715,33 @@ static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
} }
} }
static void cal_irq_handle_wdma(struct cal_ctx *ctx, bool start, bool end)
{
if (end)
cal_irq_wdma_end(ctx);
if (start)
cal_irq_wdma_start(ctx);
}
static irqreturn_t cal_irq(int irq_cal, void *data) static irqreturn_t cal_irq(int irq_cal, void *data)
{ {
struct cal_dev *cal = data; struct cal_dev *cal = data;
u32 status; u32 status[3];
unsigned int i;
status = cal_read(cal, CAL_HL_IRQSTATUS(0));
if (status) {
unsigned int i;
cal_write(cal, CAL_HL_IRQSTATUS(0), status); for (i = 0; i < 3; ++i) {
status[i] = cal_read(cal, CAL_HL_IRQSTATUS(i));
if (status[i])
cal_write(cal, CAL_HL_IRQSTATUS(i), status[i]);
}
if (status & CAL_HL_IRQ_OCPO_ERR_MASK) if (status[0]) {
if (status[0] & CAL_HL_IRQ_OCPO_ERR_MASK)
dev_err_ratelimited(cal->dev, "OCPO ERROR\n"); dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
for (i = 0; i < cal->data->num_csi2_phy; ++i) { for (i = 0; i < cal->data->num_csi2_phy; ++i) {
if (status & CAL_HL_IRQ_CIO_MASK(i)) { if (status[0] & CAL_HL_IRQ_CIO_MASK(i)) {
u32 cio_stat = cal_read(cal, u32 cio_stat = cal_read(cal,
CAL_CSI2_COMPLEXIO_IRQSTATUS(i)); CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
...@@ -741,7 +752,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data) ...@@ -741,7 +752,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
cio_stat); cio_stat);
} }
if (status & CAL_HL_IRQ_VC_MASK(i)) { if (status[0] & CAL_HL_IRQ_VC_MASK(i)) {
u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i)); u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i));
dev_err_ratelimited(cal->dev, dev_err_ratelimited(cal->dev,
...@@ -753,32 +764,12 @@ static irqreturn_t cal_irq(int irq_cal, void *data) ...@@ -753,32 +764,12 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
} }
} }
/* Check which DMA just finished */ for (i = 0; i < cal->num_contexts; ++i) {
status = cal_read(cal, CAL_HL_IRQSTATUS(1)); bool end = !!(status[1] & CAL_HL_IRQ_WDMA_END_MASK(i));
if (status) { bool start = !!(status[2] & CAL_HL_IRQ_WDMA_START_MASK(i));
unsigned int i;
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(1), status);
for (i = 0; i < cal->num_contexts; ++i) {
if (status & CAL_HL_IRQ_WDMA_END_MASK(i))
cal_irq_wdma_end(cal->ctx[i]);
}
}
/* Check which DMA just started */
status = cal_read(cal, CAL_HL_IRQSTATUS(2));
if (status) {
unsigned int i;
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(2), status);
for (i = 0; i < cal->num_contexts; ++i) { if (start || end)
if (status & CAL_HL_IRQ_WDMA_START_MASK(i)) cal_irq_handle_wdma(cal->ctx[i], start, end);
cal_irq_wdma_start(cal->ctx[i]);
}
} }
return IRQ_HANDLED; return IRQ_HANDLED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment