aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale/gianfar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.c')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 2b3c1299212..39d160d353a 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1984,7 +1984,8 @@ static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
1984 return fcb; 1984 return fcb;
1985} 1985}
1986 1986
1987static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) 1987static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,
1988 int fcb_length)
1988{ 1989{
1989 u8 flags = 0; 1990 u8 flags = 0;
1990 1991
@@ -2006,7 +2007,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
2006 * frame (skb->data) and the start of the IP hdr. 2007 * frame (skb->data) and the start of the IP hdr.
2007 * l4os is the distance between the start of the 2008 * l4os is the distance between the start of the
2008 * l3 hdr and the l4 hdr */ 2009 * l3 hdr and the l4 hdr */
2009 fcb->l3os = (u16)(skb_network_offset(skb) - GMAC_FCB_LEN); 2010 fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length);
2010 fcb->l4os = skb_network_header_len(skb); 2011 fcb->l4os = skb_network_header_len(skb);
2011 2012
2012 fcb->flags = flags; 2013 fcb->flags = flags;
@@ -2046,7 +2047,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2046 int i, rq = 0, do_tstamp = 0; 2047 int i, rq = 0, do_tstamp = 0;
2047 u32 bufaddr; 2048 u32 bufaddr;
2048 unsigned long flags; 2049 unsigned long flags;
2049 unsigned int nr_frags, nr_txbds, length; 2050 unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN;
2050 2051
2051 /* 2052 /*
2052 * TOE=1 frames larger than 2500 bytes may see excess delays 2053 * TOE=1 frames larger than 2500 bytes may see excess delays
@@ -2070,17 +2071,19 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2070 2071
2071 /* check if time stamp should be generated */ 2072 /* check if time stamp should be generated */
2072 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && 2073 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
2073 priv->hwts_tx_en)) 2074 priv->hwts_tx_en)) {
2074 do_tstamp = 1; 2075 do_tstamp = 1;
2076 fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
2077 }
2075 2078
2076 /* make space for additional header when fcb is needed */ 2079 /* make space for additional header when fcb is needed */
2077 if (((skb->ip_summed == CHECKSUM_PARTIAL) || 2080 if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
2078 vlan_tx_tag_present(skb) || 2081 vlan_tx_tag_present(skb) ||
2079 unlikely(do_tstamp)) && 2082 unlikely(do_tstamp)) &&
2080 (skb_headroom(skb) < GMAC_FCB_LEN)) { 2083 (skb_headroom(skb) < fcb_length)) {
2081 struct sk_buff *skb_new; 2084 struct sk_buff *skb_new;
2082 2085
2083 skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN); 2086 skb_new = skb_realloc_headroom(skb, fcb_length);
2084 if (!skb_new) { 2087 if (!skb_new) {
2085 dev->stats.tx_errors++; 2088 dev->stats.tx_errors++;
2086 kfree_skb(skb); 2089 kfree_skb(skb);
@@ -2158,6 +2161,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2158 lstatus = txbdp_start->lstatus; 2161 lstatus = txbdp_start->lstatus;
2159 } 2162 }
2160 2163
2164 /* Add TxPAL between FCB and frame if required */
2165 if (unlikely(do_tstamp)) {
2166 skb_push(skb, GMAC_TXPAL_LEN);
2167 memset(skb->data, 0, GMAC_TXPAL_LEN);
2168 }
2169
2161 /* Set up checksumming */ 2170 /* Set up checksumming */
2162 if (CHECKSUM_PARTIAL == skb->ip_summed) { 2171 if (CHECKSUM_PARTIAL == skb->ip_summed) {
2163 fcb = gfar_add_fcb(skb); 2172 fcb = gfar_add_fcb(skb);
@@ -2168,7 +2177,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2168 skb_checksum_help(skb); 2177 skb_checksum_help(skb);
2169 } else { 2178 } else {
2170 lstatus |= BD_LFLAG(TXBD_TOE); 2179 lstatus |= BD_LFLAG(TXBD_TOE);
2171 gfar_tx_checksum(skb, fcb); 2180 gfar_tx_checksum(skb, fcb, fcb_length);
2172 } 2181 }
2173 } 2182 }
2174 2183
@@ -2200,9 +2209,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2200 * the full frame length. 2209 * the full frame length.
2201 */ 2210 */
2202 if (unlikely(do_tstamp)) { 2211 if (unlikely(do_tstamp)) {
2203 txbdp_tstamp->bufPtr = txbdp_start->bufPtr + GMAC_FCB_LEN; 2212 txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length;
2204 txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | 2213 txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) |
2205 (skb_headlen(skb) - GMAC_FCB_LEN); 2214 (skb_headlen(skb) - fcb_length);
2206 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; 2215 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
2207 } else { 2216 } else {
2208 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); 2217 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
@@ -2494,7 +2503,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2494 2503
2495 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { 2504 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
2496 next = next_txbd(bdp, base, tx_ring_size); 2505 next = next_txbd(bdp, base, tx_ring_size);
2497 buflen = next->length + GMAC_FCB_LEN; 2506 buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN;
2498 } else 2507 } else
2499 buflen = bdp->length; 2508 buflen = bdp->length;
2500 2509
@@ -2506,6 +2515,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2506 u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); 2515 u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
2507 memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 2516 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
2508 shhwtstamps.hwtstamp = ns_to_ktime(*ns); 2517 shhwtstamps.hwtstamp = ns_to_ktime(*ns);
2518 skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN);
2509 skb_tstamp_tx(skb, &shhwtstamps); 2519 skb_tstamp_tx(skb, &shhwtstamps);
2510 bdp->lstatus &= BD_LFLAG(TXBD_WRAP); 2520 bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
2511 bdp = next; 2521 bdp = next;