static irqreturn_t ite_cir_isr(int irq, void *data)
{
	struct ite_dev *dev = data;
	unsigned long flags;
	irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
	u8 rx_buf[ITE_RX_FIFO_LEN];
	int rx_bytes;
	int iflags;

	ite_dbg_verbose("%s firing", __func__);

	
	spin_lock_irqsave(&dev->lock, flags);

	
	iflags = dev->params.get_irq_causes(dev);

	
	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
		
		rx_bytes =
			dev->params.get_rx_bytes(dev, rx_buf,
					     ITE_RX_FIFO_LEN);

		if (rx_bytes > 0) {
			spin_unlock_irqrestore(&dev->
									 lock,
									 flags);

			
			ite_decode_bytes(dev, rx_buf,
								   rx_bytes);

			
			spin_lock_irqsave(&dev->lock,
								    flags);

			
			ret = IRQ_RETVAL(IRQ_HANDLED);
		}
	} else if (iflags & ITE_IRQ_TX_FIFO) {
		
		ite_dbg_verbose("got interrupt for TX FIFO");

		
		wake_up_interruptible(&dev->tx_queue);

		
		ret = IRQ_RETVAL(IRQ_HANDLED);
	}

	
	spin_unlock_irqrestore(&dev->lock, flags);

	ite_dbg_verbose("%s done returning %d", __func__, (int)ret);

	return ret;
}
Beispiel #2
0
/* interrupt service routine for incoming and outgoing CIR data */
static irqreturn_t ite_cir_isr(int irq, void *data)
{
	struct ite_dev *dev = data;
	unsigned long flags;
	irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
	u8 rx_buf[ITE_RX_FIFO_LEN];
	int rx_bytes;
	int iflags;

	ite_dbg_verbose("%s firing", __func__);

	/* grab the spinlock */
	spin_lock_irqsave(&dev->lock, flags);

	/* read the interrupt flags */
	iflags = dev->params.get_irq_causes(dev);

	/* check for the receive interrupt */
	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
		/* read the FIFO bytes */
		rx_bytes =
			dev->params.get_rx_bytes(dev, rx_buf,
					     ITE_RX_FIFO_LEN);

		if (rx_bytes > 0) {
			/* drop the spinlock, since the ir-core layer
			 * may call us back again through
			 * ite_s_idle() */
			spin_unlock_irqrestore(&dev->
									 lock,
									 flags);

			/* decode the data we've just received */
			ite_decode_bytes(dev, rx_buf,
								   rx_bytes);

			/* reacquire the spinlock */
			spin_lock_irqsave(&dev->lock,
								    flags);

			/* mark the interrupt as serviced */
			ret = IRQ_RETVAL(IRQ_HANDLED);
		}
	} else if (iflags & ITE_IRQ_TX_FIFO) {
		/* FIFO space available interrupt */
		ite_dbg_verbose("got interrupt for TX FIFO");

		/* wake any sleeping transmitter */
		wake_up_interruptible(&dev->tx_queue);

		/* mark the interrupt as serviced */
		ret = IRQ_RETVAL(IRQ_HANDLED);
	}

	/* drop the spinlock */
	spin_unlock_irqrestore(&dev->lock, flags);

	ite_dbg_verbose("%s done returning %d", __func__, (int)ret);

	return ret;
}