u32 ipheader; 
static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct mv643xx_private *mp = netdev_priv(dev);	struct net_device_stats *stats = &mp->stats;	ETH_FUNC_RET_STATUS status;	unsigned long flags;	struct pkt_info pkt_info;	if (netif_queue_stopped(dev)) {		printk(KERN_ERR			"%s: Tried sending packet when interface is stopped\n",			dev->name);		return 1;	}	/* This is a hard error, log it. */	if ((mp->tx_ring_size - mp->tx_ring_skbs) <=					(skb_shinfo(skb)->nr_frags + 1)) {		netif_stop_queue(dev);		printk(KERN_ERR			"%s: Bug in mv643xx_eth - Trying to transmit when"			" queue full !\n", dev->name);		return 1;	}	/* Paranoid check - this shouldn't happen */	if (skb == NULL) {		stats->tx_dropped++;		printk(KERN_ERR "mv64320_eth paranoid check failed\n");		return 1;	}	spin_lock_irqsave(&mp->lock, flags);	/* Update packet info data structure -- DMA owned, first last */#ifdef MV643XX_CHECKSUM_OFFLOAD_TX	if (!skb_shinfo(skb)->nr_frags) {linear:		if (skb->ip_summed != CHECKSUM_HW) {			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;			pkt_info.l4i_chk = 0;		} else {			u32 ipheader = skb->nh.iph->ihl << 11;			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |					ETH_GEN_TCP_UDP_CHECKSUM |					ETH_GEN_IP_V_4_CHECKSUM | ipheader;			/* CPU already calculated pseudo header checksum. */			if (skb->nh.iph->protocol == IPPROTO_UDP) {				pkt_info.cmd_sts |= ETH_UDP_FRAME;				pkt_info.l4i_chk = skb->h.uh->check;			} else if (skb->nh.iph->protocol == IPPROTO_TCP)				pkt_info.l4i_chk = skb->h.th->check;			else {				printk(KERN_ERR					"%s: chksum proto != TCP or UDP\n",					dev->name);				spin_unlock_irqrestore(&mp->lock, flags);				return 1;			}		}		pkt_info.byte_cnt = skb->len;		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,							DMA_TO_DEVICE);		pkt_info.return_info = skb;		mp->tx_ring_skbs++;		status = eth_port_send(mp, &pkt_info);		if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))			printk(KERN_ERR "%s: Error on transmitting packet\n",								dev->name);		stats->tx_bytes += pkt_info.byte_cnt;	} else {		unsigned int frag;		u32 ipheader;		/* Since hardware can't handle unaligned fragments smaller		 * than 9 bytes, if we find any, we linearize the skb		 * and start again.  When I've seen it, it's always been		 * the first frag (probably near the end of the page),		 * but we check all frags to be safe.		 */		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {			skb_frag_t *fragp;			fragp = &skb_shinfo(skb)->frags[frag];			if (fragp->size <= 8 && fragp->page_offset & 0x7) {				skb_linearize(skb, GFP_ATOMIC);				printk(KERN_DEBUG "%s: unaligned tiny fragment"						"%d of %d, fixed\n",						dev->name, frag,						skb_shinfo(skb)->nr_frags);				goto linear;			}		}		/* first frag which is skb header */		pkt_info.byte_cnt = skb_headlen(skb);		pkt_info.buf_ptr = dma_map_single(NULL, skb->data,							skb_headlen(skb),							DMA_TO_DEVICE);		pkt_info.l4i_chk = 0;		pkt_info.return_info = 0;		pkt_info.cmd_sts = ETH_TX_FIRST_DESC;		if (skb->ip_summed == CHECKSUM_HW) {			ipheader = skb->nh.iph->ihl << 11;			pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |					ETH_GEN_IP_V_4_CHECKSUM | ipheader;			/* CPU already calculated pseudo header checksum. */			if (skb->nh.iph->protocol == IPPROTO_UDP) {				pkt_info.cmd_sts |= ETH_UDP_FRAME;				pkt_info.l4i_chk = skb->h.uh->check;			} else if (skb->nh.iph->protocol == IPPROTO_TCP)				pkt_info.l4i_chk = skb->h.th->check;			else {				printk(KERN_ERR					"%s: chksum proto != TCP or UDP\n",					dev->name);				spin_unlock_irqrestore(&mp->lock, flags);				return 1;			}		}		status = eth_port_send(mp, &pkt_info);		if (status != ETH_OK) {			if ((status == ETH_ERROR))				printk(KERN_ERR					"%s: Error on transmitting packet\n",					dev->name);			if (status == ETH_QUEUE_FULL)				printk("Error on Queue Full \n");			if (status == ETH_QUEUE_LAST_RESOURCE)				printk("Tx resource error \n");		}		stats->tx_bytes += pkt_info.byte_cnt;		/* Check for the remaining frags */		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {			skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];			pkt_info.l4i_chk = 0x0000;			pkt_info.cmd_sts = 0x00000000;			/* Last Frag enables interrupt and frees the skb */			if (frag == (skb_shinfo(skb)->nr_frags - 1)) {				pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |							ETH_TX_LAST_DESC;				pkt_info.return_info = skb;				mp->tx_ring_skbs++;			} else {				pkt_info.return_info = 0;			}			pkt_info.l4i_chk = 0;			pkt_info.byte_cnt = this_frag->size;			pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page,							this_frag->page_offset,							this_frag->size,							DMA_TO_DEVICE);			status = eth_port_send(mp, &pkt_info);			if (status != ETH_OK) {				if ((status == ETH_ERROR))					printk(KERN_ERR "%s: Error on "							"transmitting packet\n",							dev->name);				if (status == ETH_QUEUE_LAST_RESOURCE)					printk("Tx resource error \n");				if (status == ETH_QUEUE_FULL)					printk("Queue is full \n");			}			stats->tx_bytes += pkt_info.byte_cnt;		}	}#else	pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |							ETH_TX_LAST_DESC;	pkt_info.l4i_chk = 0;	pkt_info.byte_cnt = skb->len;	pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,								DMA_TO_DEVICE);	pkt_info.return_info = skb;	mp->tx_ring_skbs++;	status = eth_port_send(mp, &pkt_info);	if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))		printk(KERN_ERR "%s: Error on transmitting packet\n",								dev->name);	stats->tx_bytes += pkt_info.byte_cnt;#endif	/* Check if TX queue can handle another skb. If not, then	 * signal higher layers to stop requesting TX	 */	if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB))		/*		 * Stop getting skb's from upper layers.		 * Getting skb's from upper layers will be enabled again after		 * packets are released.		 */		netif_stop_queue(dev);	/* Update statistics and start of transmittion time */	stats->tx_packets++;	dev->trans_start = jiffies;	spin_unlock_irqrestore(&mp->lock, flags);	return 0;		/* success */}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/2600636065406dc14948ac2d2913c66c51be80d5/mv643xx_eth.c/buggy/drivers/net/mv643xx_eth.c