staging: comedi: pcmuio: remove subdevice private data

The subdevice private data is only needed for each 'asic' not for each
subdevice. Since the 'asic' can be calculated easily from the subdevice
we can merge the subdevice private data members directly into the
private data.

This removes the need to kcalloc/free the subdevice private data and
saves a bit of space.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 57a52da..fb0cbf0 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -127,26 +127,17 @@
 	},
 };
 
-struct pcmuio_subdev_private {
-	/* The below is only used for intr subdevices */
-	struct {
-		/*
-		 * subdev-relative channel mask for channels
-		 * we are interested in
-		 */
-		int enabled_mask;
-		int active;
-		int stop_count;
-		int continuous;
-		spinlock_t spinlock;
-	} intr;
+struct pcmuio_asic {
+	spinlock_t pagelock;
+	spinlock_t spinlock;
+	int enabled_mask;
+	int active;
+	int stop_count;
+	int continuous;
 };
 
 struct pcmuio_private {
-	struct {
-		spinlock_t pagelock;
-	} asics[PCMUIO_MAX_ASICS];
-	struct pcmuio_subdev_private *sprivs;
+	struct pcmuio_asic asics[PCMUIO_MAX_ASICS];
 	unsigned int irq2;
 };
 
@@ -154,10 +145,11 @@
 			 int asic, int page, int port)
 {
 	struct pcmuio_private *devpriv = dev->private;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE);
 	unsigned long flags;
 
-	spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags);
+	spin_lock_irqsave(&chip->pagelock, flags);
 	if (page == 0) {
 		/* Port registers are valid for any page */
 		outb(val & 0xff, iobase + PCMUIO_PORT_REG(port + 0));
@@ -169,18 +161,19 @@
 		outb((val >> 8) & 0xff, iobase + PCMUIO_PAGE_REG(1));
 		outb((val >> 16) & 0xff, iobase + PCMUIO_PAGE_REG(2));
 	}
-	spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags);
+	spin_unlock_irqrestore(&chip->pagelock, flags);
 }
 
 static unsigned int pcmuio_read(struct comedi_device *dev,
 				int asic, int page, int port)
 {
 	struct pcmuio_private *devpriv = dev->private;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE);
 	unsigned long flags;
 	unsigned int val;
 
-	spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags);
+	spin_lock_irqsave(&chip->pagelock, flags);
 	if (page == 0) {
 		/* Port registers are valid for any page */
 		val = inb(iobase + PCMUIO_PORT_REG(port + 0));
@@ -192,7 +185,7 @@
 		val |= (inb(iobase + PCMUIO_PAGE_REG(1)) << 8);
 		val |= (inb(iobase + PCMUIO_PAGE_REG(2)) << 16);
 	}
-	spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags);
+	spin_unlock_irqrestore(&chip->pagelock, flags);
 
 	return val;
 }
@@ -276,11 +269,12 @@
 static void pcmuio_stop_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
 	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 
-	subpriv->intr.enabled_mask = 0;
-	subpriv->intr.active = 0;
+	chip->enabled_mask = 0;
+	chip->active = 0;
 	s->async->inttrig = NULL;
 
 	/* disable all intrs for this subdev.. */
@@ -291,7 +285,9 @@
 				      struct comedi_subdevice *s,
 				      unsigned triggered)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
+	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned int len = s->async->cmd.chanlist_len;
 	unsigned oldevents = s->async->events;
 	unsigned int val = 0;
@@ -299,15 +295,15 @@
 	unsigned mytrig;
 	unsigned int i;
 
-	spin_lock_irqsave(&subpriv->intr.spinlock, flags);
+	spin_lock_irqsave(&chip->spinlock, flags);
 
-	if (!subpriv->intr.active)
+	if (!chip->active)
 		goto done;
 
 	mytrig = triggered;
 	mytrig &= ((0x1 << s->n_chan) - 1);
 
-	if (!(mytrig & subpriv->intr.enabled_mask))
+	if (!(mytrig & chip->enabled_mask))
 		goto done;
 
 	for (i = 0; i < len; i++) {
@@ -327,11 +323,11 @@
 	}
 
 	/* Check for end of acquisition. */
-	if (!subpriv->intr.continuous) {
+	if (!chip->continuous) {
 		/* stop_src == TRIG_COUNT */
-		if (subpriv->intr.stop_count > 0) {
-			subpriv->intr.stop_count--;
-			if (subpriv->intr.stop_count == 0) {
+		if (chip->stop_count > 0) {
+			chip->stop_count--;
+			if (chip->stop_count == 0) {
 				s->async->events |= COMEDI_CB_EOA;
 				/* TODO: STOP_ACQUISITION_CALL_HERE!! */
 				pcmuio_stop_intr(dev, s);
@@ -340,7 +336,7 @@
 	}
 
 done:
-	spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	if (oldevents != s->async->events)
 		comedi_event(dev, s);
@@ -385,20 +381,21 @@
 static int pcmuio_start_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
+	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 
-	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
+	if (!chip->continuous && chip->stop_count == 0) {
 		/* An empty acquisition! */
 		s->async->events |= COMEDI_CB_EOA;
-		subpriv->intr.active = 0;
+		chip->active = 0;
 		return 1;
 	} else {
 		struct comedi_cmd *cmd = &s->async->cmd;
-		int asic = s->index / 2;
 		unsigned bits = 0, pol_bits = 0, n;
 
-		subpriv->intr.enabled_mask = 0;
-		subpriv->intr.active = 1;
+		chip->enabled_mask = 0;
+		chip->active = 1;
 		if (cmd->chanlist) {
 			for (n = 0; n < cmd->chanlist_len; n++) {
 				bits |= (1U << CR_CHAN(cmd->chanlist[n]));
@@ -409,7 +406,7 @@
 			}
 		}
 		bits &= ((0x1 << s->n_chan) - 1);
-		subpriv->intr.enabled_mask = bits;
+		chip->enabled_mask = bits;
 
 		/* set pol and enab intrs for this subdev.. */
 		pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0);
@@ -420,13 +417,15 @@
 
 static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
+	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned long flags;
 
-	spin_lock_irqsave(&subpriv->intr.spinlock, flags);
-	if (subpriv->intr.active)
+	spin_lock_irqsave(&chip->spinlock, flags);
+	if (chip->active)
 		pcmuio_stop_intr(dev, s);
-	spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -438,19 +437,21 @@
 pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
 			  unsigned int trignum)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
+	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned long flags;
 	int event = 0;
 
 	if (trignum != 0)
 		return -EINVAL;
 
-	spin_lock_irqsave(&subpriv->intr.spinlock, flags);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	s->async->inttrig = NULL;
-	if (subpriv->intr.active)
+	if (chip->active)
 		event = pcmuio_start_intr(dev, s);
 
-	spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	if (event)
 		comedi_event(dev, s);
@@ -463,24 +464,26 @@
  */
 static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct pcmuio_subdev_private *subpriv = s->private;
+	struct pcmuio_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
+	int asic = s->index / 2;
+	struct pcmuio_asic *chip = &devpriv->asics[asic];
 	unsigned long flags;
 	int event = 0;
 
-	spin_lock_irqsave(&subpriv->intr.spinlock, flags);
-	subpriv->intr.active = 1;
+	spin_lock_irqsave(&chip->spinlock, flags);
+	chip->active = 1;
 
 	/* Set up end of acquisition. */
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		subpriv->intr.continuous = 0;
-		subpriv->intr.stop_count = cmd->stop_arg;
+		chip->continuous = 0;
+		chip->stop_count = cmd->stop_arg;
 		break;
 	default:
 		/* TRIG_NONE */
-		subpriv->intr.continuous = 1;
-		subpriv->intr.stop_count = 0;
+		chip->continuous = 1;
+		chip->stop_count = 0;
 		break;
 	}
 
@@ -494,7 +497,7 @@
 		event = pcmuio_start_intr(dev, s);
 		break;
 	}
-	spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	if (event)
 		comedi_event(dev, s);
@@ -562,7 +565,6 @@
 	const struct pcmuio_board *board = comedi_board(dev);
 	struct comedi_subdevice *s;
 	struct pcmuio_private *devpriv;
-	struct pcmuio_subdev_private *subpriv;
 	int sdev_no, n_subdevs, asic;
 	int ret;
 
@@ -575,8 +577,12 @@
 	if (!devpriv)
 		return -ENOMEM;
 
-	for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic)
-		spin_lock_init(&devpriv->asics[asic].pagelock);
+	for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) {
+		struct pcmuio_asic *chip = &devpriv->asics[asic];
+
+		spin_lock_init(&chip->pagelock);
+		spin_lock_init(&chip->spinlock);
+	}
 
 	pcmuio_reset(dev);
 
@@ -602,9 +608,6 @@
 	}
 
 	n_subdevs = board->num_asics * 2;
-	devpriv->sprivs = kcalloc(n_subdevs, sizeof(*subpriv), GFP_KERNEL);
-	if (!devpriv->sprivs)
-		return -ENOMEM;
 
 	ret = comedi_alloc_subdevices(dev, n_subdevs);
 	if (ret)
@@ -612,8 +615,6 @@
 
 	for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
 		s = &dev->subdevices[sdev_no];
-		subpriv = &devpriv->sprivs[sdev_no];
-		s->private = subpriv;
 		s->maxdata = 1;
 		s->range_table = &range_digital;
 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -635,7 +636,6 @@
 		} else {
 			s->len_chanlist = 1;
 		}
-		spin_lock_init(&subpriv->intr.spinlock);
 	}
 
 	return 0;
@@ -651,8 +651,6 @@
 		/* free the 2nd irq if used, the core will free the 1st one */
 		if (devpriv->irq2 && devpriv->irq2 != dev->irq)
 			free_irq(devpriv->irq2, dev);
-
-		kfree(devpriv->sprivs);
 	}
 	comedi_legacy_detach(dev);
 }