Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e37a72de authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [IPV6]: Added GSO support for TCPv6
  [NET]: Generalise TSO-specific bits from skb_setup_caps
  [IPV6]: Added GSO support for TCPv6
  [IPV6]: Remove redundant length check on input
  [NETFILTER]: SCTP conntrack: fix crash triggered by packet without chunks
  [TG3]: Update version and reldate
  [TG3]: Add TSO workaround using GSO
  [TG3]: Turn on hw fix for ASF problems
  [TG3]: Add rx BD workaround
  [TG3]: Add tg3_netif_stop() in vlan functions
  [TCP]: Reset gso_segs if packet is dodgy
parents 93fdf10d f83ef8c0
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -3959,7 +3959,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
	txdp->Control_2 = 0;
#ifdef NETIF_F_TSO
	mss = skb_shinfo(skb)->gso_size;
	if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
	if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
		txdp->Control_1 |= TXD_TCP_LSO_EN;
		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
	}
@@ -3979,7 +3979,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
	}

	frg_len = skb->len - skb->data_len;
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) {
		int ufo_size;

		ufo_size = skb_shinfo(skb)->gso_size;
@@ -4008,7 +4008,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
	txdp->Host_Control = (unsigned long) skb;
	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);

	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
		txdp->Control_1 |= TXD_UFO_EN;

	frg_cnt = skb_shinfo(skb)->nr_frags;
@@ -4023,12 +4023,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
		    (sp->pdev, frag->page, frag->page_offset,
		     frag->size, PCI_DMA_TODEVICE);
		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
			txdp->Control_1 |= TXD_UFO_EN;
	}
	txdp->Control_1 |= TXD_GATHER_CODE_LAST;

	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
		frg_cnt++; /* as Txd0 was used for inband header */

	tx_fifo = mac_control->tx_FIFO_start[queue];
@@ -4042,7 +4042,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
	if (mss)
		val64 |= TX_FIFO_SPECIAL_FUNC;
#endif
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
		val64 |= TX_FIFO_SPECIAL_FUNC;
	writeq(val64, &tx_fifo->List_Control);

@@ -7019,6 +7019,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
		dev->features |= NETIF_F_HIGHDMA;
#ifdef NETIF_F_TSO
	dev->features |= NETIF_F_TSO;
#endif
#ifdef NETIF_F_TSO6
	dev->features |= NETIF_F_TSO6;
#endif
	if (sp->device_type & XFRAME_II_DEVICE) {
		dev->features |= NETIF_F_UFO;
+97 −10
Original line number Diff line number Diff line
@@ -68,8 +68,8 @@

#define DRV_MODULE_NAME		"tg3"
#define PFX DRV_MODULE_NAME	": "
#define DRV_MODULE_VERSION	"3.60"
#define DRV_MODULE_RELDATE	"June 17, 2006"
#define DRV_MODULE_VERSION	"3.61"
#define DRV_MODULE_RELDATE	"June 29, 2006"

#define TG3_DEF_MAC_MODE	0
#define TG3_DEF_RX_MODE		0
@@ -3194,7 +3194,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag)
 */
static int tg3_rx(struct tg3 *tp, int budget)
{
	u32 work_mask;
	u32 work_mask, rx_std_posted = 0;
	u32 sw_idx = tp->rx_rcb_ptr;
	u16 hw_idx;
	int received;
@@ -3221,6 +3221,7 @@ static int tg3_rx(struct tg3 *tp, int budget)
						  mapping);
			skb = tp->rx_std_buffers[desc_idx].skb;
			post_ptr = &tp->rx_std_ptr;
			rx_std_posted++;
		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
			dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx],
						  mapping);
@@ -3308,6 +3309,15 @@ static int tg3_rx(struct tg3 *tp, int budget)

next_pkt:
		(*post_ptr)++;

		if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
			u32 idx = *post_ptr % TG3_RX_RING_SIZE;

			tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX +
				     TG3_64BIT_REG_LOW, idx);
			work_mask &= ~RXD_OPAQUE_RING_STD;
			rx_std_posted = 0;
		}
next_pkt_nopost:
		sw_idx++;
		sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
@@ -3869,6 +3879,40 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
	return NETDEV_TX_OK;
}

#if TG3_TSO_SUPPORT != 0
static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *);

/* Use GSO to workaround a rare TSO bug that may be triggered when the
 * TSO header is greater than 80 bytes.
 */
static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
{
	struct sk_buff *segs, *nskb;

	/* Estimate the number of fragments in the worst case */
	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
		netif_stop_queue(tp->dev);
		return NETDEV_TX_BUSY;
	}

	segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
	if (unlikely(IS_ERR(segs)))
		goto tg3_tso_bug_end;

	do {
		nskb = segs;
		segs = segs->next;
		nskb->next = NULL;
		tg3_start_xmit_dma_bug(nskb, tp->dev);
	} while (segs);

tg3_tso_bug_end:
	dev_kfree_skb(skb);

	return NETDEV_TX_OK;
}
#endif

/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
 * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
 */
@@ -3905,7 +3949,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
	mss = 0;
	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
	    (mss = skb_shinfo(skb)->gso_size) != 0) {
		int tcp_opt_len, ip_tcp_len;
		int tcp_opt_len, ip_tcp_len, hdr_len;

		if (skb_header_cloned(skb) &&
		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -3916,11 +3960,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
		tcp_opt_len = ((skb->h.th->doff - 5) * 4);
		ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);

		hdr_len = ip_tcp_len + tcp_opt_len;
		if (unlikely((ETH_HLEN + hdr_len) > 80) &&
			     (tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG))
			return (tg3_tso_bug(tp, skb));

		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
			       TXD_FLAG_CPU_POST_DMA);

		skb->nh.iph->check = 0;
		skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
		skb->nh.iph->tot_len = htons(mss + hdr_len);
		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
			skb->h.th->check = 0;
			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
@@ -5980,7 +6029,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
	}

	/* Setup replenish threshold. */
	tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8);
	val = tp->rx_pending / 8;
	if (val == 0)
		val = 1;
	else if (val > tp->rx_std_max_post)
		val = tp->rx_std_max_post;

	tw32(RCVBDI_STD_THRESH, val);

	/* Initialize TG3_BDINFO's at:
	 *  RCVDBDI_STD_BD:	standard eth size rx ring
@@ -6140,7 +6195,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
#endif

	/* Receive/send statistics. */
	if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
		val = tr32(RCVLPC_STATS_ENABLE);
		val &= ~RCVLPC_STATSENAB_DACK_FIX;
		tw32(RCVLPC_STATS_ENABLE, val);
	} else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
		   (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
		val = tr32(RCVLPC_STATS_ENABLE);
		val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX;
@@ -8737,6 +8796,9 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
	struct tg3 *tp = netdev_priv(dev);

	if (netif_running(dev))
		tg3_netif_stop(tp);

	tg3_full_lock(tp, 0);

	tp->vlgrp = grp;
@@ -8745,16 +8807,25 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
	__tg3_set_rx_mode(dev);

	tg3_full_unlock(tp);

	if (netif_running(dev))
		tg3_netif_start(tp);
}

static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
	struct tg3 *tp = netdev_priv(dev);

	if (netif_running(dev))
		tg3_netif_stop(tp);

	tg3_full_lock(tp, 0);
	if (tp->vlgrp)
		tp->vlgrp->vlan_devices[vid] = NULL;
	tg3_full_unlock(tp);

	if (netif_running(dev))
		tg3_netif_start(tp);
}
#endif

@@ -10159,8 +10230,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
			tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
		} else
			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1;
		} else {
			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 |
					  TG3_FLG2_HW_TSO_1_BUG;
			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
				ASIC_REV_5750 &&
	     		    tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)
				tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG;
		}
	}

	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
@@ -10532,6 +10609,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
		tp->rx_offset = 0;

	tp->rx_std_max_post = TG3_RX_RING_SIZE;

	/* Increment the rx prod index on the rx std ring by at most
	 * 8 for these chips to workaround hw errata.
	 */
	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
		tp->rx_std_max_post = 8;

	/* By default, disable wake-on-lan.  User can change this
	 * using ETHTOOL_SWOL.
	 */
+4 −1
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@
#define  CHIPREV_ID_5750_A0		 0x4000
#define  CHIPREV_ID_5750_A1		 0x4001
#define  CHIPREV_ID_5750_A3		 0x4003
#define  CHIPREV_ID_5750_C2		 0x4202
#define  CHIPREV_ID_5752_A0_HW		 0x5000
#define  CHIPREV_ID_5752_A0		 0x6000
#define  CHIPREV_ID_5752_A1		 0x6001
@@ -760,6 +761,7 @@
#define  RCVLPC_STATSCTRL_ENABLE	 0x00000001
#define  RCVLPC_STATSCTRL_FASTUPD	 0x00000002
#define RCVLPC_STATS_ENABLE		0x00002018
#define  RCVLPC_STATSENAB_DACK_FIX	 0x00040000
#define  RCVLPC_STATSENAB_LNGBRST_RFIX	 0x00400000
#define RCVLPC_STATS_INCMASK		0x0000201c
/* 0x2020 --> 0x2100 unused */
@@ -2137,6 +2139,7 @@ struct tg3 {
	struct tg3_rx_buffer_desc	*rx_std;
	struct ring_info		*rx_std_buffers;
	dma_addr_t			rx_std_mapping;
	u32				rx_std_max_post;

	struct tg3_rx_buffer_desc	*rx_jumbo;
	struct ring_info		*rx_jumbo_buffers;
@@ -2191,7 +2194,7 @@ struct tg3 {
#define TG3_FLAG_INIT_COMPLETE		0x80000000
	u32				tg3_flags2;
#define TG3_FLG2_RESTART_TIMER		0x00000001
/*					0x00000002 available */
#define TG3_FLG2_HW_TSO_1_BUG		0x00000002
#define TG3_FLG2_NO_ETH_WIRE_SPEED	0x00000004
#define TG3_FLG2_IS_5788		0x00000008
#define TG3_FLG2_MAX_RXPEND_64		0x00000010
+12 −5
Original line number Diff line number Diff line
@@ -313,10 +313,12 @@ struct net_device

	/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT	16
#define NETIF_F_GSO_MASK	0xffff0000
#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO		(SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO		(SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN		(SKB_GSO_TCPV4_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN		(SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)

#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
@@ -991,13 +993,18 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);

extern void linkwatch_run_queue(void);

static inline int skb_gso_ok(struct sk_buff *skb, int features)
static inline int net_gso_ok(int features, int gso_type)
{
	int feature = skb_shinfo(skb)->gso_size ?
		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
	int feature = gso_type << NETIF_F_GSO_SHIFT;
	return (features & feature) == feature;
}

static inline int skb_gso_ok(struct sk_buff *skb, int features)
{
	return net_gso_ok(features, skb_shinfo(skb)->gso_size ?
				    skb_shinfo(skb)->gso_type : 0);
}

static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
	return !skb_gso_ok(skb, dev->features);
+4 −2
Original line number Diff line number Diff line
@@ -171,13 +171,15 @@ enum {

enum {
	SKB_GSO_TCPV4 = 1 << 0,
	SKB_GSO_UDPV4 = 1 << 1,
	SKB_GSO_UDP = 1 << 1,

	/* This indicates the skb is from an untrusted source. */
	SKB_GSO_DODGY = 1 << 2,

	/* This indicates the tcp segment has CWR set. */
	SKB_GSO_TCPV4_ECN = 1 << 3,
	SKB_GSO_TCP_ECN = 1 << 3,

	SKB_GSO_TCPV6 = 1 << 4,
};

/** 
Loading