diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2013-08-05 10:20:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-05 15:29:15 -0400 |
commit | 0d0cffdcc6fc4f57080b9a443401e8dad5ca77f8 (patch) | |
tree | d347a4f950c7f552e25055bca28d4652b8a84f22 /drivers/net/ethernet/freescale/gianfar.c | |
parent | 02d88fb4fb6a580b0224b3bf07bbfd9d4806f6fb (diff) |
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: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.c')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 352035e440d8..3cb464780777 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c | |||
@@ -2081,10 +2081,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2081 | struct txfcb *fcb = NULL; | 2081 | struct txfcb *fcb = NULL; |
2082 | struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; | 2082 | struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; |
2083 | u32 lstatus; | 2083 | u32 lstatus; |
2084 | int i, rq = 0, do_tstamp = 0; | 2084 | int i, rq = 0; |
2085 | int do_tstamp, do_csum, do_vlan; | ||
2085 | u32 bufaddr; | 2086 | u32 bufaddr; |
2086 | unsigned long flags; | 2087 | unsigned long flags; |
2087 | unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; | 2088 | unsigned int nr_frags, nr_txbds, length, fcb_len = 0; |
2088 | 2089 | ||
2089 | rq = skb->queue_mapping; | 2090 | rq = skb->queue_mapping; |
2090 | tx_queue = priv->tx_queue[rq]; | 2091 | tx_queue = priv->tx_queue[rq]; |
@@ -2092,21 +2093,23 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2092 | base = tx_queue->tx_bd_base; | 2093 | base = tx_queue->tx_bd_base; |
2093 | regs = tx_queue->grp->regs; | 2094 | regs = tx_queue->grp->regs; |
2094 | 2095 | ||
2096 | do_csum = (CHECKSUM_PARTIAL == skb->ip_summed); | ||
2097 | do_vlan = vlan_tx_tag_present(skb); | ||
2098 | do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && | ||
2099 | priv->hwts_tx_en; | ||
2100 | |||
2101 | if (do_csum || do_vlan) | ||
2102 | fcb_len = GMAC_FCB_LEN; | ||
2103 | |||
2095 | /* check if time stamp should be generated */ | 2104 | /* check if time stamp should be generated */ |
2096 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && | 2105 | if (unlikely(do_tstamp)) |
2097 | priv->hwts_tx_en)) { | 2106 | fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN; |
2098 | do_tstamp = 1; | ||
2099 | fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN; | ||
2100 | } | ||
2101 | 2107 | ||
2102 | /* make space for additional header when fcb is needed */ | 2108 | /* make space for additional header when fcb is needed */ |
2103 | if (((skb->ip_summed == CHECKSUM_PARTIAL) || | 2109 | if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) { |
2104 | vlan_tx_tag_present(skb) || | ||
2105 | unlikely(do_tstamp)) && | ||
2106 | (skb_headroom(skb) < fcb_length)) { | ||
2107 | struct sk_buff *skb_new; | 2110 | struct sk_buff *skb_new; |
2108 | 2111 | ||
2109 | skb_new = skb_realloc_headroom(skb, fcb_length); | 2112 | skb_new = skb_realloc_headroom(skb, fcb_len); |
2110 | if (!skb_new) { | 2113 | if (!skb_new) { |
2111 | dev->stats.tx_errors++; | 2114 | dev->stats.tx_errors++; |
2112 | kfree_skb(skb); | 2115 | kfree_skb(skb); |
@@ -2189,37 +2192,38 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2189 | memset(skb->data, 0, GMAC_TXPAL_LEN); | 2192 | memset(skb->data, 0, GMAC_TXPAL_LEN); |
2190 | } | 2193 | } |
2191 | 2194 | ||
2192 | /* Set up checksumming */ | 2195 | /* Add TxFCB if required */ |
2193 | if (CHECKSUM_PARTIAL == skb->ip_summed) { | 2196 | if (fcb_len) { |
2194 | fcb = gfar_add_fcb(skb); | 2197 | fcb = gfar_add_fcb(skb); |
2195 | lstatus |= BD_LFLAG(TXBD_TOE); | 2198 | lstatus |= BD_LFLAG(TXBD_TOE); |
2196 | gfar_tx_checksum(skb, fcb, fcb_length); | 2199 | } |
2200 | |||
2201 | /* Set up checksumming */ | ||
2202 | if (do_csum) { | ||
2203 | gfar_tx_checksum(skb, fcb, fcb_len); | ||
2197 | 2204 | ||
2198 | if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) || | 2205 | if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) || |
2199 | unlikely(gfar_csum_errata_76(priv, skb->len))) { | 2206 | unlikely(gfar_csum_errata_76(priv, skb->len))) { |
2200 | __skb_pull(skb, GMAC_FCB_LEN); | 2207 | __skb_pull(skb, GMAC_FCB_LEN); |
2201 | skb_checksum_help(skb); | 2208 | skb_checksum_help(skb); |
2202 | lstatus &= ~(BD_LFLAG(TXBD_TOE)); | 2209 | if (do_vlan || do_tstamp) { |
2203 | fcb = NULL; | 2210 | /* put back a new fcb for vlan/tstamp TOE */ |
2211 | fcb = gfar_add_fcb(skb); | ||
2212 | } else { | ||
2213 | /* Tx TOE not used */ | ||
2214 | lstatus &= ~(BD_LFLAG(TXBD_TOE)); | ||
2215 | fcb = NULL; | ||
2216 | } | ||
2204 | } | 2217 | } |
2205 | } | 2218 | } |
2206 | 2219 | ||
2207 | if (vlan_tx_tag_present(skb)) { | 2220 | if (do_vlan) |
2208 | if (unlikely(NULL == fcb)) { | ||
2209 | fcb = gfar_add_fcb(skb); | ||
2210 | lstatus |= BD_LFLAG(TXBD_TOE); | ||
2211 | } | ||
2212 | |||
2213 | gfar_tx_vlan(skb, fcb); | 2221 | gfar_tx_vlan(skb, fcb); |
2214 | } | ||
2215 | 2222 | ||
2216 | /* Setup tx hardware time stamping if requested */ | 2223 | /* Setup tx hardware time stamping if requested */ |
2217 | if (unlikely(do_tstamp)) { | 2224 | if (unlikely(do_tstamp)) { |
2218 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | 2225 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
2219 | if (fcb == NULL) | ||
2220 | fcb = gfar_add_fcb(skb); | ||
2221 | fcb->ptp = 1; | 2226 | fcb->ptp = 1; |
2222 | lstatus |= BD_LFLAG(TXBD_TOE); | ||
2223 | } | 2227 | } |
2224 | 2228 | ||
2225 | txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data, | 2229 | 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 | * the full frame length. | 2235 | * the full frame length. |
2232 | */ | 2236 | */ |
2233 | if (unlikely(do_tstamp)) { | 2237 | if (unlikely(do_tstamp)) { |
2234 | txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length; | 2238 | txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_len; |
2235 | txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | | 2239 | txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | |
2236 | (skb_headlen(skb) - fcb_length); | 2240 | (skb_headlen(skb) - fcb_len); |
2237 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; | 2241 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; |
2238 | } else { | 2242 | } else { |
2239 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); | 2243 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); |