⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interrupt.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
						   dev->name, status);				tp->stats.rx_errors++; /* end of a packet.*/				if (status & 0x0890) tp->stats.rx_length_errors++;				if (status & 0x0004) tp->stats.rx_frame_errors++;				if (status & 0x0002) tp->stats.rx_crc_errors++;				if (status & 0x0001) tp->stats.rx_fifo_errors++;			}		} else {			/* Omit the four octet CRC from the length. */			short pkt_len = ((status >> 16) & 0x7ff) - 4;			struct sk_buff *skb;#ifndef final_version			if (pkt_len > 1518) {				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",					   dev->name, pkt_len, pkt_len);				pkt_len = 1518;				tp->stats.rx_length_errors++;			}#endif			/* Check if the packet is long enough to accept without copying			   to a minimally-sized skbuff. */			if (pkt_len < tulip_rx_copybreak				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {				skb->dev = dev;				skb_reserve(skb, 2);	/* 16 byte align the IP header */				pci_dma_sync_single_for_cpu(tp->pdev,							    tp->rx_buffers[entry].mapping,							    pkt_len, PCI_DMA_FROMDEVICE);#if ! defined(__alpha__)				eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,						 pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len),				       tp->rx_buffers[entry].skb->data,				       pkt_len);#endif				pci_dma_sync_single_for_device(tp->pdev,							       tp->rx_buffers[entry].mapping,							       pkt_len, PCI_DMA_FROMDEVICE);			} else { 	/* Pass up the skb already on the Rx ring. */				char *temp = skb_put(skb = tp->rx_buffers[entry].skb,						     pkt_len);#ifndef final_version				if (tp->rx_buffers[entry].mapping !=				    le32_to_cpu(tp->rx_ring[entry].buffer1)) {					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "					       "do not match in tulip_rx: %08x vs. %Lx %p / %p.\n",					       dev->name,					       le32_to_cpu(tp->rx_ring[entry].buffer1),					       (long long)tp->rx_buffers[entry].mapping,					       skb->head, temp);				}#endif				pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,						 PKT_BUF_SZ, PCI_DMA_FROMDEVICE);				tp->rx_buffers[entry].skb = NULL;				tp->rx_buffers[entry].mapping = 0;			}			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			tp->stats.rx_packets++;			tp->stats.rx_bytes += pkt_len;		}		received++;		entry = (++tp->cur_rx) % RX_RING_SIZE;	}	return received;}#endif  /* CONFIG_TULIP_NAPI */static inline unsigned int phy_interrupt (struct net_device *dev){#ifdef __hppa__	struct tulip_private *tp = netdev_priv(dev);	int csr12 = ioread32(tp->base_addr + CSR12) & 0xff;	if (csr12 != tp->csr12_shadow) {		/* ack interrupt */		iowrite32(csr12 | 0x02, tp->base_addr + CSR12);		tp->csr12_shadow = csr12;		/* do link change stuff */		spin_lock(&tp->lock);		tulip_check_duplex(dev);		spin_unlock(&tp->lock);		/* clear irq ack bit */		iowrite32(csr12 & ~0x02, tp->base_addr + CSR12);		return 1;	}#endif	return 0;}/* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. */irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs){	struct net_device *dev = (struct net_device *)dev_instance;	struct tulip_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->base_addr;	int csr5;	int missed;	int rx = 0;	int tx = 0;	int oi = 0;	int maxrx = RX_RING_SIZE;	int maxtx = TX_RING_SIZE;	int maxoi = TX_RING_SIZE;#ifdef CONFIG_TULIP_NAPI	int rxd = 0;#else	int entry;#endif	unsigned int work_count = tulip_max_interrupt_work;	unsigned int handled = 0;	/* Let's see whether the interrupt really is for us */	csr5 = ioread32(ioaddr + CSR5);        if (tp->flags & HAS_PHY_IRQ) 	        handled = phy_interrupt (dev);    	if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)		return IRQ_RETVAL(handled);	tp->nir++;	do {#ifdef CONFIG_TULIP_NAPI		if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {			rxd++;			/* Mask RX intrs and add the device to poll list. */			iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);			netif_rx_schedule(dev);						if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))                               break;		}		               /* Acknowledge the interrupt sources we handle here ASAP                  the poll function does Rx and RxNoBuf acking */				iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);#else 		/* Acknowledge all of the current interrupt sources ASAP. */		iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);		if (csr5 & (RxIntr | RxNoBuf)) {				rx += tulip_rx(dev);			tulip_refill_rx(dev);		}#endif /*  CONFIG_TULIP_NAPI */				if (tulip_debug > 4)			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",			       dev->name, csr5, ioread32(ioaddr + CSR5));				if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {			unsigned int dirty_tx;			spin_lock(&tp->lock);			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;				 dirty_tx++) {				int entry = dirty_tx % TX_RING_SIZE;				int status = le32_to_cpu(tp->tx_ring[entry].status);				if (status < 0)					break;			/* It still has not been Txed */				/* Check for Rx filter setup frames. */				if (tp->tx_buffers[entry].skb == NULL) {					/* test because dummy frames not mapped */					if (tp->tx_buffers[entry].mapping)						pci_unmap_single(tp->pdev,							 tp->tx_buffers[entry].mapping,							 sizeof(tp->setup_frame),							 PCI_DMA_TODEVICE);					continue;				}				if (status & 0x8000) {					/* There was an major error, log it. */#ifndef final_version					if (tulip_debug > 1)						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",							   dev->name, status);#endif					tp->stats.tx_errors++;					if (status & 0x4104) tp->stats.tx_aborted_errors++;					if (status & 0x0C00) tp->stats.tx_carrier_errors++;					if (status & 0x0200) tp->stats.tx_window_errors++;					if (status & 0x0002) tp->stats.tx_fifo_errors++;					if ((status & 0x0080) && tp->full_duplex == 0)						tp->stats.tx_heartbeat_errors++;				} else {					tp->stats.tx_bytes +=						tp->tx_buffers[entry].skb->len;					tp->stats.collisions += (status >> 3) & 15;					tp->stats.tx_packets++;				}				pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,						 tp->tx_buffers[entry].skb->len,						 PCI_DMA_TODEVICE);				/* Free the original skb. */				dev_kfree_skb_irq(tp->tx_buffers[entry].skb);				tp->tx_buffers[entry].skb = NULL;				tp->tx_buffers[entry].mapping = 0;				tx++;			}#ifndef final_version			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {				printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n",					   dev->name, dirty_tx, tp->cur_tx);				dirty_tx += TX_RING_SIZE;			}#endif			if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)				netif_wake_queue(dev);			tp->dirty_tx = dirty_tx;			if (csr5 & TxDied) {				if (tulip_debug > 2)					printk(KERN_WARNING "%s: The transmitter stopped."						   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",						   dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6);				tulip_restart_rxtx(tp);			}			spin_unlock(&tp->lock);		}		/* Log errors. */		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */			if (csr5 == 0xffffffff)				break;			if (csr5 & TxJabber) tp->stats.tx_errors++;			if (csr5 & TxFIFOUnderflow) {				if ((tp->csr6 & 0xC000) != 0xC000)					tp->csr6 += 0x4000;	/* Bump up the Tx threshold */				else					tp->csr6 |= 0x00200000;  /* Store-n-forward. */				/* Restart the transmit process. */				tulip_restart_rxtx(tp);				iowrite32(0, ioaddr + CSR1);			}			if (csr5 & (RxDied | RxNoBuf)) {				if (tp->flags & COMET_MAC_ADDR) {					iowrite32(tp->mc_filter[0], ioaddr + 0xAC);					iowrite32(tp->mc_filter[1], ioaddr + 0xB0);				}			}			if (csr5 & RxDied) {		/* Missed a Rx frame. */                                tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;				tp->stats.rx_errors++;				tulip_start_rxtx(tp);			}			/*			 * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this			 * call is ever done under the spinlock			 */			if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {				if (tp->link_change)					(tp->link_change)(dev, csr5);			}			if (csr5 & SytemError) {				int error = (csr5 >> 23) & 7;				/* oops, we hit a PCI error.  The code produced corresponds				 * to the reason:				 *  0 - parity error				 *  1 - master abort				 *  2 - target abort				 * Note that on parity error, we should do a software reset				 * of the chip to get it back into a sane state (according				 * to the 21142/3 docs that is).				 *   -- rmk				 */				printk(KERN_ERR "%s: (%lu) System Error occurred (%d)\n",					dev->name, tp->nir, error);			}			/* Clear all error sources, included undocumented ones! */			iowrite32(0x0800f7ba, ioaddr + CSR5);			oi++;		}		if (csr5 & TimerInt) {			if (tulip_debug > 2)				printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",					   dev->name, csr5);			iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);			tp->ttimer = 0;			oi++;		}		if (tx > maxtx || rx > maxrx || oi > maxoi) {			if (tulip_debug > 1)				printk(KERN_WARNING "%s: Too much work during an interrupt, "					   "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi);                       /* Acknowledge all interrupt sources. */                        iowrite32(0x8001ffff, ioaddr + CSR5);                        if (tp->flags & HAS_INTR_MITIGATION) {                     /* Josip Loncaric at ICASE did extensive experimentation			to develop a good interrupt mitigation setting.*/                                iowrite32(0x8b240000, ioaddr + CSR11);                        } else if (tp->chip_id == LC82C168) {				/* the LC82C168 doesn't have a hw timer.*/				iowrite32(0x00, ioaddr + CSR7);				mod_timer(&tp->timer, RUN_AT(HZ/50));			} else {                          /* Mask all interrupting sources, set timer to				re-enable. */                                iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);                                iowrite32(0x0012, ioaddr + CSR11);                        }			break;		}		work_count--;		if (work_count == 0)			break;		csr5 = ioread32(ioaddr + CSR5);#ifdef CONFIG_TULIP_NAPI		if (rxd)			csr5 &= ~RxPollInt;	} while ((csr5 & (TxNoBuf | 			  TxDied | 			  TxIntr | 			  TimerInt |			  /* Abnormal intr. */			  RxDied | 			  TxFIFOUnderflow | 			  TxJabber | 			  TPLnkFail |  			  SytemError )) != 0);#else 	} while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);	tulip_refill_rx(dev);	/* check if the card is in suspend mode */	entry = tp->dirty_rx % RX_RING_SIZE;	if (tp->rx_buffers[entry].skb == NULL) {		if (tulip_debug > 1)			printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx);		if (tp->chip_id == LC82C168) {			iowrite32(0x00, ioaddr + CSR7);			mod_timer(&tp->timer, RUN_AT(HZ/50));		} else {			if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) {				if (tulip_debug > 1)					printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir);				iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,					ioaddr + CSR7);				iowrite32(TimerInt, ioaddr + CSR5);				iowrite32(12, ioaddr + CSR11);				tp->ttimer = 1;			}		}	}#endif /* CONFIG_TULIP_NAPI */	if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {		tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;	}	if (tulip_debug > 4)		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",			   dev->name, ioread32(ioaddr + CSR5));	return IRQ_HANDLED;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -