Skip to content

Commit

Permalink
tilegx: fix some issues in the SW TSO support
Browse files Browse the repository at this point in the history
This change correctly computes the header length and data length in
the fragments to avoid a bug where we would end up with extremely
slow performance.  Also adopt use of skb_frag_size() accessor.

Signed-off-by: Chris Metcalf <[email protected]>
Cc: [email protected] [v3.6]
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
cmetcalf-tilera authored and davem330 committed Oct 26, 2012
1 parent f8295ec commit 3da3fff
Showing 1 changed file with 19 additions and 16 deletions.
35 changes: 19 additions & 16 deletions drivers/net/ethernet/tile/tilegx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)
{
struct skb_shared_info *sh = skb_shinfo(skb);
unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
unsigned int data_len = skb->len - sh_len;
unsigned int p_len = sh->gso_size;
long f_id = -1; /* id of the current fragment */
long f_size = skb->hdr_len; /* size of the current fragment */
long f_used = sh_len; /* bytes used from the current fragment */
long f_size = skb_headlen(skb) - sh_len; /* current fragment size */
long f_used = 0; /* bytes used from the current fragment */
long n; /* size of the current piece of payload */
int num_edescs = 0;
int segment;
Expand All @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)
/* Advance as needed. */
while (f_used >= f_size) {
f_id++;
f_size = sh->frags[f_id].size;
f_size = skb_frag_size(&sh->frags[f_id]);
f_used = 0;
}

Expand Down Expand Up @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
struct iphdr *ih;
struct tcphdr *th;
unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
unsigned int data_len = skb->len - sh_len;
unsigned char *data = skb->data;
unsigned int ih_off, th_off, p_len;
unsigned int isum_seed, tsum_seed, id, seq;
long f_id = -1; /* id of the current fragment */
long f_size = skb->hdr_len; /* size of the current fragment */
long f_used = sh_len; /* bytes used from the current fragment */
long f_size = skb_headlen(skb) - sh_len; /* current fragment size */
long f_used = 0; /* bytes used from the current fragment */
long n; /* size of the current piece of payload */
int segment;

Expand All @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
isum_seed = ((0xFFFF - ih->check) +
(0xFFFF - ih->tot_len) +
(0xFFFF - ih->id));
tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
id = ntohs(ih->id);
seq = ntohl(th->seq);

Expand Down Expand Up @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
/* Advance as needed. */
while (f_used >= f_size) {
f_id++;
f_size = sh->frags[f_id].size;
f_size = skb_frag_size(&sh->frags[f_id]);
f_used = 0;
}

Expand Down Expand Up @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
struct tile_net_priv *priv = netdev_priv(dev);
struct skb_shared_info *sh = skb_shinfo(skb);
unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
unsigned int data_len = skb->len - sh_len;
unsigned int p_len = sh->gso_size;
gxio_mpipe_edesc_t edesc_head = { { 0 } };
gxio_mpipe_edesc_t edesc_body = { { 0 } };
long f_id = -1; /* id of the current fragment */
long f_size = skb->hdr_len; /* size of the current fragment */
long f_used = sh_len; /* bytes used from the current fragment */
void *f_data = skb->data;
long f_size = skb_headlen(skb) - sh_len; /* current fragment size */
long f_used = 0; /* bytes used from the current fragment */
void *f_data = skb->data + sh_len;
long n; /* size of the current piece of payload */
unsigned long tx_packets = 0, tx_bytes = 0;
unsigned int csum_start;
Expand Down Expand Up @@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,

/* Egress the payload. */
while (p_used < p_len) {
void *va;

/* Advance as needed. */
while (f_used >= f_size) {
f_id++;
f_size = sh->frags[f_id].size;
f_used = 0;
f_size = skb_frag_size(&sh->frags[f_id]);
f_data = tile_net_frag_buf(&sh->frags[f_id]);
f_used = 0;
}

va = f_data + f_used;

/* Use bytes from the current fragment. */
n = p_len - p_used;
if (n > f_size - f_used)
Expand All @@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
p_used += n;

/* Egress a piece of the payload. */
edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
edesc_body.va = va_to_tile_io_addr(va);
edesc_body.xfer_size = n;
edesc_body.bound = !(p_used < p_len);
gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
Expand Down

0 comments on commit 3da3fff

Please sign in to comment.