Commit 0d0cffdc authored by Claudiu Manoil's avatar Claudiu Manoil Committed by David S. Miller

gianfar: Cleanup TxFCB insertion on xmit

Cleanup gfar_start_xmit()'s fast path by factoring out "redundant"
FCB insertion code (repeated gfar_add_fcb() calls and related)
and by reducing the number of if() clauses (i.e. if(fcb) checks).
Improve maintainability (e.g. there's less code and easier to read)
also by introducing do_csum and do_vlan to mark the other 2 Tx TOE
functionalities, following the same model as do_tstamp.
fcb_len may also be 0 now, to mark that Tx FCB insertion conditions
(do_csum, do_vlan, do_tstamp) have not been met.
Signed-off-by: default avatarClaudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 02d88fb4
...@@ -2081,10 +2081,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2081,10 +2081,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct txfcb *fcb = NULL; struct txfcb *fcb = NULL;
struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL;
u32 lstatus; u32 lstatus;
int i, rq = 0, do_tstamp = 0; int i, rq = 0;
int do_tstamp, do_csum, do_vlan;
u32 bufaddr; u32 bufaddr;
unsigned long flags; unsigned long flags;
unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; unsigned int nr_frags, nr_txbds, length, fcb_len = 0;
rq = skb->queue_mapping; rq = skb->queue_mapping;
tx_queue = priv->tx_queue[rq]; tx_queue = priv->tx_queue[rq];
...@@ -2092,21 +2093,23 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2092,21 +2093,23 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
base = tx_queue->tx_bd_base; base = tx_queue->tx_bd_base;
regs = tx_queue->grp->regs; regs = tx_queue->grp->regs;
do_csum = (CHECKSUM_PARTIAL == skb->ip_summed);
do_vlan = vlan_tx_tag_present(skb);
do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
priv->hwts_tx_en;
if (do_csum || do_vlan)
fcb_len = GMAC_FCB_LEN;
/* check if time stamp should be generated */ /* check if time stamp should be generated */
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && if (unlikely(do_tstamp))
priv->hwts_tx_en)) { fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
do_tstamp = 1;
fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
}
/* make space for additional header when fcb is needed */ /* make space for additional header when fcb is needed */
if (((skb->ip_summed == CHECKSUM_PARTIAL) || if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) {
vlan_tx_tag_present(skb) ||
unlikely(do_tstamp)) &&
(skb_headroom(skb) < fcb_length)) {
struct sk_buff *skb_new; struct sk_buff *skb_new;
skb_new = skb_realloc_headroom(skb, fcb_length); skb_new = skb_realloc_headroom(skb, fcb_len);
if (!skb_new) { if (!skb_new) {
dev->stats.tx_errors++; dev->stats.tx_errors++;
kfree_skb(skb); kfree_skb(skb);
...@@ -2189,37 +2192,38 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2189,37 +2192,38 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
memset(skb->data, 0, GMAC_TXPAL_LEN); memset(skb->data, 0, GMAC_TXPAL_LEN);
} }
/* Set up checksumming */ /* Add TxFCB if required */
if (CHECKSUM_PARTIAL == skb->ip_summed) { if (fcb_len) {
fcb = gfar_add_fcb(skb); fcb = gfar_add_fcb(skb);
lstatus |= BD_LFLAG(TXBD_TOE); lstatus |= BD_LFLAG(TXBD_TOE);
gfar_tx_checksum(skb, fcb, fcb_length); }
/* Set up checksumming */
if (do_csum) {
gfar_tx_checksum(skb, fcb, fcb_len);
if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) || if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
unlikely(gfar_csum_errata_76(priv, skb->len))) { unlikely(gfar_csum_errata_76(priv, skb->len))) {
__skb_pull(skb, GMAC_FCB_LEN); __skb_pull(skb, GMAC_FCB_LEN);
skb_checksum_help(skb); skb_checksum_help(skb);
if (do_vlan || do_tstamp) {
/* put back a new fcb for vlan/tstamp TOE */
fcb = gfar_add_fcb(skb);
} else {
/* Tx TOE not used */
lstatus &= ~(BD_LFLAG(TXBD_TOE)); lstatus &= ~(BD_LFLAG(TXBD_TOE));
fcb = NULL; fcb = NULL;
} }
} }
if (vlan_tx_tag_present(skb)) {
if (unlikely(NULL == fcb)) {
fcb = gfar_add_fcb(skb);
lstatus |= BD_LFLAG(TXBD_TOE);
} }
if (do_vlan)
gfar_tx_vlan(skb, fcb); gfar_tx_vlan(skb, fcb);
}
/* Setup tx hardware time stamping if requested */ /* Setup tx hardware time stamping if requested */
if (unlikely(do_tstamp)) { if (unlikely(do_tstamp)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
if (fcb == NULL)
fcb = gfar_add_fcb(skb);
fcb->ptp = 1; fcb->ptp = 1;
lstatus |= BD_LFLAG(TXBD_TOE);
} }
txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data, txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
...@@ -2231,9 +2235,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2231,9 +2235,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
* the full frame length. * the full frame length.
*/ */
if (unlikely(do_tstamp)) { if (unlikely(do_tstamp)) {
txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length; txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_len;
txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) |
(skb_headlen(skb) - fcb_length); (skb_headlen(skb) - fcb_len);
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
} else { } else {
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment