static irqreturn_t tsi721_irqhandler()

in devices/tsi721.c [457:567]


static irqreturn_t tsi721_irqhandler(int irq, void *ptr)
{
	struct tsi721_device *priv = (struct tsi721_device *)ptr;
	u32 dev_int;
	u32 dev_ch_int;
	u32 intval;
	u32 ch_inte;

	/* For MSI mode disable all device-level interrupts */
	if (priv->flags & TSI721_USING_MSI)
		iowrite32(0, priv->regs + TSI721_DEV_INTE);

	dev_int = ioread32(priv->regs + TSI721_DEV_INT);
	if (!dev_int)
		return IRQ_NONE;

	dev_ch_int = ioread32(priv->regs + TSI721_DEV_CHAN_INT);

	if (dev_int & TSI721_DEV_INT_SR2PC_CH) {
		/* Service SR2PC Channel interrupts */
		if (dev_ch_int & TSI721_INT_SR2PC_CHAN(IDB_QUEUE)) {
			/* Service Inbound Doorbell interrupt */
			intval = ioread32(priv->regs +
						TSI721_SR_CHINT(IDB_QUEUE));
			if (intval & TSI721_SR_CHINT_IDBQRCV)
				tsi721_dbell_handler(priv);
			else
				tsi_info(&priv->pdev->dev,
					"Unsupported SR_CH_INT %x", intval);

			/* Clear interrupts */
			iowrite32(intval,
				priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
			ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
		}
	}

	if (dev_int & TSI721_DEV_INT_SMSG_CH) {
		int ch;

		/*
		 * Service channel interrupts from Messaging Engine
		 */

		if (dev_ch_int & TSI721_INT_IMSG_CHAN_M) { /* Inbound Msg */
			/* Disable signaled OB MSG Channel interrupts */
			ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
			ch_inte &= ~(dev_ch_int & TSI721_INT_IMSG_CHAN_M);
			iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);

			/*
			 * Process Inbound Message interrupt for each MBOX
			 */
			for (ch = 4; ch < RIO_MAX_MBOX + 4; ch++) {
				if (!(dev_ch_int & TSI721_INT_IMSG_CHAN(ch)))
					continue;
				tsi721_imsg_handler(priv, ch);
			}
		}

		if (dev_ch_int & TSI721_INT_OMSG_CHAN_M) { /* Outbound Msg */
			/* Disable signaled OB MSG Channel interrupts */
			ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
			ch_inte &= ~(dev_ch_int & TSI721_INT_OMSG_CHAN_M);
			iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);

			/*
			 * Process Outbound Message interrupts for each MBOX
			 */

			for (ch = 0; ch < RIO_MAX_MBOX; ch++) {
				if (!(dev_ch_int & TSI721_INT_OMSG_CHAN(ch)))
					continue;
				tsi721_omsg_handler(priv, ch);
			}
		}
	}

	if (dev_int & TSI721_DEV_INT_SRIO) {
		/* Service SRIO MAC interrupts */
		intval = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT);
		if (intval & TSI721_RIO_EM_INT_STAT_PW_RX)
			tsi721_pw_handler(priv);
	}

#ifdef CONFIG_RAPIDIO_DMA_ENGINE
	if (dev_int & TSI721_DEV_INT_BDMA_CH) {
		int ch;

		if (dev_ch_int & TSI721_INT_BDMA_CHAN_M) {
			tsi_debug(DMA, &priv->pdev->dev,
				  "IRQ from DMA channel 0x%08x", dev_ch_int);

			for (ch = 0; ch < TSI721_DMA_MAXCH; ch++) {
				if (!(dev_ch_int & TSI721_INT_BDMA_CHAN(ch)))
					continue;
				tsi721_bdma_handler(&priv->bdma[ch]);
			}
		}
	}
#endif

	/* For MSI mode re-enable device-level interrupts */
	if (priv->flags & TSI721_USING_MSI) {
		dev_int = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO |
			TSI721_DEV_INT_SMSG_CH | TSI721_DEV_INT_BDMA_CH;
		iowrite32(dev_int, priv->regs + TSI721_DEV_INTE);
	}

	return IRQ_HANDLED;
}