|
@@ -2389,6 +2389,47 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
txbdp = txbdp_start = tx_queue->cur_tx;
|
|
|
lstatus = be32_to_cpu(txbdp->lstatus);
|
|
|
|
|
|
+ /* Add TxPAL between FCB and frame if required */
|
|
|
+ if (unlikely(do_tstamp)) {
|
|
|
+ skb_push(skb, GMAC_TXPAL_LEN);
|
|
|
+ memset(skb->data, 0, GMAC_TXPAL_LEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Add TxFCB if required */
|
|
|
+ if (fcb_len) {
|
|
|
+ fcb = gfar_add_fcb(skb);
|
|
|
+ lstatus |= BD_LFLAG(TXBD_TOE);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Set up checksumming */
|
|
|
+ if (do_csum) {
|
|
|
+ gfar_tx_checksum(skb, fcb, fcb_len);
|
|
|
+
|
|
|
+ if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
|
|
|
+ unlikely(gfar_csum_errata_76(priv, skb->len))) {
|
|
|
+ __skb_pull(skb, GMAC_FCB_LEN);
|
|
|
+ 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));
|
|
|
+ fcb = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (do_vlan)
|
|
|
+ gfar_tx_vlan(skb, fcb);
|
|
|
+
|
|
|
+ bufaddr = dma_map_single(priv->dev, skb->data, skb_headlen(skb),
|
|
|
+ DMA_TO_DEVICE);
|
|
|
+ if (unlikely(dma_mapping_error(priv->dev, bufaddr)))
|
|
|
+ goto dma_map_err;
|
|
|
+
|
|
|
+ txbdp_start->bufPtr = cpu_to_be32(bufaddr);
|
|
|
+
|
|
|
/* Time stamp insertion requires one additional TxBD */
|
|
|
if (unlikely(do_tstamp))
|
|
|
txbdp_tstamp = txbdp = next_txbd(txbdp, base,
|
|
@@ -2404,6 +2445,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
|
|
|
}
|
|
|
} else {
|
|
|
+ u32 lstatus_start = lstatus;
|
|
|
+
|
|
|
/* Place the fragment addresses and lengths into the TxBDs */
|
|
|
for (i = 0; i < nr_frags; i++) {
|
|
|
unsigned int frag_len;
|
|
@@ -2432,56 +2475,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
txbdp->lstatus = cpu_to_be32(lstatus);
|
|
|
}
|
|
|
|
|
|
- lstatus = be32_to_cpu(txbdp_start->lstatus);
|
|
|
+ lstatus = lstatus_start;
|
|
|
}
|
|
|
|
|
|
- /* Add TxPAL between FCB and frame if required */
|
|
|
- if (unlikely(do_tstamp)) {
|
|
|
- skb_push(skb, GMAC_TXPAL_LEN);
|
|
|
- memset(skb->data, 0, GMAC_TXPAL_LEN);
|
|
|
- }
|
|
|
-
|
|
|
- /* Add TxFCB if required */
|
|
|
- if (fcb_len) {
|
|
|
- fcb = gfar_add_fcb(skb);
|
|
|
- lstatus |= BD_LFLAG(TXBD_TOE);
|
|
|
- }
|
|
|
-
|
|
|
- /* Set up checksumming */
|
|
|
- if (do_csum) {
|
|
|
- gfar_tx_checksum(skb, fcb, fcb_len);
|
|
|
-
|
|
|
- if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
|
|
|
- unlikely(gfar_csum_errata_76(priv, skb->len))) {
|
|
|
- __skb_pull(skb, GMAC_FCB_LEN);
|
|
|
- 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));
|
|
|
- fcb = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (do_vlan)
|
|
|
- gfar_tx_vlan(skb, fcb);
|
|
|
-
|
|
|
- /* Setup tx hardware time stamping if requested */
|
|
|
- if (unlikely(do_tstamp)) {
|
|
|
- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
|
|
- fcb->ptp = 1;
|
|
|
- }
|
|
|
-
|
|
|
- bufaddr = dma_map_single(priv->dev, skb->data, skb_headlen(skb),
|
|
|
- DMA_TO_DEVICE);
|
|
|
- if (unlikely(dma_mapping_error(priv->dev, bufaddr)))
|
|
|
- goto dma_map_err;
|
|
|
-
|
|
|
- txbdp_start->bufPtr = cpu_to_be32(bufaddr);
|
|
|
-
|
|
|
/* If time stamping is requested one additional TxBD must be set up. The
|
|
|
* first TxBD points to the FCB and must have a data length of
|
|
|
* GMAC_FCB_LEN. The second TxBD points to the actual frame data with
|
|
@@ -2498,6 +2494,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
txbdp_tstamp->bufPtr = cpu_to_be32(bufaddr);
|
|
|
txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts);
|
|
|
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
|
|
|
+
|
|
|
+ /* Setup tx hardware time stamping */
|
|
|
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
|
|
+ fcb->ptp = 1;
|
|
|
} else {
|
|
|
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
|
|
|
}
|