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

📄 via-velocity.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	Scan the queues looking for transmitted packets that *	we can complete and clean up. Update any statistics as *	neccessary/ */ static int velocity_tx_srv(struct velocity_info *vptr, u32 status){	struct tx_desc *td;	int qnum;	int full = 0;	int idx;	int works = 0;	struct velocity_td_info *tdinfo;	struct net_device_stats *stats = &vptr->stats;	for (qnum = 0; qnum < vptr->num_txq; qnum++) {		for (idx = vptr->td_tail[qnum]; vptr->td_used[qnum] > 0; 			idx = (idx + 1) % vptr->options.numtx) {			/*			 *	Get Tx Descriptor			 */			td = &(vptr->td_rings[qnum][idx]);			tdinfo = &(vptr->td_infos[qnum][idx]);			if (td->tdesc0.owner == OWNED_BY_NIC)				break;			if ((works++ > 15))				break;			if (td->tdesc0.TSR & TSR0_TERR) {				stats->tx_errors++;				stats->tx_dropped++;				if (td->tdesc0.TSR & TSR0_CDH)					stats->tx_heartbeat_errors++;				if (td->tdesc0.TSR & TSR0_CRS)					stats->tx_carrier_errors++;				if (td->tdesc0.TSR & TSR0_ABT)					stats->tx_aborted_errors++;				if (td->tdesc0.TSR & TSR0_OWC)					stats->tx_window_errors++;			} else {				stats->tx_packets++;				stats->tx_bytes += tdinfo->skb->len;			}			velocity_free_tx_buf(vptr, tdinfo);			vptr->td_used[qnum]--;		}		vptr->td_tail[qnum] = idx;		if (AVAIL_TD(vptr, qnum) < 1) {			full = 1;		}	}	/*	 *	Look to see if we should kick the transmit network	 *	layer for more work.	 */	if (netif_queue_stopped(vptr->dev) && (full == 0)	    && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {		netif_wake_queue(vptr->dev);	}	return works;}/** *	velocity_print_link_status	-	link status reporting *	@vptr: velocity to report on * *	Turn the link status of the velocity card into a kernel log *	description of the new link state, detailing speed and duplex *	status */static void velocity_print_link_status(struct velocity_info *vptr){	if (vptr->mii_status & VELOCITY_LINK_FAIL) {		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);	} else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name);		if (vptr->mii_status & VELOCITY_SPEED_1000)			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");		else if (vptr->mii_status & VELOCITY_SPEED_100)			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps");		else			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps");		if (vptr->mii_status & VELOCITY_DUPLEX_FULL)			VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n");		else			VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");	} else {		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);		switch (vptr->options.spd_dpx) {		case SPD_DPX_100_HALF:			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");			break;		case SPD_DPX_100_FULL:			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n");			break;		case SPD_DPX_10_HALF:			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n");			break;		case SPD_DPX_10_FULL:			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n");			break;		default:			break;		}	}}/** *	velocity_error	-	handle error from controller *	@vptr: velocity *	@status: card status * *	Process an error report from the hardware and attempt to recover *	the card itself. At the moment we cannot recover from some  *	theoretically impossible errors but this could be fixed using *	the pci_device_failed logic to bounce the hardware * */ static void velocity_error(struct velocity_info *vptr, int status){	if (status & ISR_TXSTLI) {		struct mac_regs * regs = vptr->mac_regs;		printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(&regs->TDIdx[0]));		BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);		writew(TRDCSR_RUN, &regs->TDCSRClr);		netif_stop_queue(vptr->dev);				/* FIXME: port over the pci_device_failed code and use it		   here */	}	if (status & ISR_SRCI) {		struct mac_regs * regs = vptr->mac_regs;		int linked;		if (vptr->options.spd_dpx == SPD_DPX_AUTO) {			vptr->mii_status = check_connection_type(regs);			/*			 *	If it is a 3119, disable frame bursting in 			 *	halfduplex mode and enable it in fullduplex			 *	 mode			 */			if (vptr->rev_id < REV_ID_VT3216_A0) {				if (vptr->mii_status | VELOCITY_DUPLEX_FULL)					BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);				else					BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);			}			/*			 *	Only enable CD heart beat counter in 10HD mode			 */			if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10)) {				BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);			} else {				BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);			}		}		/*		 *	Get link status from PHYSR0		 */		linked = readb(&regs->PHYSR0) & PHYSR0_LINKGD;		if (linked) {			vptr->mii_status &= ~VELOCITY_LINK_FAIL;		} else {			vptr->mii_status |= VELOCITY_LINK_FAIL;		}		velocity_print_link_status(vptr);		enable_flow_control_ability(vptr);		/*		 *	Re-enable auto-polling because SRCI will disable 		 *	auto-polling		 */		 		enable_mii_autopoll(regs);		if (vptr->mii_status & VELOCITY_LINK_FAIL)			netif_stop_queue(vptr->dev);		else			netif_wake_queue(vptr->dev);	};	if (status & ISR_MIBFI)		velocity_update_hw_mibs(vptr);	if (status & ISR_LSTEI)		mac_rx_queue_wake(vptr->mac_regs);}/** *	velocity_free_tx_buf	-	free transmit buffer *	@vptr: velocity *	@tdinfo: buffer * *	Release an transmit buffer. If the buffer was preallocated then *	recycle it, if not then unmap the buffer. */ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo){	struct sk_buff *skb = tdinfo->skb;	int i;	/*	 *	Don't unmap the pre-allocated tx_bufs	 */	if (tdinfo->skb_dma && (tdinfo->skb_dma[0] != tdinfo->buf_dma)) {		for (i = 0; i < tdinfo->nskb_dma; i++) {#ifdef VELOCITY_ZERO_COPY_SUPPORT			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], td->tdesc1.len, PCI_DMA_TODEVICE);#else			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE);#endif			tdinfo->skb_dma[i] = 0;		}	}	dev_kfree_skb_irq(skb);	tdinfo->skb = NULL;}/** *	velocity_open		-	interface activation callback *	@dev: network layer device to open * *	Called when the network layer brings the interface up. Returns *	a negative posix error code on failure, or zero on success. * *	All the ring allocation and set up is done on open for this *	adapter to minimise memory usage when inactive */ static int velocity_open(struct net_device *dev){	struct velocity_info *vptr = dev->priv;	int ret;	vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);	ret = velocity_init_rings(vptr);	if (ret < 0)		goto out;	ret = velocity_init_rd_ring(vptr);	if (ret < 0)		goto err_free_desc_rings;	ret = velocity_init_td_ring(vptr);	if (ret < 0)		goto err_free_rd_ring;		/* Ensure chip is running */		pci_set_power_state(vptr->pdev, 0);		velocity_init_registers(vptr, VELOCITY_INIT_COLD);	ret = request_irq(vptr->pdev->irq, &velocity_intr, SA_SHIRQ,			  dev->name, dev);	if (ret < 0) {		/* Power down the chip */		pci_set_power_state(vptr->pdev, 3);		goto err_free_td_ring;	}	mac_enable_int(vptr->mac_regs);	netif_start_queue(dev);	vptr->flags |= VELOCITY_FLAGS_OPENED;out:	return ret;err_free_td_ring:	velocity_free_td_ring(vptr);err_free_rd_ring:	velocity_free_rd_ring(vptr);err_free_desc_rings:	velocity_free_rings(vptr);	goto out;}/**  *	velocity_change_mtu	-	MTU change callback *	@dev: network device *	@new_mtu: desired MTU * *	Handle requests from the networking layer for MTU change on *	this interface. It gets called on a change by the network layer. *	Return zero for success or negative posix error code. */ static int velocity_change_mtu(struct net_device *dev, int new_mtu){	struct velocity_info *vptr = dev->priv;	unsigned long flags;	int oldmtu = dev->mtu;	int ret = 0;	if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", 				vptr->dev->name);		return -EINVAL;	}	if (new_mtu != oldmtu) {		spin_lock_irqsave(&vptr->lock, flags);		netif_stop_queue(dev);		velocity_shutdown(vptr);		velocity_free_td_ring(vptr);		velocity_free_rd_ring(vptr);		dev->mtu = new_mtu;		if (new_mtu > 8192)			vptr->rx_buf_sz = 9 * 1024;		else if (new_mtu > 4096)			vptr->rx_buf_sz = 8192;		else			vptr->rx_buf_sz = 4 * 1024;		ret = velocity_init_rd_ring(vptr);		if (ret < 0)			goto out_unlock;		ret = velocity_init_td_ring(vptr);		if (ret < 0)			goto out_unlock;		velocity_init_registers(vptr, VELOCITY_INIT_COLD);		mac_enable_int(vptr->mac_regs);		netif_start_queue(dev);out_unlock:		spin_unlock_irqrestore(&vptr->lock, flags);	}	return ret;}/** *	velocity_shutdown	-	shut down the chip *	@vptr: velocity to deactivate * *	Shuts down the internal operations of the velocity and *	disables interrupts, autopolling, transmit and receive */ static void velocity_shutdown(struct velocity_info *vptr){	struct mac_regs * regs = vptr->mac_regs;	mac_disable_int(regs);	writel(CR0_STOP, &regs->CR0Set);	writew(0xFFFF, &regs->TDCSRClr);	writeb(0xFF, &regs->RDCSRClr);	safe_disable_mii_autopoll(regs);	mac_clear_isr(regs);}/** *	velocity_close		-	close adapter callback *	@dev: network device * *	Callback from the network layer when the velocity is being *	deactivated by the network layer */static int velocity_close(struct net_device *dev){	struct velocity_info *vptr = dev->priv;	netif_stop_queue(dev);	velocity_shutdown(vptr);	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)		velocity_get_ip(vptr);	if (dev->irq != 0)		free_irq(dev->irq, dev);			/* Power down the chip */	pci_set_power_state(vptr->pdev, 3);		/* Free the resources */	velocity_free_td_ring(vptr);	velocity_free_rd_ring(vptr);	velocity_free_rings(vptr);	vptr->flags &= (~VELOCITY_FLAGS_OPENED);	return 0;}/** *	velocity_xmit		-	transmit packet callback *	@skb: buffer to transmit *	@dev: network device * *	Called by the networ layer to request a packet is queued to *	the velocity. Returns zero on success. */ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev){	struct velocity_info *vptr = dev->priv;	int qnum = 0;	struct tx_desc *td_ptr;	struct velocity_td_info *tdinfo;	unsigned long flags;	int index;	int pktlen = skb->len;	spin_lock_irqsave(&vptr->lock, flags);	index = vptr->td_curr[qnum];	td_ptr = &(vptr->td_rings[qnum][index]);	tdinfo = &(vptr->td_infos[qnum][index]);	td_ptr->tdesc1.TCPLS = TCPLS_NORMAL;	td_ptr->tdesc1.TCR = TCR0_TIC;	td_ptr->td_buf[0].queue = 0;	/*	 *	Pad short frames. 	 */	if (pktlen < ETH_ZLEN) {		/* Cannot occur until ZC support */		if(skb_linearize(skb, GFP_ATOMIC))			return 0; 		pktlen = ETH_ZLEN;		memcpy(tdinfo->buf, skb->data, skb->len);		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);		tdinfo->skb = skb;		tdinfo->skb_dma[0] = tdinfo->buf_dma;		td_ptr->tdesc0.pktsize = pktlen;		td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);		td_ptr->td_buf[0].pa_high = 0;		td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;		tdinfo->nskb_dma = 1;		td_ptr->tdesc1.CMDZ = 2;	} else#ifdef VELOCITY_ZERO_COPY_SUPPORT	if (skb_shinfo(skb)->nr_frags > 0) {		int nfrags = skb_shinfo(skb)->nr_frags;		tdinfo->skb = skb;		if (nfrags > 6) {			skb_linearize(skb, GFP_ATOMIC);			memcpy(tdinfo->buf, skb->data, skb->len);			tdinfo->skb_dma[0] = tdinfo->buf_dma;			td_ptr->tdesc0.pktsize = 			td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);			td_ptr->td_buf[0].pa_high = 0;			td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;			tdinfo->nskb_dma = 1;			td_ptr->tdesc1.CMDZ = 2;		} else {			int i = 0;			tdinfo->nskb_dma = 0;			tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data, skb->len - skb->data_len, PCI_DMA_TODEVICE);			td_ptr->tdesc0.pktsize = pktlen;			/* FIXME: support 48bit DMA later */			td_ptr->td_buf[i].pa_low = cpu_to_le32(tdinfo->skb_dma);			td_ptr->td_buf[i].pa_high = 0;			td_ptr->td_buf[i].bufsize = skb->len->skb->data_len;			for (i = 0; i < nfrags; i++) {				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];				void *addr = ((void *) page_address(frag->page + frag->page_offset));				tdinfo->skb_dma[i + 1] = pci_map_single(vptr->pdev, addr, frag->size, PCI_DMA_TODEVICE);				td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);				td_ptr->td_buf[i + 1].pa_high = 0;				td_ptr->td_buf[i + 1].bufsize = frag->size;			}			tdinfo->nskb_dma = i - 1;			td_ptr->tdesc1.CMDZ = i;		}	} else#endif

⌨️ 快捷键说明

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