[Xenomai-git] Alexis Berlemont : analogy: [pcimio] fix many race conditions in DMA output transfers
Module: xenomai-2.5 Branch: master Commit: 07bae25974ad76d29a427b195c6b7de1c0d30c63 URL: http://git.xenomai.org/?p=xenomai-2.5.git;a=commit;h=07bae25974ad76d29a427b195c6b7de1c0d30c63 Author: Alexis Berlemont alexis.berlem...@gmail.com Date: Mon Mar 1 01:08:28 2010 +0100 analogy: [pcimio] fix many race conditions in DMA output transfers WARNING: Some parts of the driver mio_common cannot be tolerated in a real-time system. For example, the function ni_ao_wait_for_dma_load must be reviewed; it contains two busy waiting loops which can last up to 1 micro-seconds. --- .../analogy/national_instruments/mio_common.c | 98 +++ ksrc/drivers/analogy/national_instruments/mite.c | 17 +++- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/ksrc/drivers/analogy/national_instruments/mio_common.c b/ksrc/drivers/analogy/national_instruments/mio_common.c index db9762a..1a39206 100644 --- a/ksrc/drivers/analogy/national_instruments/mio_common.c +++ b/ksrc/drivers/analogy/national_instruments/mio_common.c @@ -506,17 +506,28 @@ void mite_handle_b_linkc(a4l_subd_t *subd) a4l_unlock_irqrestore(devpriv-mite_channel_lock, flags); } -static int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { static const int timeout = 1; + + a4l_dev_t *dev = subd-dev; + a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; + int i; for (i = 0; i timeout; i++) { + + int buffer_filled; unsigned short b_status; b_status = devpriv-stc_readw(dev, AO_Status_1_Register); - if (b_status AO_FIFO_Half_Full_St) + + buffer_filled = test_bit(A4L_BUF_EOA_NR, buf-evt_flags); + buffer_filled |= (b_status AO_FIFO_Half_Full_St); + + if (buffer_filled) break; + /* If we poll too often, the pci bus activity seems to slow the dma transfer down */ a4l_udelay(10); @@ -569,7 +580,7 @@ static inline int ni_request_cdo_mite_channel(a4l_dev_t *dev) #define ni_sync_ai_dma(x) do { } while (0) #define mite_handle_b_linkc(x) do { } while (0) -static inline int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static inline int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { return -ENOTSUPP; } @@ -714,14 +725,12 @@ static void ni_handle_eos(a4l_subd_t *subd) } static void ni_event(a4l_subd_t * subd) -{ - +{ /* Temporary hack */ a4l_dev_t *dev = subd-dev; a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; - if(test_bit(A4L_BUF_ERROR, buf-evt_flags)) { - + if(test_bit(A4L_BUF_ERROR_NR, buf-evt_flags)) { if (subd-cancel != NULL) subd-cancel(subd); } @@ -939,28 +948,15 @@ static void handle_b_interrupt(a4l_dev_t * dev, a4l_subd_t *subd = a4l_get_subd(dev, NI_AO_SUBDEV); - a4l_info(dev, ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, -b_status, ao_mite_status); - ni_mio_print_status_b(b_status); - -#if (defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE) || \ - defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE_MODULE)) - /* Currently, mite.c requires us to handle LINKC */ - if (ao_mite_status CHSR_LINKC) { - mite_handle_b_linkc(subd); - } + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, + b_status, ao_mite_status); - if (ao_mite_status ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | - CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | - CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { - a4l_info(dev, unknown mite interrupt, ack! (ao_mite_status=%08x)\n, -ao_mite_status); - a4l_buf_evt(subd, A4L_BUF_ERROR); - } -#endif /* CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE */ + ni_mio_print_status_b(b_status); if (b_status == 0x) return; + if (b_status AO_Overrun_St) { a4l_err(dev, ni_mio_common: interrupt: @@ -971,15 +967,38 @@ static void handle_b_interrupt(a4l_dev_t * dev, } if (b_status AO_BC_TC_St) { - a4l_info(dev, -ni_mio_common: interrupt: -AO BC_TC status=0x%04x status2=0x%04x\n, -b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: + AO BC_TC status=0x%04x status2=0x%04x\n, + b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); a4l_buf_evt(subd, A4L_BUF_EOA); } +#if
[Xenomai-git] Alexis Berlemont : analogy: [pcimio] fix many race conditions in DMA output transfers
Module: xenomai-abe Branch: analogy Commit: 07bae25974ad76d29a427b195c6b7de1c0d30c63 URL: http://git.xenomai.org/?p=xenomai-abe.git;a=commit;h=07bae25974ad76d29a427b195c6b7de1c0d30c63 Author: Alexis Berlemont alexis.berlem...@gmail.com Date: Mon Mar 1 01:08:28 2010 +0100 analogy: [pcimio] fix many race conditions in DMA output transfers WARNING: Some parts of the driver mio_common cannot be tolerated in a real-time system. For example, the function ni_ao_wait_for_dma_load must be reviewed; it contains two busy waiting loops which can last up to 1 micro-seconds. --- .../analogy/national_instruments/mio_common.c | 98 +++ ksrc/drivers/analogy/national_instruments/mite.c | 17 +++- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/ksrc/drivers/analogy/national_instruments/mio_common.c b/ksrc/drivers/analogy/national_instruments/mio_common.c index db9762a..1a39206 100644 --- a/ksrc/drivers/analogy/national_instruments/mio_common.c +++ b/ksrc/drivers/analogy/national_instruments/mio_common.c @@ -506,17 +506,28 @@ void mite_handle_b_linkc(a4l_subd_t *subd) a4l_unlock_irqrestore(devpriv-mite_channel_lock, flags); } -static int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { static const int timeout = 1; + + a4l_dev_t *dev = subd-dev; + a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; + int i; for (i = 0; i timeout; i++) { + + int buffer_filled; unsigned short b_status; b_status = devpriv-stc_readw(dev, AO_Status_1_Register); - if (b_status AO_FIFO_Half_Full_St) + + buffer_filled = test_bit(A4L_BUF_EOA_NR, buf-evt_flags); + buffer_filled |= (b_status AO_FIFO_Half_Full_St); + + if (buffer_filled) break; + /* If we poll too often, the pci bus activity seems to slow the dma transfer down */ a4l_udelay(10); @@ -569,7 +580,7 @@ static inline int ni_request_cdo_mite_channel(a4l_dev_t *dev) #define ni_sync_ai_dma(x) do { } while (0) #define mite_handle_b_linkc(x) do { } while (0) -static inline int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static inline int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { return -ENOTSUPP; } @@ -714,14 +725,12 @@ static void ni_handle_eos(a4l_subd_t *subd) } static void ni_event(a4l_subd_t * subd) -{ - +{ /* Temporary hack */ a4l_dev_t *dev = subd-dev; a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; - if(test_bit(A4L_BUF_ERROR, buf-evt_flags)) { - + if(test_bit(A4L_BUF_ERROR_NR, buf-evt_flags)) { if (subd-cancel != NULL) subd-cancel(subd); } @@ -939,28 +948,15 @@ static void handle_b_interrupt(a4l_dev_t * dev, a4l_subd_t *subd = a4l_get_subd(dev, NI_AO_SUBDEV); - a4l_info(dev, ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, -b_status, ao_mite_status); - ni_mio_print_status_b(b_status); - -#if (defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE) || \ - defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE_MODULE)) - /* Currently, mite.c requires us to handle LINKC */ - if (ao_mite_status CHSR_LINKC) { - mite_handle_b_linkc(subd); - } + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, + b_status, ao_mite_status); - if (ao_mite_status ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | - CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | - CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { - a4l_info(dev, unknown mite interrupt, ack! (ao_mite_status=%08x)\n, -ao_mite_status); - a4l_buf_evt(subd, A4L_BUF_ERROR); - } -#endif /* CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE */ + ni_mio_print_status_b(b_status); if (b_status == 0x) return; + if (b_status AO_Overrun_St) { a4l_err(dev, ni_mio_common: interrupt: @@ -971,15 +967,38 @@ static void handle_b_interrupt(a4l_dev_t * dev, } if (b_status AO_BC_TC_St) { - a4l_info(dev, -ni_mio_common: interrupt: -AO BC_TC status=0x%04x status2=0x%04x\n, -b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: + AO BC_TC status=0x%04x status2=0x%04x\n, + b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); a4l_buf_evt(subd, A4L_BUF_EOA); } +#if
[Xenomai-git] Alexis Berlemont : analogy: [pcimio] fix many race conditions in DMA output transfers
Module: xenomai-abe Branch: analogy Commit: 1ab31f83998636f2fc7b9bf1f53d73adfc950ecc URL: http://git.xenomai.org/?p=xenomai-abe.git;a=commit;h=1ab31f83998636f2fc7b9bf1f53d73adfc950ecc Author: Alexis Berlemont alexis.berlem...@gmail.com Date: Mon Mar 1 01:08:28 2010 +0100 analogy: [pcimio] fix many race conditions in DMA output transfers WARNING: Some parts of the driver mio_common cannot be tolerated in a real-time system. For example, the function ni_ao_wait_for_dma_load must be reviewed; it contains two busy waiting loops which can last up to 1 micro-seconds. --- .../analogy/national_instruments/mio_common.c | 98 +++ ksrc/drivers/analogy/national_instruments/mite.c | 17 +++- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/ksrc/drivers/analogy/national_instruments/mio_common.c b/ksrc/drivers/analogy/national_instruments/mio_common.c index db9762a..1a39206 100644 --- a/ksrc/drivers/analogy/national_instruments/mio_common.c +++ b/ksrc/drivers/analogy/national_instruments/mio_common.c @@ -506,17 +506,28 @@ void mite_handle_b_linkc(a4l_subd_t *subd) a4l_unlock_irqrestore(devpriv-mite_channel_lock, flags); } -static int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { static const int timeout = 1; + + a4l_dev_t *dev = subd-dev; + a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; + int i; for (i = 0; i timeout; i++) { + + int buffer_filled; unsigned short b_status; b_status = devpriv-stc_readw(dev, AO_Status_1_Register); - if (b_status AO_FIFO_Half_Full_St) + + buffer_filled = test_bit(A4L_BUF_EOA_NR, buf-evt_flags); + buffer_filled |= (b_status AO_FIFO_Half_Full_St); + + if (buffer_filled) break; + /* If we poll too often, the pci bus activity seems to slow the dma transfer down */ a4l_udelay(10); @@ -569,7 +580,7 @@ static inline int ni_request_cdo_mite_channel(a4l_dev_t *dev) #define ni_sync_ai_dma(x) do { } while (0) #define mite_handle_b_linkc(x) do { } while (0) -static inline int ni_ao_wait_for_dma_load(a4l_dev_t *dev) +static inline int ni_ao_wait_for_dma_load(a4l_subd_t *subd) { return -ENOTSUPP; } @@ -714,14 +725,12 @@ static void ni_handle_eos(a4l_subd_t *subd) } static void ni_event(a4l_subd_t * subd) -{ - +{ /* Temporary hack */ a4l_dev_t *dev = subd-dev; a4l_buf_t *buf = dev-transfer.bufs[subd-idx]; - if(test_bit(A4L_BUF_ERROR, buf-evt_flags)) { - + if(test_bit(A4L_BUF_ERROR_NR, buf-evt_flags)) { if (subd-cancel != NULL) subd-cancel(subd); } @@ -939,28 +948,15 @@ static void handle_b_interrupt(a4l_dev_t * dev, a4l_subd_t *subd = a4l_get_subd(dev, NI_AO_SUBDEV); - a4l_info(dev, ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, -b_status, ao_mite_status); - ni_mio_print_status_b(b_status); - -#if (defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE) || \ - defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE_MODULE)) - /* Currently, mite.c requires us to handle LINKC */ - if (ao_mite_status CHSR_LINKC) { - mite_handle_b_linkc(subd); - } + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n, + b_status, ao_mite_status); - if (ao_mite_status ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | - CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | - CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { - a4l_info(dev, unknown mite interrupt, ack! (ao_mite_status=%08x)\n, -ao_mite_status); - a4l_buf_evt(subd, A4L_BUF_ERROR); - } -#endif /* CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE */ + ni_mio_print_status_b(b_status); if (b_status == 0x) return; + if (b_status AO_Overrun_St) { a4l_err(dev, ni_mio_common: interrupt: @@ -971,15 +967,38 @@ static void handle_b_interrupt(a4l_dev_t * dev, } if (b_status AO_BC_TC_St) { - a4l_info(dev, -ni_mio_common: interrupt: -AO BC_TC status=0x%04x status2=0x%04x\n, -b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); + a4l_dbg(1, drv_dbg, dev, + ni_mio_common: interrupt: + AO BC_TC status=0x%04x status2=0x%04x\n, + b_status, devpriv-stc_readw(dev, AO_Status_2_Register)); a4l_buf_evt(subd, A4L_BUF_EOA); } +#if