aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2013-02-14 00:00:07 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-14 13:32:25 -0500
commitba7797119b486bb5992beda74bdb26be9a291b46 (patch)
treeb694530d4f62a4e28d60313b57e1c98bfa24bf56 /drivers/net/ethernet/freescale
parent13f228da40cacdb3c4c23c8e1272c2ad37d1e4c0 (diff)
gianfar: Fix and cleanup Rx FCB indication
This fixes a less obvious error on one hand, and prevents futher similar errors by disambiguating and optimizing RxFCB indication, on the other hand. The error consists in NETIF_F_HW_VLAN_TX flag being used as an indication of Rx FCB insertion. This happened as soon gfar_uses_fcb(), which despite its name indicates Rx FCB insertion, started incorporating is_vlan_on(). is_vlan_on(), on the other hand, is also a misleading construct because we need to differentiate b/w hw VLAN extraction/VLEX (marked by VLAN_RX flag) and hw VLAN insertion/VLINS (VLAN_TX flag), which are different mechanisms using different types of FCBs. The hw spec for the RxFCB feature is as follows: In the case of RxBD rings, FCBs (Frame Control Block) are inserted by the eTSEC whenever RCTRL[PRSDEP] is set to a non-zero value. Only one FCB is inserted per frame (in the buffer pointed to by the RxBD with bit F set). TOE acceleration for receive is enabled for all rx frames in this case. This patch introduces priv->uses_rxfcb field to quickly signal RxFCB insertion in accordance with the specification above. The dependency on FSL_GIANFAR_DEV_HAS_TIMER was also eliminated as another source of confusion. The actual dependency is to priv->hwts_rx_en. Upon changing priv->hwts_rx_en via IOCTL, the gfar device is being restarted and on init_mac() the priv->hwts_rx_en flag determines RxFCB insertion, and rctrl is programmed accordingly. The patch takes care of this case too. Though maybe not as self documenting as the inlining version uses_fcb(), priv->uses_rxfcb has the main purpose to quickly signal, on the hot path, that the incoming frame has a *Rx* FCB block inserted which needs to be pulled out before passing the skb to the stack. This is a performance critical operation, it needs to happen fast, that's why uses_rxfcb is placed in the first cacheline of gfar_private. This is also why a cached rctrl cannot be used instead: 1) because we don't have 32 bits available in the first cacheline of gfar_priv (but only 16); 2) bit operations are expensive on the hot path. 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')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c41
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h1
2 files changed, 21 insertions, 21 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index b2c60772bd96..4b5e8a692481 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -344,6 +344,9 @@ static void gfar_init_mac(struct net_device *ndev)
344 /* Configure the coalescing support */ 344 /* Configure the coalescing support */
345 gfar_configure_coalescing(priv, 0xFF, 0xFF); 345 gfar_configure_coalescing(priv, 0xFF, 0xFF);
346 346
347 /* set this when rx hw offload (TOE) functions are being used */
348 priv->uses_rxfcb = 0;
349
347 if (priv->rx_filer_enable) { 350 if (priv->rx_filer_enable) {
348 rctrl |= RCTRL_FILREN; 351 rctrl |= RCTRL_FILREN;
349 /* Program the RIR0 reg with the required distribution */ 352 /* Program the RIR0 reg with the required distribution */
@@ -354,8 +357,10 @@ static void gfar_init_mac(struct net_device *ndev)
354 if (ndev->flags & IFF_PROMISC) 357 if (ndev->flags & IFF_PROMISC)
355 rctrl |= RCTRL_PROM; 358 rctrl |= RCTRL_PROM;
356 359
357 if (ndev->features & NETIF_F_RXCSUM) 360 if (ndev->features & NETIF_F_RXCSUM) {
358 rctrl |= RCTRL_CHECKSUMMING; 361 rctrl |= RCTRL_CHECKSUMMING;
362 priv->uses_rxfcb = 1;
363 }
359 364
360 if (priv->extended_hash) { 365 if (priv->extended_hash) {
361 rctrl |= RCTRL_EXTHASH; 366 rctrl |= RCTRL_EXTHASH;
@@ -377,11 +382,15 @@ static void gfar_init_mac(struct net_device *ndev)
377 } 382 }
378 383
379 /* Enable HW time stamping if requested from user space */ 384 /* Enable HW time stamping if requested from user space */
380 if (priv->hwts_rx_en) 385 if (priv->hwts_rx_en) {
381 rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; 386 rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
387 priv->uses_rxfcb = 1;
388 }
382 389
383 if (ndev->features & NETIF_F_HW_VLAN_RX) 390 if (ndev->features & NETIF_F_HW_VLAN_RX) {
384 rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; 391 rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
392 priv->uses_rxfcb = 1;
393 }
385 394
386 /* Init rctrl based on our settings */ 395 /* Init rctrl based on our settings */
387 gfar_write(&regs->rctrl, rctrl); 396 gfar_write(&regs->rctrl, rctrl);
@@ -500,20 +509,6 @@ void unlock_tx_qs(struct gfar_private *priv)
500 spin_unlock(&priv->tx_queue[i]->txlock); 509 spin_unlock(&priv->tx_queue[i]->txlock);
501} 510}
502 511
503static bool gfar_is_vlan_on(struct gfar_private *priv)
504{
505 return (priv->ndev->features & NETIF_F_HW_VLAN_RX) ||
506 (priv->ndev->features & NETIF_F_HW_VLAN_TX);
507}
508
509/* Returns 1 if incoming frames use an FCB */
510static inline int gfar_uses_fcb(struct gfar_private *priv)
511{
512 return gfar_is_vlan_on(priv) ||
513 (priv->ndev->features & NETIF_F_RXCSUM) ||
514 (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER);
515}
516
517static void free_tx_pointers(struct gfar_private *priv) 512static void free_tx_pointers(struct gfar_private *priv)
518{ 513{
519 int i; 514 int i;
@@ -2326,10 +2321,13 @@ void gfar_check_rx_parser_mode(struct gfar_private *priv)
2326 2321
2327 tempval = gfar_read(&regs->rctrl); 2322 tempval = gfar_read(&regs->rctrl);
2328 /* If parse is no longer required, then disable parser */ 2323 /* If parse is no longer required, then disable parser */
2329 if (tempval & RCTRL_REQ_PARSER) 2324 if (tempval & RCTRL_REQ_PARSER) {
2330 tempval |= RCTRL_PRSDEP_INIT; 2325 tempval |= RCTRL_PRSDEP_INIT;
2331 else 2326 priv->uses_rxfcb = 1;
2327 } else {
2332 tempval &= ~RCTRL_PRSDEP_INIT; 2328 tempval &= ~RCTRL_PRSDEP_INIT;
2329 priv->uses_rxfcb = 0;
2330 }
2333 gfar_write(&regs->rctrl, tempval); 2331 gfar_write(&regs->rctrl, tempval);
2334} 2332}
2335 2333
@@ -2362,6 +2360,7 @@ void gfar_vlan_mode(struct net_device *dev, netdev_features_t features)
2362 tempval = gfar_read(&regs->rctrl); 2360 tempval = gfar_read(&regs->rctrl);
2363 tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT); 2361 tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
2364 gfar_write(&regs->rctrl, tempval); 2362 gfar_write(&regs->rctrl, tempval);
2363 priv->uses_rxfcb = 1;
2365 } else { 2364 } else {
2366 /* Disable VLAN tag extraction */ 2365 /* Disable VLAN tag extraction */
2367 tempval = gfar_read(&regs->rctrl); 2366 tempval = gfar_read(&regs->rctrl);
@@ -2390,7 +2389,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
2390 return -EINVAL; 2389 return -EINVAL;
2391 } 2390 }
2392 2391
2393 if (gfar_uses_fcb(priv)) 2392 if (priv->uses_rxfcb)
2394 frame_size += GMAC_FCB_LEN; 2393 frame_size += GMAC_FCB_LEN;
2395 2394
2396 frame_size += priv->padding; 2395 frame_size += priv->padding;
@@ -2759,7 +2758,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
2759 bdp = rx_queue->cur_rx; 2758 bdp = rx_queue->cur_rx;
2760 base = rx_queue->rx_bd_base; 2759 base = rx_queue->rx_bd_base;
2761 2760
2762 amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0); 2761 amount_pull = priv->uses_rxfcb ? GMAC_FCB_LEN : 0;
2763 2762
2764 while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) { 2763 while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
2765 struct sk_buff *newskb; 2764 struct sk_buff *newskb;
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 1e2ce8bfea83..63a28d294e20 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1056,6 +1056,7 @@ struct gfar_private {
1056 enum gfar_errata errata; 1056 enum gfar_errata errata;
1057 unsigned int rx_buffer_size; 1057 unsigned int rx_buffer_size;
1058 1058
1059 u16 uses_rxfcb;
1059 u16 padding; 1060 u16 padding;
1060 1061
1061 /* HW time stamping enabled flag */ 1062 /* HW time stamping enabled flag */