Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

staging: comedi: pcmuio: refactor interrupt_pcmuio()



Refactor this function into two new functions in order to reduce the indent
levels and clean up the ugly line breaks that, unsuccessfully, try to keep
the lines < 80 chars.

The first function handles the irq for a specific asic.

The second function handles the irq for a specific subdevice that is
associated with the asic.

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 8099a984
Loading
Loading
Loading
Loading
+116 −139
Original line number Diff line number Diff line
@@ -447,121 +447,44 @@ static void pcmuio_stop_intr(struct comedi_device *dev,
	}
}

static irqreturn_t interrupt_pcmuio(int irq, void *d)
static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
				      struct comedi_subdevice *s,
				      unsigned triggered)
{
	struct comedi_device *dev = (struct comedi_device *)d;
	struct pcmuio_private *devpriv = dev->private;
	struct pcmuio_subdev_private *subpriv;
	int asic, got1 = 0;
	int i;

	for (asic = 0; asic < MAX_ASICS; ++asic) {
		if (irq == devpriv->asics[asic].irq) {
	struct pcmuio_subdev_private *subpriv = s->private;
	unsigned int len = s->async->cmd.chanlist_len;
	unsigned oldevents = s->async->events;
	unsigned int val = 0;
	unsigned long flags;
			unsigned triggered = 0;
			unsigned long iobase = devpriv->asics[asic].iobase;
			/* it is an interrupt for ASIC #asic */
			unsigned char int_pend;
	unsigned mytrig;
	unsigned int i;

			spin_lock_irqsave(&devpriv->asics[asic].spinlock,
					  flags);
	spin_lock_irqsave(&subpriv->intr.spinlock, flags);

			int_pend = inb(iobase + REG_INT_PENDING) & 0x07;
	if (!subpriv->intr.active)
		goto done;

			if (int_pend) {
				int port;
				for (port = 0; port < INTR_PORTS_PER_ASIC;
				     ++port) {
					if (int_pend & (0x1 << port)) {
						unsigned char
						    io_lines_with_edges = 0;
						switch_page(dev, asic,
							    PAGE_INT_ID);
						io_lines_with_edges =
						    inb(iobase +
							REG_INT_ID0 + port);

						if (io_lines_with_edges)
							/* clear pending interrupt */
							outb(0, iobase +
							     REG_INT_ID0 +
							     port);
	mytrig = triggered >> subpriv->intr.asic_chan;
	mytrig &= ((0x1 << subpriv->intr.num_asic_chans) - 1);
	mytrig <<= subpriv->intr.first_chan;

						triggered |=
						    io_lines_with_edges <<
						    port * 8;
					}
				}
	if (!(mytrig & subpriv->intr.enabled_mask))
		goto done;

				++got1;
	for (i = 0; i < len; i++) {
		unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]);
		if (mytrig & (1U << chan))
			val |= (1U << i);
	}

			spin_unlock_irqrestore(&devpriv->asics[asic].spinlock,
					       flags);

			if (triggered) {
				struct comedi_subdevice *s;
				/* TODO here: dispatch io lines to subdevs with commands.. */
				printk
				    ("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n",
				     irq, asic, triggered);
				for (i = 0; i < dev->n_subdevices; i++) {
					s = &dev->subdevices[i];
					subpriv = s->private;
					if (subpriv->intr.asic == asic) {	/* this is an interrupt subdev, and it matches this asic! */
						unsigned long flags;
						unsigned oldevents;

						spin_lock_irqsave(&subpriv->
								  intr.spinlock,
								  flags);

						oldevents = s->async->events;

						if (subpriv->intr.active) {
							unsigned mytrig =
							    ((triggered >>
							      subpriv->intr.asic_chan)
							     &
							     ((0x1 << subpriv->
							       intr.
							       num_asic_chans) -
							      1)) << subpriv->
							    intr.first_chan;
							if (mytrig &
							    subpriv->intr.enabled_mask)
							{
								unsigned int val
								    = 0;
								unsigned int n,
								    ch, len;

								len =
								    s->
								    async->cmd.chanlist_len;
								for (n = 0;
								     n < len;
								     n++) {
									ch = CR_CHAN(s->async->cmd.chanlist[n]);
									if (mytrig & (1U << ch)) {
										val |= (1U << n);
									}
								}
	/* Write the scan to the buffer. */
								if (comedi_buf_put(s->async, ((short *)&val)[0])
								    &&
								    comedi_buf_put
								    (s->async,
								     ((short *)
								      &val)[1]))
								{
	if (comedi_buf_put(s->async, ((short *)&val)[0]) &&
	    comedi_buf_put(s->async, ((short *)&val)[1])) {
		s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
	} else {
		/* Overflow! Stop acquisition!! */
		/* TODO: STOP_ACQUISITION_CALL_HERE!! */
									pcmuio_stop_intr
									    (dev,
									     s);
		pcmuio_stop_intr(dev, s);
	}

	/* Check for end of acquisition. */
@@ -572,29 +495,83 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
			if (subpriv->intr.stop_count == 0) {
				s->async->events |= COMEDI_CB_EOA;
				/* TODO: STOP_ACQUISITION_CALL_HERE!! */
											pcmuio_stop_intr
											    (dev,
											     s);
										}
									}
				pcmuio_stop_intr(dev, s);
			}
		}
	}

						spin_unlock_irqrestore
						    (&subpriv->intr.spinlock,
						     flags);
done:
	spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);

						if (oldevents !=
						    s->async->events) {
	if (oldevents != s->async->events)
		comedi_event(dev, s);
}

static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic)
{
	struct pcmuio_private *devpriv = dev->private;
	struct pcmuio_subdev_private *subpriv;
	unsigned long iobase = devpriv->asics[asic].iobase;
	unsigned triggered = 0;
	int got1 = 0;
	unsigned long flags;
	unsigned char int_pend;
	int i;

	spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags);

	int_pend = inb(iobase + REG_INT_PENDING) & 0x07;
	if (int_pend) {
		for (i = 0; i < INTR_PORTS_PER_ASIC; ++i) {
			if (int_pend & (0x1 << i)) {
				unsigned char val;

				switch_page(dev, asic, PAGE_INT_ID);
				val = inb(iobase + REG_INT_ID0 + i);
				if (val)
					/* clear pending interrupt */
					outb(0, iobase + REG_INT_ID0 + i);

					triggered |= (val << (i * 8));
			}
		}

		++got1;
	}

	spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, flags);

	if (triggered) {
		struct comedi_subdevice *s;
		/* TODO here: dispatch io lines to subdevs with commands.. */
		for (i = 0; i < dev->n_subdevices; i++) {
			s = &dev->subdevices[i];
			subpriv = s->private;
			if (subpriv->intr.asic == asic) {
				/*
				 * This is an interrupt subdev, and it
				 * matches this asic!
				 */
				pcmuio_handle_intr_subdev(dev, s,
							  triggered);
			}
		}
	}
	return got1;
}

static irqreturn_t interrupt_pcmuio(int irq, void *d)
{
	struct comedi_device *dev = d;
	struct pcmuio_private *devpriv = dev->private;
	int got1 = 0;
	int asic;

	for (asic = 0; asic < MAX_ASICS; ++asic) {
		if (irq == devpriv->asics[asic].irq) {
			/* it is an interrupt for ASIC #asic */
			if (pcmuio_handle_asic_interrupt(dev, asic))
				got1++;
		}
	}
	if (!got1)