staging: comedi: introduce, and use, comedi_spriv_free()

The comedi_subdevice 'private' variable is a void * that is available
for the subdevice to use in manner. It's common in comedi drivers for
the driver to allocate memory for a subdevice and store the pointer
to that memory in the 'private' variable. It's then the responsibility
of the driver to free that memory when the device is detached.

Due to how the attach/detach works in comedi, the drivers need to do
some sanity checking before they can free the allocated memory during
the detach.

Introduce a helper function, comedi_spriv_free(), to handle freeing
the private data allocated for a subdevice. This allows moving all the
sanity checks into the helper function and makes it safe to call
with any context. It also allows removing some of the boilerplate
code in the (*detach) functions.

Remove the subdev_8255_cleanup() export in the 8255 subdevice driver
as well as the addi_watchdog_cleanup() export in the addi_watchdog
driver and use the new helper instead.

The amplc_dio200_common driver uses a number of local helper functions
to free the private data for it's subdevices. Remove those as well and
use the new helper.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
H Hartley Sweeten 2013-04-15 16:41:57 -07:00 committed by Greg Kroah-Hartman
parent f4362867e0
commit 2f69915c72
30 changed files with 50 additions and 154 deletions

View File

@ -348,6 +348,8 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
int comedi_alloc_subdevices(struct comedi_device *, int); int comedi_alloc_subdevices(struct comedi_device *, int);
void comedi_spriv_free(struct comedi_device *, int subdev_num);
int __comedi_request_region(struct comedi_device *, int __comedi_request_region(struct comedi_device *,
unsigned long start, unsigned long len); unsigned long start, unsigned long len);
int comedi_request_region(struct comedi_device *, int comedi_request_region(struct comedi_device *,

View File

@ -86,6 +86,18 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
} }
EXPORT_SYMBOL_GPL(comedi_alloc_subdevices); EXPORT_SYMBOL_GPL(comedi_alloc_subdevices);
void comedi_spriv_free(struct comedi_device *dev, int subdev_num)
{
struct comedi_subdevice *s;
if (dev->subdevices && subdev_num < dev->n_subdevices) {
s = &dev->subdevices[subdev_num];
kfree(s->private);
s->private = NULL;
}
}
EXPORT_SYMBOL_GPL(comedi_spriv_free);
static void cleanup_device(struct comedi_device *dev) static void cleanup_device(struct comedi_device *dev)
{ {
int i; int i;

View File

@ -334,12 +334,6 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
} }
EXPORT_SYMBOL_GPL(subdev_8255_init_irq); EXPORT_SYMBOL_GPL(subdev_8255_init_irq);
void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
{
kfree(s->private);
}
EXPORT_SYMBOL_GPL(subdev_8255_cleanup);
/* /*
Start of the 8255 standalone device Start of the 8255 standalone device
@ -397,7 +391,7 @@ static void dev_8255_detach(struct comedi_device *dev)
spriv = s->private; spriv = s->private;
release_region(spriv->iobase, _8255_SIZE); release_region(spriv->iobase, _8255_SIZE);
} }
subdev_8255_cleanup(dev, s); comedi_spriv_free(dev, i);
} }
} }

View File

@ -32,7 +32,6 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io) (int, int, int, unsigned long), int (*io) (int, int, int, unsigned long),
unsigned long iobase); unsigned long iobase);
void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s);
void subdev_8255_interrupt(struct comedi_device *dev, void subdev_8255_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s); struct comedi_subdevice *s);

View File

@ -241,20 +241,12 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
static void pci_8255_detach(struct comedi_device *dev) static void pci_8255_detach(struct comedi_device *dev)
{ {
const struct pci_8255_boardinfo *board = comedi_board(dev);
struct pci_8255_private *devpriv = dev->private; struct pci_8255_private *devpriv = dev->private;
struct comedi_subdevice *s;
int i; int i;
if (!board || !devpriv) for (i = 0; i < dev->n_subdevices; i++)
return; comedi_spriv_free(dev, i);
if (dev->subdevices) { if (devpriv && devpriv->mmio_base)
for (i = 0; i < board->n_8255; i++) {
s = &dev->subdevices[i];
subdev_8255_cleanup(dev, s);
}
}
if (devpriv->mmio_base)
iounmap(devpriv->mmio_base); iounmap(devpriv->mmio_base);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -203,8 +203,7 @@ static void apci1516_detach(struct comedi_device *dev)
{ {
if (dev->iobase) if (dev->iobase)
apci1516_reset(dev); apci1516_reset(dev);
if (dev->subdevices) comedi_spriv_free(dev, 2);
addi_watchdog_cleanup(&dev->subdevices[2]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -354,8 +354,7 @@ static void apci2032_detach(struct comedi_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if (dev->read_subdev) if (dev->read_subdev)
kfree(dev->read_subdev->private); kfree(dev->read_subdev->private);
if (dev->subdevices) comedi_spriv_free(dev, 1);
addi_watchdog_cleanup(&dev->subdevices[1]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -130,8 +130,7 @@ static void apci2200_detach(struct comedi_device *dev)
{ {
if (dev->iobase) if (dev->iobase)
apci2200_reset(dev); apci2200_reset(dev);
if (dev->subdevices) comedi_spriv_free(dev, 2);
addi_watchdog_cleanup(&dev->subdevices[2]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -150,12 +150,6 @@ int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase)
} }
EXPORT_SYMBOL_GPL(addi_watchdog_init); EXPORT_SYMBOL_GPL(addi_watchdog_init);
void addi_watchdog_cleanup(struct comedi_subdevice *s)
{
kfree(s->private);
}
EXPORT_SYMBOL_GPL(addi_watchdog_cleanup);
static int __init addi_watchdog_module_init(void) static int __init addi_watchdog_module_init(void)
{ {
return 0; return 0;

View File

@ -5,6 +5,5 @@
void addi_watchdog_reset(unsigned long iobase); void addi_watchdog_reset(unsigned long iobase);
int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase); int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase);
void addi_watchdog_cleanup(struct comedi_subdevice *s);
#endif #endif

View File

@ -1180,13 +1180,11 @@ static void pci_dio_detach(struct comedi_device *dev)
if (devpriv->valid) if (devpriv->valid)
pci_dio_reset(dev); pci_dio_reset(dev);
} }
if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) {
for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i];
s = &dev->subdevices[i]; if (s->type == COMEDI_SUBD_DIO)
if (s->type == COMEDI_SUBD_DIO) comedi_spriv_free(dev, i);
subdev_8255_cleanup(dev, s); s->private = NULL; /* some private data is static */
s->private = NULL;
}
} }
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -261,8 +261,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
static void aio_aio12_8_detach(struct comedi_device *dev) static void aio_aio12_8_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) comedi_spriv_free(dev, 2);
subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->iobase) if (dev->iobase)
release_region(dev->iobase, 24); release_region(dev->iobase, 24);
} }

View File

@ -594,17 +594,6 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
return 0; return 0;
} }
/*
* This function cleans up an 'INTERRUPT' subdevice.
*/
static void
dio200_subdev_intr_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_intr *subpriv = s->private;
kfree(subpriv);
}
/* /*
* Interrupt service routine. * Interrupt service routine.
*/ */
@ -937,17 +926,6 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
return 0; return 0;
} }
/*
* This function cleans up an '8254' counter subdevice.
*/
static void
dio200_subdev_8254_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_intr *subpriv = s->private;
kfree(subpriv);
}
/* /*
* This function sets I/O directions for an '8255' DIO subdevice. * This function sets I/O directions for an '8255' DIO subdevice.
*/ */
@ -1064,17 +1042,6 @@ static int dio200_subdev_8255_init(struct comedi_device *dev,
return 0; return 0;
} }
/*
* This function cleans up an '8255' DIO subdevice.
*/
static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_8255 *subpriv = s->private;
kfree(subpriv);
}
/* /*
* Handle 'insn_read' for a timer subdevice. * Handle 'insn_read' for a timer subdevice.
*/ */
@ -1178,15 +1145,6 @@ static int dio200_subdev_timer_init(struct comedi_device *dev,
return 0; return 0;
} }
/*
* This function cleans up a timer subdevice.
*/
static void dio200_subdev_timer_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
/* Nothing to do. */
}
void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val) void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val)
{ {
dio200_write8(dev, DIO200_ENHANCE, val); dio200_write8(dev, DIO200_ENHANCE, val);
@ -1282,20 +1240,13 @@ void amplc_dio200_common_detach(struct comedi_device *dev)
if (dev->subdevices) { if (dev->subdevices) {
layout = dio200_board_layout(thisboard); layout = dio200_board_layout(thisboard);
for (n = 0; n < dev->n_subdevices; n++) { for (n = 0; n < dev->n_subdevices; n++) {
struct comedi_subdevice *s = &dev->subdevices[n];
switch (layout->sdtype[n]) { switch (layout->sdtype[n]) {
case sd_8254: case sd_8254:
dio200_subdev_8254_cleanup(dev, s);
break;
case sd_8255: case sd_8255:
dio200_subdev_8255_cleanup(dev, s);
break;
case sd_intr: case sd_intr:
dio200_subdev_intr_cleanup(dev, s); comedi_spriv_free(dev, n);
break; break;
case sd_timer: case sd_timer:
dio200_subdev_timer_cleanup(dev, s);
break;
default: default:
break; break;
} }

View File

@ -545,8 +545,7 @@ static void pc236_detach(struct comedi_device *dev)
pc236_intr_disable(dev); pc236_intr_disable(dev);
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if (dev->subdevices) comedi_spriv_free(dev, 0);
subdev_8255_cleanup(dev, &dev->subdevices[0]);
if (is_isa_board(thisboard)) { if (is_isa_board(thisboard)) {
if (dev->iobase) if (dev->iobase)
release_region(dev->iobase, PC236_IO_SIZE); release_region(dev->iobase, PC236_IO_SIZE);

View File

@ -2832,11 +2832,9 @@ static int pci230_auto_attach(struct comedi_device *dev,
static void pci230_detach(struct comedi_device *dev) static void pci230_detach(struct comedi_device *dev)
{ {
const struct pci230_board *thisboard = comedi_board(dev);
struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pci_dev *pcidev = comedi_to_pci_dev(dev);
if (dev->subdevices && thisboard->have_dio) comedi_spriv_free(dev, 2);
subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
comedi_pci_disable(dev); comedi_pci_disable(dev);

View File

@ -1608,8 +1608,7 @@ static void cb_pcidas_detach(struct comedi_device *dev)
} }
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if (dev->subdevices) comedi_spriv_free(dev, 2);
subdev_8255_cleanup(dev, &dev->subdevices[2]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -4163,8 +4163,7 @@ static void detach(struct comedi_device *dev)
devpriv->ao_dma_desc_bus_addr); devpriv->ao_dma_desc_bus_addr);
} }
} }
if (dev->subdevices) comedi_spriv_free(dev, 4);
subdev_8255_cleanup(dev, &dev->subdevices[4]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -399,10 +399,8 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
static void cb_pcidda_detach(struct comedi_device *dev) static void cb_pcidda_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) { comedi_spriv_free(dev, 1);
subdev_8255_cleanup(dev, &dev->subdevices[1]); comedi_spriv_free(dev, 2);
subdev_8255_cleanup(dev, &dev->subdevices[2]);
}
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -199,8 +199,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
static void cb_pcimdda_detach(struct comedi_device *dev) static void cb_pcimdda_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) comedi_spriv_free(dev, 1);
subdev_8255_cleanup(dev, &dev->subdevices[1]);
comedi_pci_disable(dev); comedi_pci_disable(dev);
} }

View File

@ -766,8 +766,7 @@ static void daqboard2000_detach(struct comedi_device *dev)
{ {
struct daqboard2000_private *devpriv = dev->private; struct daqboard2000_private *devpriv = dev->private;
if (dev->subdevices) comedi_spriv_free(dev, 2);
subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if (devpriv) { if (devpriv) {

View File

@ -568,8 +568,7 @@ EXPORT_SYMBOL_GPL(das08_common_attach);
void das08_common_detach(struct comedi_device *dev) void das08_common_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) comedi_spriv_free(dev, 4);
subdev_8255_cleanup(dev, &dev->subdevices[4]);
} }
EXPORT_SYMBOL_GPL(das08_common_detach); EXPORT_SYMBOL_GPL(das08_common_detach);

View File

@ -1339,8 +1339,7 @@ static void das16_detach(struct comedi_device *dev)
struct das16_private_struct *devpriv = dev->private; struct das16_private_struct *devpriv = dev->private;
das16_reset(dev); das16_reset(dev);
if (dev->subdevices) comedi_spriv_free(dev, 4);
subdev_8255_cleanup(dev, &dev->subdevices[4]);
if (devpriv) { if (devpriv) {
int i; int i;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {

View File

@ -669,8 +669,7 @@ static int das16m1_attach(struct comedi_device *dev,
static void das16m1_detach(struct comedi_device *dev) static void das16m1_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) comedi_spriv_free(dev, 3);
subdev_8255_cleanup(dev, &dev->subdevices[3]);
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if (dev->iobase) { if (dev->iobase) {

View File

@ -730,6 +730,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
static void ni_65xx_detach(struct comedi_device *dev) static void ni_65xx_detach(struct comedi_device *dev)
{ {
struct ni_65xx_private *devpriv = dev->private; struct ni_65xx_private *devpriv = dev->private;
int i;
if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) { if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
writeb(0x00, writeb(0x00,
@ -738,15 +739,9 @@ static void ni_65xx_detach(struct comedi_device *dev)
} }
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
for (i = 0; i < dev->n_subdevices; ++i)
comedi_spriv_free(dev, i);
if (devpriv) { if (devpriv) {
struct comedi_subdevice *s;
unsigned i;
for (i = 0; i < dev->n_subdevices; ++i) {
s = &dev->subdevices[i];
kfree(s->private);
s->private = NULL;
}
if (devpriv->mite) { if (devpriv->mite) {
mite_unsetup(devpriv->mite); mite_unsetup(devpriv->mite);
mite_free(devpriv->mite); mite_free(devpriv->mite);

View File

@ -767,13 +767,7 @@ static int atmio16d_attach(struct comedi_device *dev,
static void atmio16d_detach(struct comedi_device *dev) static void atmio16d_detach(struct comedi_device *dev)
{ {
const struct atmio16_board_t *board = comedi_board(dev); comedi_spriv_free(dev, 3);
struct comedi_subdevice *s;
if (dev->subdevices && board->has_8255) {
s = &dev->subdevices[3];
subdev_8255_cleanup(dev, s);
}
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
reset_atmio16d(dev); reset_atmio16d(dev);

View File

@ -73,8 +73,7 @@ static int dio24_auto_attach(struct comedi_device *dev,
static void dio24_detach(struct comedi_device *dev) static void dio24_detach(struct comedi_device *dev)
{ {
if (dev->subdevices) comedi_spriv_free(dev, 0);
subdev_8255_cleanup(dev, &dev->subdevices[0]);
comedi_pcmcia_disable(dev); comedi_pcmcia_disable(dev);
} }

View File

@ -1860,14 +1860,10 @@ void labpc_common_detach(struct comedi_device *dev)
{ {
const struct labpc_boardinfo *board = comedi_board(dev); const struct labpc_boardinfo *board = comedi_board(dev);
struct labpc_private *devpriv = dev->private; struct labpc_private *devpriv = dev->private;
struct comedi_subdevice *s;
if (!board) if (!board)
return; return;
if (dev->subdevices) { comedi_spriv_free(dev, 2);
s = &dev->subdevices[2];
subdev_8255_cleanup(dev, s);
}
#ifdef CONFIG_ISA_DMA_API #ifdef CONFIG_ISA_DMA_API
/* only free stuff if it has been allocated by _attach */ /* only free stuff if it has been allocated by _attach */
kfree(devpriv->dma_buffer); kfree(devpriv->dma_buffer);

View File

@ -4068,19 +4068,14 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
static void mio_common_detach(struct comedi_device *dev) static void mio_common_detach(struct comedi_device *dev)
{ {
const struct ni_board_struct *board = comedi_board(dev);
struct ni_private *devpriv = dev->private; struct ni_private *devpriv = dev->private;
struct comedi_subdevice *s;
if (devpriv) { if (devpriv) {
if (devpriv->counter_dev) { if (devpriv->counter_dev) {
ni_gpct_device_destroy(devpriv->counter_dev); ni_gpct_device_destroy(devpriv->counter_dev);
} }
} }
if (dev->subdevices && board->has_8255) { comedi_spriv_free(dev, NI_8255_DIO_SUBDEV);
s = &dev->subdevices[NI_8255_DIO_SUBDEV];
subdev_8255_cleanup(dev, s);
}
} }
static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)

View File

@ -170,13 +170,10 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static void pcl724_detach(struct comedi_device *dev) static void pcl724_detach(struct comedi_device *dev)
{ {
const struct pcl724_board *board = comedi_board(dev); const struct pcl724_board *board = comedi_board(dev);
struct comedi_subdevice *s;
int i; int i;
for (i = 0; i < dev->n_subdevices; i++) { for (i = 0; i < dev->n_subdevices; i++)
s = &dev->subdevices[i]; comedi_spriv_free(dev, i);
subdev_8255_cleanup(dev, s);
}
#ifdef PCL724_IRQ #ifdef PCL724_IRQ
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);

View File

@ -252,15 +252,10 @@ static int pcm3724_attach(struct comedi_device *dev,
static void pcm3724_detach(struct comedi_device *dev) static void pcm3724_detach(struct comedi_device *dev)
{ {
struct comedi_subdevice *s;
int i; int i;
if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++)
for (i = 0; i < dev->n_subdevices; i++) { comedi_spriv_free(dev, i);
s = &dev->subdevices[i];
subdev_8255_cleanup(dev, s);
}
}
if (dev->iobase) if (dev->iobase)
release_region(dev->iobase, PCM3724_SIZE); release_region(dev->iobase, PCM3724_SIZE);
} }