diff options
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 3 |
2 files changed, 23 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 | ||
1987 | static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) | 1987 | static 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; |
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index fe7ac3a8319..40c33a7554c 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h | |||
@@ -63,6 +63,9 @@ struct ethtool_rx_list { | |||
63 | /* Length for FCB */ | 63 | /* Length for FCB */ |
64 | #define GMAC_FCB_LEN 8 | 64 | #define GMAC_FCB_LEN 8 |
65 | 65 | ||
66 | /* Length for TxPAL */ | ||
67 | #define GMAC_TXPAL_LEN 16 | ||
68 | |||
66 | /* Default padding amount */ | 69 | /* Default padding amount */ |
67 | #define DEFAULT_PADDING 2 | 70 | #define DEFAULT_PADDING 2 |
68 | 71 | ||