Currently the dma buffers are freed during the detach of the driver using the function s626_close_dma_b(). The buffers are also freed while the interrupt handler is still attached. This could result in a race condition. Refactor the code so that the buffers are freed after the interrupt handler is released and the PCI device is disabled. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/drivers/s626.c | 44 +++++++++++++++-------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 080608a..304be83 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2457,26 +2457,6 @@ static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image) s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE); } -static void s626_close_dma_b(struct comedi_device *dev, - struct s626_buffer_dma *pdma, size_t bsize) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - void *vbptr; - dma_addr_t vpptr; - - if (pdma == NULL) - return; - - /* find the matching allocation from the board struct */ - vbptr = pdma->logical_base; - vpptr = pdma->physical_base; - if (vbptr) { - pci_free_consistent(pcidev, bsize, vbptr, vpptr); - pdma->logical_base = NULL; - pdma->physical_base = 0; - } -} - static void s626_counters_init(struct comedi_device *dev) { int chan; @@ -2527,6 +2507,24 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) return 0; } +static void s626_free_dma_buffers(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct s626_private *devpriv = dev->private; + + if (!devpriv) + return; + + if (devpriv->rps_buf.logical_base) + pci_free_consistent(pcidev, S626_DMABUF_SIZE, + devpriv->rps_buf.logical_base, + devpriv->rps_buf.physical_base); + if (devpriv->ana_buf.logical_base) + pci_free_consistent(pcidev, S626_DMABUF_SIZE, + devpriv->ana_buf.logical_base, + devpriv->ana_buf.physical_base); +} + static int s626_initialize(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; @@ -2923,11 +2921,6 @@ static void s626_detach(struct comedi_device *dev) /* Close all interfaces on 7146 device */ writel(S626_MC1_SHUTDOWN, dev->mmio + S626_P_MC1); writel(S626_ACON1_BASE, dev->mmio + S626_P_ACON1); - - s626_close_dma_b(dev, &devpriv->rps_buf, - S626_DMABUF_SIZE); - s626_close_dma_b(dev, &devpriv->ana_buf, - S626_DMABUF_SIZE); } if (dev->irq) @@ -2936,6 +2929,7 @@ static void s626_detach(struct comedi_device *dev) iounmap(dev->mmio); } comedi_pci_disable(dev); + s626_free_dma_buffers(dev); } static struct comedi_driver s626_driver = { -- 2.0.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel