[PATCH] Avoid a possible too early interrupt from the omap mcSPI controller

Jan Kiszka jan.kiszka at siemens.com
Fri Apr 24 19:24:23 CEST 2020


On 24.04.20 13:41, Laurentiu-Cristian Duca via Xenomai wrote:
> In order to avoid a possible too early interrupt
> from the omap mcSPI controller,
> disable interrupts before writing the number of bytes from the SPI message
> that fill up the omap mcSPI controller queue,
> and enable interrupts after that.
> 
> Signed-off-by: Laurentiu-Cristian Duca <laurentiu.duca at gmail.com>
> ---
>   kernel/drivers/spi/spi-omap2-mcspi-rt.c | 28 ++++++++++++++++++++++++-
>   1 file changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/drivers/spi/spi-omap2-mcspi-rt.c b/kernel/drivers/spi/spi-omap2-mcspi-rt.c
> index a7a005b22..03678b991 100644
> --- a/kernel/drivers/spi/spi-omap2-mcspi-rt.c
> +++ b/kernel/drivers/spi/spi-omap2-mcspi-rt.c
> @@ -149,6 +149,7 @@ struct spi_master_omap2_mcspi {
>   	int rx_len;
>   	int fifo_depth;
>   	rtdm_event_t transfer_done;
> +	rtdm_lock_t lock;
>   	unsigned int pin_dir:1;
>   	struct omap2_mcspi_cs cs[OMAP2_MCSPI_CS_N];
>   	/* logging */
> @@ -421,6 +422,26 @@ static void mcspi_wr_fifo(struct spi_master_omap2_mcspi *spim, int cs_id)
>   	}
>   }
>   
> +static void mcspi_wr_fifo_bh(struct spi_master_omap2_mcspi *spim, int cs_id)
> +{
> +	u8 byte;
> +	int i;
> +	rtdm_lockctx_t c;
> +
> +	rtdm_lock_get_irqsave(&spim->lock, c);
> +
> +	for (i = 0; i < spim->fifo_depth; i++) {
> +		if (spim->tx_len <= 0)
> +			byte = 0;
> +		else
> +			byte = spim->tx_buf ? *spim->tx_buf++ : 0;
> +		mcspi_wr_cs_reg(spim, cs_id, OMAP2_MCSPI_TX0, byte);
> +		spim->tx_len--;
> +	}
> +
> +	rtdm_lock_put_irqrestore(&spim->lock, c);
> +}
> +
>   static int omap2_mcspi_interrupt(rtdm_irq_t *irqh)
>   {
>   	struct spi_master_omap2_mcspi *spim;
> @@ -428,6 +449,8 @@ static int omap2_mcspi_interrupt(rtdm_irq_t *irqh)
>   	int i, cs_id = 0;
>   
>   	spim = rtdm_irq_get_arg(irqh, struct spi_master_omap2_mcspi);
> +	rtdm_lock_get(&spim->lock);
> +
>   	for (i = 0; i < OMAP2_MCSPI_CS_N; i++)
>   		if (spim->cs[i].chosen) {
>   			cs_id = i;
> @@ -459,6 +482,8 @@ static int omap2_mcspi_interrupt(rtdm_irq_t *irqh)
>   		rtdm_event_signal(&spim->transfer_done);
>   	}
>   
> +	rtdm_lock_put(&spim->lock);
> +
>   	return RTDM_IRQ_HANDLED;
>   }
>   
> @@ -572,7 +597,7 @@ static int do_transfer_irq_bh(struct rtdm_spi_remote_slave *slave)
>   	mcspi_wr_reg(spim, OMAP2_MCSPI_IRQENABLE, l);
>   
>   	/* TX_EMPTY will be raised only after data is transfered */
> -	mcspi_wr_fifo(spim, slave->chip_select);
> +	mcspi_wr_fifo_bh(spim, slave->chip_select);
>   
>   	/* wait for transfer completion */
>   	ret = rtdm_event_wait(&spim->transfer_done);
> @@ -905,6 +930,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
>   
>   	spim = container_of(master, struct spi_master_omap2_mcspi, master);
>   	rtdm_event_init(&spim->transfer_done, 0);
> +	rtdm_lock_init(&spim->lock);
>   
>   	spim->pin_dir = pin_dir;
>   	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> 

Thanks, applied.

Did you see the issue in reality or did you identify it as "can 
potentially happen"?

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux



More information about the Xenomai mailing list