Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Linus Torvalds committed Jun 30, 2006
2 parents 93fdf10 + f83ef8c commit e37a72d
Show file tree
Hide file tree
Showing 23 changed files with 236 additions and 65 deletions.
15 changes: 9 additions & 6 deletions drivers/net/s2io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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];
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
107 changes: 97 additions & 10 deletions drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -6140,8 +6195,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
#endif

/* Receive/send statistics. */
if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
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;
tw32(RCVLPC_STATS_ENABLE, val);
Expand Down Expand Up @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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.
*/
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
17 changes: 12 additions & 5 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

/**
Expand Down
2 changes: 1 addition & 1 deletion include/net/ip6_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
struct rt6_info *rt = (struct rt6_info *) dst;

write_lock(&sk->sk_dst_lock);
__sk_dst_set(sk, dst);
sk_setup_caps(sk, dst);
np->daddr_cache = daddr;
np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
write_unlock(&sk->sk_dst_lock);
Expand Down
6 changes: 6 additions & 0 deletions include/net/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,17 @@ struct inet6_protocol
struct inet6_skb_parm *opt,
int type, int code, int offset,
__u32 info);

struct sk_buff *(*gso_segment)(struct sk_buff *skb,
int features);

unsigned int flags; /* INET6_PROTO_xxx */
};

#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
/* This should be set for any extension header which is compatible with GSO. */
#define INET6_PROTO_GSO_EXTHDR 0x4
#endif

/* This is used to register socket interfaces for IP protocols. */
Expand Down
Loading

0 comments on commit e37a72d

Please sign in to comment.