* [PATCH net-next v2 1/3] gianfar: Map head TxBD first
2016-02-23 9:48 [PATCH net-next v2 0/3] gianfar: xmit() improvements Claudiu Manoil
@ 2016-02-23 9:48 ` Claudiu Manoil
2016-02-23 9:48 ` [PATCH net-next v2 2/3] gianfar: Use skb_frag_t pointers inside xmit() Claudiu Manoil
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Claudiu Manoil @ 2016-02-23 9:48 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller
Move the mapping of the head BD before the mapping of fragments.
The TOE (h/w offload) decision logic block can be also moved up
(as the TOE flag belongs to the head BD), resulting in more
localized code (TOE logic vs BD mapping code blocks).
Note that, for this h/w, the R (status) bit for the head BD of a S/G
frame needs to be written last for a reliable transmission.
For the fragmented skb case, a local variable is used to temporarily
store the status info of the first BD, replacing a BD status read.
A merge of 2 "if(do_tstamp)" blocks was also possible.
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
v2: Don't remove the wmb() preceding the head BD status write.
drivers/net/ethernet/freescale/gianfar.c | 96 ++++++++++++++++----------------
1 file changed, 48 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 2aa7b40..cb80dba8 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -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);
}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH net-next v2 2/3] gianfar: Use skb_frag_t pointers inside xmit()
2016-02-23 9:48 [PATCH net-next v2 0/3] gianfar: xmit() improvements Claudiu Manoil
2016-02-23 9:48 ` [PATCH net-next v2 1/3] gianfar: Map head TxBD first Claudiu Manoil
@ 2016-02-23 9:48 ` Claudiu Manoil
2016-02-23 9:48 ` [PATCH net-next v2 3/3] gianfar: Remove redundant ops for do_tstamp from xmit() Claudiu Manoil
2016-02-24 21:56 ` [PATCH net-next v2 0/3] gianfar: xmit() improvements David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Claudiu Manoil @ 2016-02-23 9:48 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index cb80dba8..7b16ce6 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2322,6 +2322,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct txfcb *fcb = NULL;
struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL;
u32 lstatus;
+ skb_frag_t *frag;
int i, rq = 0;
int do_tstamp, do_csum, do_vlan;
u32 bufaddr;
@@ -2448,25 +2449,24 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 lstatus_start = lstatus;
/* Place the fragment addresses and lengths into the TxBDs */
- for (i = 0; i < nr_frags; i++) {
- unsigned int frag_len;
+ frag = &skb_shinfo(skb)->frags[0];
+ for (i = 0; i < nr_frags; i++, frag++) {
+ unsigned int size;
+
/* Point at the next BD, wrapping as needed */
txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size);
- frag_len = skb_shinfo(skb)->frags[i].size;
+ size = skb_frag_size(frag);
- lstatus = be32_to_cpu(txbdp->lstatus) | frag_len |
+ lstatus = be32_to_cpu(txbdp->lstatus) | size |
BD_LFLAG(TXBD_READY);
/* Handle the last BD specially */
if (i == nr_frags - 1)
lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
- bufaddr = skb_frag_dma_map(priv->dev,
- &skb_shinfo(skb)->frags[i],
- 0,
- frag_len,
- DMA_TO_DEVICE);
+ bufaddr = skb_frag_dma_map(priv->dev, frag, 0,
+ size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(priv->dev, bufaddr)))
goto dma_map_err;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH net-next v2 3/3] gianfar: Remove redundant ops for do_tstamp from xmit()
2016-02-23 9:48 [PATCH net-next v2 0/3] gianfar: xmit() improvements Claudiu Manoil
2016-02-23 9:48 ` [PATCH net-next v2 1/3] gianfar: Map head TxBD first Claudiu Manoil
2016-02-23 9:48 ` [PATCH net-next v2 2/3] gianfar: Use skb_frag_t pointers inside xmit() Claudiu Manoil
@ 2016-02-23 9:48 ` Claudiu Manoil
2016-02-24 21:56 ` [PATCH net-next v2 0/3] gianfar: xmit() improvements David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Claudiu Manoil @ 2016-02-23 9:48 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller
Timestamp BD status updates that can be merged into the
same "do_tstamp" block, no need for extra save/restore
to the BD area. The code is more readable too.
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 7b16ce6..1e1157f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2436,15 +2436,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbdp_tstamp = txbdp = next_txbd(txbdp, base,
tx_queue->tx_ring_size);
- if (nr_frags == 0) {
- if (unlikely(do_tstamp)) {
- u32 lstatus_ts = be32_to_cpu(txbdp_tstamp->lstatus);
-
- lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
- txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts);
- } else {
- lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
- }
+ if (likely(!nr_frags)) {
+ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
} else {
u32 lstatus_start = lstatus;
@@ -2488,8 +2481,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
bufaddr = be32_to_cpu(txbdp_start->bufPtr);
bufaddr += fcb_len;
+
lstatus_ts |= BD_LFLAG(TXBD_READY) |
(skb_headlen(skb) - fcb_len);
+ if (!nr_frags)
+ lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
txbdp_tstamp->bufPtr = cpu_to_be32(bufaddr);
txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 5+ messages in thread