Commit 588ba6dc authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: drivers: let core handle freeing s->private



Introduce a new subdevice runflags, SRF_FREE_SPRIV, and a new helper
function, comedi_set_spriv(), that the drivers can use to set the
comedi_subdevice private data pointer. The helper function will also
set SRF_FREE_SPRIV to allow the comedi core to automatically free the
subdevice private data during the cleanup_device() stage of the detach.

Currently s->private is only allocated by the 8255, addi_watchdog,
amplc_dio200_common, and ni_65xx drivers. All users of those drivers
can then have the comedi_spriv_free() calls removed and in many cases
the (*detach) can then simply be the appropriate comedi core provided
function.

The ni_65xx driver uses a helper function, ni_65xx_alloc_subdevice_private(),
to allocate the private data. Refactor the function to return an errno
or call comedi_set_spriv() instead of returning a pointer to the private
data and requiring the caller to handle it.

Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cadf87a0
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -531,6 +531,21 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
	return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true;
}

/**
 * comedi_set_spriv() - Set the subdevice private data pointer.
 * @s: comedi_subdevice struct
 * @data: pointer to the private data
 *
 * This also sets the subdevice runflags to allow the core to automatically
 * free the private data during the detach.
 */
void comedi_set_spriv(struct comedi_subdevice *s, void *data)
{
	s->private = data;
	comedi_set_subdevice_runflags(s, ~0, SRF_FREE_SPRIV);
}
EXPORT_SYMBOL_GPL(comedi_set_spriv);

/*
   This function restores a subdevice to an idle state.
 */
+3 −3
Original line number Diff line number Diff line
@@ -265,10 +265,12 @@ enum subdevice_runflags {
	/* indicates an COMEDI_CB_ERROR event has occurred since the last
	 * command was started */
	SRF_ERROR = 0x00000004,
	SRF_RUNNING = 0x08000000
	SRF_RUNNING = 0x08000000,
	SRF_FREE_SPRIV = 0x80000000,	/* free s->private on detach */
};

bool comedi_is_subdevice_running(struct comedi_subdevice *s);
void comedi_set_spriv(struct comedi_subdevice *s, void *data);

int comedi_check_chanlist(struct comedi_subdevice *s,
			  int n,
@@ -356,8 +358,6 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,

int comedi_alloc_subdevices(struct comedi_device *, int);

void comedi_spriv_free(struct comedi_device *, int subdev_num);

int comedi_load_firmware(struct comedi_device *, struct device *,
			 const char *name,
			 int (*cb)(struct comedi_device *,
+2 −12
Original line number Diff line number Diff line
@@ -83,18 +83,6 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_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)
{
	int i;
@@ -103,6 +91,8 @@ static void cleanup_device(struct comedi_device *dev)
	if (dev->subdevices) {
		for (i = 0; i < dev->n_subdevices; i++) {
			s = &dev->subdevices[i];
			if (s->runflags & SRF_FREE_SPRIV)
				kfree(s->private);
			comedi_free_subdevice_minor(s);
			if (s->async) {
				comedi_buf_alloc(dev, s, 0);
+1 −3
Original line number Diff line number Diff line
@@ -288,12 +288,11 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
	if (!spriv)
		return -ENOMEM;
	comedi_set_spriv(s, spriv);

	spriv->iobase	= iobase;
	spriv->io	= io ? io : subdev_8255_io;

	s->private	= spriv;

	s->type		= COMEDI_SUBD_DIO;
	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
	s->n_chan	= 24;
@@ -386,7 +385,6 @@ static void dev_8255_detach(struct comedi_device *dev)
			spriv = s->private;
			release_region(spriv->iobase, _8255_SIZE);
		}
		comedi_spriv_free(dev, i);
	}
}

+0 −3
Original line number Diff line number Diff line
@@ -238,10 +238,7 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
static void pci_8255_detach(struct comedi_device *dev)
{
	struct pci_8255_private *devpriv = dev->private;
	int i;

	for (i = 0; i < dev->n_subdevices; i++)
		comedi_spriv_free(dev, i);
	if (devpriv && devpriv->mmio_base)
		iounmap(devpriv->mmio_base);
	comedi_pci_disable(dev);
Loading