Example #1
0
static irqreturn_t smc_interrupt(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	int status, mask, timeout, card_stats;
	int saved_pointer;

	DBG(3, "%s: %s\n", dev->name, __func__);

	spin_lock(&lp->lock);

	
	SMC_INTERRUPT_PREAMBLE;

	saved_pointer = SMC_GET_PTR(lp);
	mask = SMC_GET_INT_MASK(lp);
	SMC_SET_INT_MASK(lp, 0);

	
	timeout = MAX_IRQ_LOOPS;

	do {
		status = SMC_GET_INT(lp);

		DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
			dev->name, status, mask,
			({ int meminfo; SMC_SELECT_BANK(lp, 0);
			   meminfo = SMC_GET_MIR(lp);
			   SMC_SELECT_BANK(lp, 2); meminfo; }),
			SMC_GET_FIFO(lp));

		status &= mask;
		if (!status)
			break;

		if (status & IM_TX_INT) {
			
			DBG(3, "%s: TX int\n", dev->name);
			smc_tx(dev);
			SMC_ACK_INT(lp, IM_TX_INT);
			if (THROTTLE_TX_PKTS)
				netif_wake_queue(dev);
		} else if (status & IM_RCV_INT) {
			DBG(3, "%s: RX irq\n", dev->name);
			smc_rcv(dev);
		} else if (status & IM_ALLOC_INT) {
			DBG(3, "%s: Allocation irq\n", dev->name);
			tasklet_hi_schedule(&lp->tx_task);
			mask &= ~IM_ALLOC_INT;
		} else if (status & IM_TX_EMPTY_INT) {
			DBG(3, "%s: TX empty\n", dev->name);
			mask &= ~IM_TX_EMPTY_INT;

			
			SMC_SELECT_BANK(lp, 0);
			card_stats = SMC_GET_COUNTER(lp);
			SMC_SELECT_BANK(lp, 2);

			
			dev->stats.collisions += card_stats & 0xF;
			card_stats >>= 4;

			
			dev->stats.collisions += card_stats & 0xF;
		} else if (status & IM_RX_OVRN_INT) {
Example #2
0
/*
 * This is the main routine of the driver, to handle the device when
 * it needs some attention.
 */
static irqreturn_t smc_interrupt(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	int status, mask, timeout, card_stats;
	int saved_pointer;

	DBG(3, "%s: %s\n", dev->name, __func__);

	spin_lock(&lp->lock);

	/* A preamble may be used when there is a potential race
	 * between the interruptible transmit functions and this
	 * ISR. */
	SMC_INTERRUPT_PREAMBLE;

	saved_pointer = SMC_GET_PTR(lp);
	mask = SMC_GET_INT_MASK(lp);
	SMC_SET_INT_MASK(lp, 0);

	/* set a timeout value, so I don't stay here forever */
	timeout = MAX_IRQ_LOOPS;

	do {
		status = SMC_GET_INT(lp);

		DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
			dev->name, status, mask,
			({ int meminfo; SMC_SELECT_BANK(lp, 0);
			   meminfo = SMC_GET_MIR(lp);
			   SMC_SELECT_BANK(lp, 2); meminfo; }),
			SMC_GET_FIFO(lp));

		status &= mask;
		if (!status)
			break;

		if (status & IM_TX_INT) {
			/* do this before RX as it will free memory quickly */
			DBG(3, "%s: TX int\n", dev->name);
			smc_tx(dev);
			SMC_ACK_INT(lp, IM_TX_INT);
			if (THROTTLE_TX_PKTS)
				netif_wake_queue(dev);
		} else if (status & IM_RCV_INT) {
			DBG(3, "%s: RX irq\n", dev->name);
			smc_rcv(dev);
		} else if (status & IM_ALLOC_INT) {
			DBG(3, "%s: Allocation irq\n", dev->name);
			tasklet_hi_schedule(&lp->tx_task);
			mask &= ~IM_ALLOC_INT;
		} else if (status & IM_TX_EMPTY_INT) {
			DBG(3, "%s: TX empty\n", dev->name);
			mask &= ~IM_TX_EMPTY_INT;

			/* update stats */
			SMC_SELECT_BANK(lp, 0);
			card_stats = SMC_GET_COUNTER(lp);
			SMC_SELECT_BANK(lp, 2);

			/* single collisions */
			dev->stats.collisions += card_stats & 0xF;
			card_stats >>= 4;

			/* multiple collisions */
			dev->stats.collisions += card_stats & 0xF;
		} else if (status & IM_RX_OVRN_INT) {