diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c index e9a437bcc0b2f..2d8577bce2f48 100644 --- a/drivers/misc/rp1-pio.c +++ b/drivers/misc/rp1-pio.c @@ -618,6 +618,7 @@ static int rp1_pio_sm_config_xfer_internal(struct rp1_pio_client *client, uint s struct dma_info *dma = NULL; uint32_t dma_mask; char chan_name[4]; + bool reconfigure = false; int ret = 0; if (sm >= RP1_PIO_SMS_COUNT || dir >= RP1_PIO_DIR_COUNT) @@ -633,7 +634,7 @@ static int rp1_pio_sm_config_xfer_internal(struct rp1_pio_client *client, uint s if (!(pio->claimed_dmas & dma_mask & ~client->claimed_dmas)) { dma = &pio->dma_configs[sm][dir]; if (client->claimed_dmas & dma_mask) - rp1_pio_sm_dma_free(dev, dma); + reconfigure = true; pio->claimed_dmas |= dma_mask; client->claimed_dmas |= dma_mask; } @@ -641,6 +642,10 @@ static int rp1_pio_sm_config_xfer_internal(struct rp1_pio_client *client, uint s if (!dma) return -EBUSY; + /* dma_release_channel() sleeps, so free the old channel outside the lock. */ + if (reconfigure) + rp1_pio_sm_dma_free(dev, dma); + dma->buf_size = buf_size; /* Round up the allocations */ buf_size = ROUND_UP(buf_size, PAGE_SIZE);