Skip to content

Commit 4e83313

Browse files
Jyothi Kumar Seerapuvinodkoul
authored andcommitted
dmaengine: qcom: gpi: Add GPI Block event interrupt support
GSI hardware generates an interrupt for each transfer completion. For multiple messages within a single transfer, this results in N interrupts for N messages, leading to significant software interrupt latency. To mitigate this latency, utilize Block Event Interrupt (BEI) mechanism. Enabling BEI instructs the GSI hardware to prevent interrupt generation and BEI is disabled when an interrupt is necessary. Large I2C transfer can be divided into chunks of messages internally. Interrupts are not expected for the messages for which BEI bit set, only the last message triggers an interrupt, indicating the completion of N messages. This BEI mechanism enhances overall transfer efficiency. Signed-off-by: Jyothi Kumar Seerapu <quic_jseerapu@quicinc.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent f80ea85 commit 4e83313

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

drivers/dma/qcom/gpi.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,8 @@ gpi_peripheral_config(struct dma_chan *chan, struct dma_slave_config *config)
16191619
}
16201620

16211621
static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
1622-
struct scatterlist *sgl, enum dma_transfer_direction direction)
1622+
struct scatterlist *sgl, enum dma_transfer_direction direction,
1623+
unsigned long flags)
16231624
{
16241625
struct gpi_i2c_config *i2c = chan->config;
16251626
struct device *dev = chan->gpii->gpi_dev->dev;
@@ -1684,6 +1685,9 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
16841685

16851686
tre->dword[3] = u32_encode_bits(TRE_TYPE_DMA, TRE_FLAGS_TYPE);
16861687
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOT);
1688+
1689+
if (!(flags & DMA_PREP_INTERRUPT))
1690+
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI);
16871691
}
16881692

16891693
for (i = 0; i < tre_idx; i++)
@@ -1827,6 +1831,9 @@ gpi_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
18271831
return NULL;
18281832
}
18291833

1834+
if (!(flags & DMA_PREP_INTERRUPT) && (nr - nr_tre < 2))
1835+
return NULL;
1836+
18301837
gpi_desc = kzalloc(sizeof(*gpi_desc), GFP_NOWAIT);
18311838
if (!gpi_desc)
18321839
return NULL;
@@ -1835,7 +1842,7 @@ gpi_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
18351842
if (gchan->protocol == QCOM_GPI_SPI) {
18361843
i = gpi_create_spi_tre(gchan, gpi_desc, sgl, direction);
18371844
} else if (gchan->protocol == QCOM_GPI_I2C) {
1838-
i = gpi_create_i2c_tre(gchan, gpi_desc, sgl, direction);
1845+
i = gpi_create_i2c_tre(gchan, gpi_desc, sgl, direction, flags);
18391846
} else {
18401847
dev_err(dev, "invalid peripheral: %d\n", gchan->protocol);
18411848
kfree(gpi_desc);

0 commit comments

Comments
 (0)