Skip to content

Commit dd81d82

Browse files
slongerbeampH5
authored andcommitted
gpu: ipu-v3: image-convert: Wait for all EOFs before completing a tile
Use a bit-mask of EOF irqs to determine when all required idmac channel EOFs have been received for a tile conversion, and only do tile completion processing after all EOFs have been received. Otherwise it was found that a conversion would stall after the completion of a tile and the start of the next tile, because the input/read idmac channel had not completed and entered idle state, thus locking up the channel when attempting to re-start it for the next tile. Fixes: 0537db8 ("gpu: ipu-v3: image-convert: reconfigure IC per tile") Signed-off-by: Steve Longerbeam <[email protected]> Signed-off-by: Philipp Zabel <[email protected]>
1 parent 0f6245f commit dd81d82

File tree

1 file changed

+82
-27
lines changed

1 file changed

+82
-27
lines changed

drivers/gpu/ipu-v3/ipu-image-convert.c

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ struct ipu_image_convert_ctx;
137137
struct ipu_image_convert_chan;
138138
struct ipu_image_convert_priv;
139139

140+
enum eof_irq_mask {
141+
EOF_IRQ_IN = BIT(0),
142+
EOF_IRQ_ROT_IN = BIT(1),
143+
EOF_IRQ_OUT = BIT(2),
144+
EOF_IRQ_ROT_OUT = BIT(3),
145+
};
146+
147+
#define EOF_IRQ_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT)
148+
#define EOF_IRQ_ROT_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT | \
149+
EOF_IRQ_ROT_IN | EOF_IRQ_ROT_OUT)
150+
140151
struct ipu_image_convert_ctx {
141152
struct ipu_image_convert_chan *chan;
142153

@@ -173,6 +184,9 @@ struct ipu_image_convert_ctx {
173184
/* where to place converted tile in dest image */
174185
unsigned int out_tile_map[MAX_TILES];
175186

187+
/* mask of completed EOF irqs at every tile conversion */
188+
enum eof_irq_mask eof_mask;
189+
176190
struct list_head list;
177191
};
178192

@@ -189,6 +203,8 @@ struct ipu_image_convert_chan {
189203
struct ipuv3_channel *rotation_out_chan;
190204

191205
/* the IPU end-of-frame irqs */
206+
int in_eof_irq;
207+
int rot_in_eof_irq;
192208
int out_eof_irq;
193209
int rot_out_eof_irq;
194210

@@ -1380,6 +1396,9 @@ static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
13801396
dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
13811397
__func__, chan->ic_task, ctx, run, tile, dst_tile);
13821398

1399+
/* clear EOF irq mask */
1400+
ctx->eof_mask = 0;
1401+
13831402
if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
13841403
/* swap width/height for resizer */
13851404
dest_width = d_image->tile[dst_tile].height;
@@ -1615,7 +1634,7 @@ static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
16151634
}
16161635

16171636
/* hold irqlock when calling */
1618-
static irqreturn_t do_irq(struct ipu_image_convert_run *run)
1637+
static irqreturn_t do_tile_complete(struct ipu_image_convert_run *run)
16191638
{
16201639
struct ipu_image_convert_ctx *ctx = run->ctx;
16211640
struct ipu_image_convert_chan *chan = ctx->chan;
@@ -1700,6 +1719,7 @@ static irqreturn_t do_irq(struct ipu_image_convert_run *run)
17001719
ctx->cur_buf_num ^= 1;
17011720
}
17021721

1722+
ctx->eof_mask = 0; /* clear EOF irq mask for next tile */
17031723
ctx->next_tile++;
17041724
return IRQ_HANDLED;
17051725
done:
@@ -1715,8 +1735,9 @@ static irqreturn_t eof_irq(int irq, void *data)
17151735
struct ipu_image_convert_priv *priv = chan->priv;
17161736
struct ipu_image_convert_ctx *ctx;
17171737
struct ipu_image_convert_run *run;
1738+
irqreturn_t ret = IRQ_HANDLED;
1739+
bool tile_complete = false;
17181740
unsigned long flags;
1719-
irqreturn_t ret;
17201741

17211742
spin_lock_irqsave(&chan->irqlock, flags);
17221743

@@ -1729,27 +1750,33 @@ static irqreturn_t eof_irq(int irq, void *data)
17291750

17301751
ctx = run->ctx;
17311752

1732-
if (irq == chan->out_eof_irq) {
1733-
if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
1734-
/* this is a rotation op, just ignore */
1735-
ret = IRQ_HANDLED;
1736-
goto out;
1737-
}
1738-
} else if (irq == chan->rot_out_eof_irq) {
1753+
if (irq == chan->in_eof_irq) {
1754+
ctx->eof_mask |= EOF_IRQ_IN;
1755+
} else if (irq == chan->out_eof_irq) {
1756+
ctx->eof_mask |= EOF_IRQ_OUT;
1757+
} else if (irq == chan->rot_in_eof_irq ||
1758+
irq == chan->rot_out_eof_irq) {
17391759
if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
17401760
/* this was NOT a rotation op, shouldn't happen */
17411761
dev_err(priv->ipu->dev,
17421762
"Unexpected rotation interrupt\n");
1743-
ret = IRQ_HANDLED;
17441763
goto out;
17451764
}
1765+
ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ?
1766+
EOF_IRQ_ROT_IN : EOF_IRQ_ROT_OUT;
17461767
} else {
17471768
dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq);
17481769
ret = IRQ_NONE;
17491770
goto out;
17501771
}
17511772

1752-
ret = do_irq(run);
1773+
if (ipu_rot_mode_is_irt(ctx->rot_mode))
1774+
tile_complete = (ctx->eof_mask == EOF_IRQ_ROT_COMPLETE);
1775+
else
1776+
tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE);
1777+
1778+
if (tile_complete)
1779+
ret = do_tile_complete(run);
17531780
out:
17541781
spin_unlock_irqrestore(&chan->irqlock, flags);
17551782
return ret;
@@ -1783,6 +1810,10 @@ static void force_abort(struct ipu_image_convert_ctx *ctx)
17831810

17841811
static void release_ipu_resources(struct ipu_image_convert_chan *chan)
17851812
{
1813+
if (chan->in_eof_irq >= 0)
1814+
free_irq(chan->in_eof_irq, chan);
1815+
if (chan->rot_in_eof_irq >= 0)
1816+
free_irq(chan->rot_in_eof_irq, chan);
17861817
if (chan->out_eof_irq >= 0)
17871818
free_irq(chan->out_eof_irq, chan);
17881819
if (chan->rot_out_eof_irq >= 0)
@@ -1801,7 +1832,27 @@ static void release_ipu_resources(struct ipu_image_convert_chan *chan)
18011832

18021833
chan->in_chan = chan->out_chan = chan->rotation_in_chan =
18031834
chan->rotation_out_chan = NULL;
1804-
chan->out_eof_irq = chan->rot_out_eof_irq = -1;
1835+
chan->in_eof_irq = -1;
1836+
chan->rot_in_eof_irq = -1;
1837+
chan->out_eof_irq = -1;
1838+
chan->rot_out_eof_irq = -1;
1839+
}
1840+
1841+
static int get_eof_irq(struct ipu_image_convert_chan *chan,
1842+
struct ipuv3_channel *channel)
1843+
{
1844+
struct ipu_image_convert_priv *priv = chan->priv;
1845+
int ret, irq;
1846+
1847+
irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF);
1848+
1849+
ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan);
1850+
if (ret < 0) {
1851+
dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq);
1852+
return ret;
1853+
}
1854+
1855+
return irq;
18051856
}
18061857

18071858
static int get_ipu_resources(struct ipu_image_convert_chan *chan)
@@ -1837,31 +1888,33 @@ static int get_ipu_resources(struct ipu_image_convert_chan *chan)
18371888
}
18381889

18391890
/* acquire the EOF interrupts */
1840-
chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
1841-
chan->out_chan,
1842-
IPU_IRQ_EOF);
1891+
ret = get_eof_irq(chan, chan->in_chan);
1892+
if (ret < 0) {
1893+
chan->in_eof_irq = -1;
1894+
goto err;
1895+
}
1896+
chan->in_eof_irq = ret;
18431897

1844-
ret = request_threaded_irq(chan->out_eof_irq, eof_irq, do_bh,
1845-
0, "ipu-ic", chan);
1898+
ret = get_eof_irq(chan, chan->rotation_in_chan);
18461899
if (ret < 0) {
1847-
dev_err(priv->ipu->dev, "could not acquire irq %d\n",
1848-
chan->out_eof_irq);
1849-
chan->out_eof_irq = -1;
1900+
chan->rot_in_eof_irq = -1;
18501901
goto err;
18511902
}
1903+
chan->rot_in_eof_irq = ret;
18521904

1853-
chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
1854-
chan->rotation_out_chan,
1855-
IPU_IRQ_EOF);
1905+
ret = get_eof_irq(chan, chan->out_chan);
1906+
if (ret < 0) {
1907+
chan->out_eof_irq = -1;
1908+
goto err;
1909+
}
1910+
chan->out_eof_irq = ret;
18561911

1857-
ret = request_threaded_irq(chan->rot_out_eof_irq, eof_irq, do_bh,
1858-
0, "ipu-ic", chan);
1912+
ret = get_eof_irq(chan, chan->rotation_out_chan);
18591913
if (ret < 0) {
1860-
dev_err(priv->ipu->dev, "could not acquire irq %d\n",
1861-
chan->rot_out_eof_irq);
18621914
chan->rot_out_eof_irq = -1;
18631915
goto err;
18641916
}
1917+
chan->rot_out_eof_irq = ret;
18651918

18661919
return 0;
18671920
err:
@@ -2440,6 +2493,8 @@ int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
24402493
chan->ic_task = i;
24412494
chan->priv = priv;
24422495
chan->dma_ch = &image_convert_dma_chan[i];
2496+
chan->in_eof_irq = -1;
2497+
chan->rot_in_eof_irq = -1;
24432498
chan->out_eof_irq = -1;
24442499
chan->rot_out_eof_irq = -1;
24452500

0 commit comments

Comments
 (0)