The worst case number of DMA bytes that omap_dma will ask us to transfer is 0xffff * 0xffff * 4 == 0x3fff80004, which is slightly larger than fits into a uint32_t. Move the byte count to uint64_t, and adjust code that passes it around to also use uint64_t.
Signed-off-by: Peter Maydell <[email protected]> --- hw/dma/soc_dma.c | 6 +++++- include/hw/arm/soc_dma.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c index bbcd2bdcd5..1b93aaf565 100644 --- a/hw/dma/soc_dma.c +++ b/hw/dma/soc_dma.c @@ -49,11 +49,15 @@ struct dma_s { struct soc_dma_ch_s ch[]; }; -static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes) +static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, uint64_t delay_bytes) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); struct dma_s *dma = (struct dma_s *) ch->dma; + /* + * Worst case delay bytes is only slightly larger than fits into + * a 32-bit integer, so this won't overflow. + */ timer_mod(ch->timer, now + delay_bytes / dma->channel_freq); } diff --git a/include/hw/arm/soc_dma.h b/include/hw/arm/soc_dma.h index e1d75bb3ba..b5ad9743be 100644 --- a/include/hw/arm/soc_dma.h +++ b/include/hw/arm/soc_dma.h @@ -49,7 +49,7 @@ struct soc_dma_ch_s { int update; /* This should be set by dma->setup_fn(). */ - int bytes; + uint64_t bytes; /* Initialised by the DMA module, call soc_dma_ch_update after writing. */ enum soc_dma_access_type type[2]; hwaddr vaddr[2]; /* Updated by .transfer_fn(). */ -- 2.43.0
