would_hit_hwbug -= 1; entry = entry - 1 - skb_shinfo(skb)->nr_frags; entry &= (TG3_TX_RING_SIZE - 1); start = entry; i = 0; while (entry != last_plus_one) { if (i == 0) len = skb_headlen(skb); else len = skb_shinfo(skb)->frags[i-1].size;  if (entry == would_hit_hwbug) break;  i++; entry = NEXT_TX(entry);  } 
start = entry - 1 - skb_shinfo(skb)->nr_frags; start &= (TG3_TX_RING_SIZE - 1); 
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct tg3 *tp = netdev_priv(dev);	dma_addr_t mapping;	unsigned int i;	u32 len, entry, base_flags, mss;	int would_hit_hwbug;	len = skb_headlen(skb);	/* No BH disabling for tx_lock here.  We are running in BH disabled	 * context and TX reclaim runs via tp->poll inside of a software	 * interrupt.  Furthermore, IRQ processing runs lockless so we have	 * no IRQ context deadlocks to worry about either.  Rejoice!	 */	if (!spin_trylock(&tp->tx_lock))		return NETDEV_TX_LOCKED; 	/* This is a hard error, log it. */	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {		netif_stop_queue(dev);		spin_unlock(&tp->tx_lock);		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",		       dev->name);		return NETDEV_TX_BUSY;	}	entry = tp->tx_prod;	base_flags = 0;	if (skb->ip_summed == CHECKSUM_HW)		base_flags |= TXD_FLAG_TCPUDP_CSUM;#if TG3_TSO_SUPPORT != 0	mss = 0;	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&	    (mss = skb_shinfo(skb)->tso_size) != 0) {		int tcp_opt_len, ip_tcp_len;		if (skb_header_cloned(skb) &&		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {			dev_kfree_skb(skb);			goto out_unlock;		}		tcp_opt_len = ((skb->h.th->doff - 5) * 4);		ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);		base_flags |= (TXD_FLAG_CPU_PRE_DMA |			       TXD_FLAG_CPU_POST_DMA);		skb->nh.iph->check = 0;		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {			skb->h.th->check = 0;			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;		}		else {			skb->h.th->check =				~csum_tcpudp_magic(skb->nh.iph->saddr,						   skb->nh.iph->daddr,						   0, IPPROTO_TCP, 0);		}		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) ||		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {			if (tcp_opt_len || skb->nh.iph->ihl > 5) {				int tsflags;				tsflags = ((skb->nh.iph->ihl - 5) +					   (tcp_opt_len >> 2));				mss |= (tsflags << 11);			}		} else {			if (tcp_opt_len || skb->nh.iph->ihl > 5) {				int tsflags;				tsflags = ((skb->nh.iph->ihl - 5) +					   (tcp_opt_len >> 2));				base_flags |= tsflags << 12;			}		}	}#else	mss = 0;#endif#if TG3_VLAN_TAG_USED	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))		base_flags |= (TXD_FLAG_VLAN |			       (vlan_tx_tag_get(skb) << 16));#endif	/* Queue skb data, a.k.a. the main skb fragment. */	mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);	tp->tx_buffers[entry].skb = skb;	pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);	would_hit_hwbug = 0;	if (tg3_4g_overflow_test(mapping, len))		would_hit_hwbug = entry + 1;	tg3_set_txd(tp, entry, mapping, len, base_flags,		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));	entry = NEXT_TX(entry);	/* Now loop through additional data fragments, and queue them. */	if (skb_shinfo(skb)->nr_frags > 0) {		unsigned int i, last;		last = skb_shinfo(skb)->nr_frags - 1;		for (i = 0; i <= last; i++) {			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];			len = frag->size;			mapping = pci_map_page(tp->pdev,					       frag->page,					       frag->page_offset,					       len, PCI_DMA_TODEVICE);			tp->tx_buffers[entry].skb = NULL;			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);			if (tg3_4g_overflow_test(mapping, len)) {				/* Only one should match. */				if (would_hit_hwbug)					BUG();				would_hit_hwbug = entry + 1;			}			if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)				tg3_set_txd(tp, entry, mapping, len,					    base_flags, (i == last)|(mss << 1));			else				tg3_set_txd(tp, entry, mapping, len,					    base_flags, (i == last));			entry = NEXT_TX(entry);		}	}	if (would_hit_hwbug) {		u32 last_plus_one = entry;		u32 start;		unsigned int len = 0;		would_hit_hwbug -= 1;		entry = entry - 1 - skb_shinfo(skb)->nr_frags;		entry &= (TG3_TX_RING_SIZE - 1);		start = entry;		i = 0;		while (entry != last_plus_one) {			if (i == 0)				len = skb_headlen(skb);			else				len = skb_shinfo(skb)->frags[i-1].size;			if (entry == would_hit_hwbug)				break;			i++;			entry = NEXT_TX(entry);		}		/* If the workaround fails due to memory/mapping		 * failure, silently drop this packet.		 */		if (tigon3_4gb_hwbug_workaround(tp, skb,						entry, len,						last_plus_one,						&start, mss))			goto out_unlock;		entry = start;	}	/* Packets are ready, update Tx producer idx local and on card. */	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);	tp->tx_prod = entry;	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {		netif_stop_queue(dev);		if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)			netif_wake_queue(tp->dev);	}out_unlock:    	mmiowb();	spin_unlock(&tp->tx_lock);	dev->trans_start = jiffies;	return NETDEV_TX_OK;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/c58ec93245a1fb7354f9e331960380827b9f41db/tg3.c/clean/drivers/net/tg3.c