Skip to content

Commit f966082

Browse files
claudiu-mdavem330
authored andcommitted
gianfar: Fix and cleanup rxbd status handling
There are several (long standing) problems about how the status field of the rx buffer descriptor (rxbd) is currently handled on the error path: - too many unnecessary 16bit reads of the two halves of the rxbd status field (32bit), also resulting in overuse of endianness convesion macros; - "bdp->status = RXBD_LARGE" makes no sense, since the "large" flag is read only (only eTSEC can write it), and trying to clear the other status bits is also error prone in this context (most of the rx status bits are read only anyway). This is fixed with a single 32bit read of the "status" field, and then the appropriate 16bit shifting is applied to access the various status bits or the rx frame length. Also corrected the use of the RXBD_LARGE flag. Additional fix: "rx_over_errors" stat is incremented instead of "rx_crc_errors" in case of RXBD_OVERRUN occurrence. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 76f31e8 commit f966082

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

drivers/net/ethernet/freescale/gianfar.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2756,40 +2756,40 @@ static void gfar_alloc_rx_buffs(struct gfar_priv_rx_q *rx_queue,
27562756
rx_queue->next_to_use = i;
27572757
}
27582758

2759-
static inline void count_errors(unsigned short status, struct net_device *dev)
2759+
static void count_errors(u32 lstatus, struct net_device *dev)
27602760
{
27612761
struct gfar_private *priv = netdev_priv(dev);
27622762
struct net_device_stats *stats = &dev->stats;
27632763
struct gfar_extra_stats *estats = &priv->extra_stats;
27642764

27652765
/* If the packet was truncated, none of the other errors matter */
2766-
if (status & RXBD_TRUNCATED) {
2766+
if (lstatus & BD_LFLAG(RXBD_TRUNCATED)) {
27672767
stats->rx_length_errors++;
27682768

27692769
atomic64_inc(&estats->rx_trunc);
27702770

27712771
return;
27722772
}
27732773
/* Count the errors, if there were any */
2774-
if (status & (RXBD_LARGE | RXBD_SHORT)) {
2774+
if (lstatus & BD_LFLAG(RXBD_LARGE | RXBD_SHORT)) {
27752775
stats->rx_length_errors++;
27762776

2777-
if (status & RXBD_LARGE)
2777+
if (lstatus & BD_LFLAG(RXBD_LARGE))
27782778
atomic64_inc(&estats->rx_large);
27792779
else
27802780
atomic64_inc(&estats->rx_short);
27812781
}
2782-
if (status & RXBD_NONOCTET) {
2782+
if (lstatus & BD_LFLAG(RXBD_NONOCTET)) {
27832783
stats->rx_frame_errors++;
27842784
atomic64_inc(&estats->rx_nonoctet);
27852785
}
2786-
if (status & RXBD_CRCERR) {
2786+
if (lstatus & BD_LFLAG(RXBD_CRCERR)) {
27872787
atomic64_inc(&estats->rx_crcerr);
27882788
stats->rx_crc_errors++;
27892789
}
2790-
if (status & RXBD_OVERRUN) {
2790+
if (lstatus & BD_LFLAG(RXBD_OVERRUN)) {
27912791
atomic64_inc(&estats->rx_overrun);
2792-
stats->rx_crc_errors++;
2792+
stats->rx_over_errors++;
27932793
}
27942794
}
27952795

@@ -2921,14 +2921,16 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
29212921
i = rx_queue->next_to_clean;
29222922

29232923
while (rx_work_limit--) {
2924+
u32 lstatus;
29242925

29252926
if (cleaned_cnt >= GFAR_RX_BUFF_ALLOC) {
29262927
gfar_alloc_rx_buffs(rx_queue, cleaned_cnt);
29272928
cleaned_cnt = 0;
29282929
}
29292930

29302931
bdp = &rx_queue->rx_bd_base[i];
2931-
if (be16_to_cpu(bdp->status) & RXBD_EMPTY)
2932+
lstatus = be32_to_cpu(bdp->lstatus);
2933+
if (lstatus & BD_LFLAG(RXBD_EMPTY))
29322934
break;
29332935

29342936
/* order rx buffer descriptor reads */
@@ -2940,13 +2942,13 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
29402942
dma_unmap_single(priv->dev, be32_to_cpu(bdp->bufPtr),
29412943
priv->rx_buffer_size, DMA_FROM_DEVICE);
29422944

2943-
if (unlikely(!(be16_to_cpu(bdp->status) & RXBD_ERR) &&
2944-
be16_to_cpu(bdp->length) > priv->rx_buffer_size))
2945-
bdp->status = cpu_to_be16(RXBD_LARGE);
2945+
if (unlikely(!(lstatus & BD_LFLAG(RXBD_ERR)) &&
2946+
(lstatus & BD_LENGTH_MASK) > priv->rx_buffer_size))
2947+
lstatus |= BD_LFLAG(RXBD_LARGE);
29462948

2947-
if (unlikely(!(be16_to_cpu(bdp->status) & RXBD_LAST) ||
2948-
be16_to_cpu(bdp->status) & RXBD_ERR)) {
2949-
count_errors(be16_to_cpu(bdp->status), dev);
2949+
if (unlikely(!(lstatus & BD_LFLAG(RXBD_LAST)) ||
2950+
(lstatus & BD_LFLAG(RXBD_ERR)))) {
2951+
count_errors(lstatus, dev);
29502952

29512953
/* discard faulty buffer */
29522954
dev_kfree_skb(skb);
@@ -2957,7 +2959,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
29572959
howmany++;
29582960

29592961
if (likely(skb)) {
2960-
int pkt_len = be16_to_cpu(bdp->length) -
2962+
int pkt_len = (lstatus & BD_LENGTH_MASK) -
29612963
ETH_FCS_LEN;
29622964
/* Remove the FCS from the packet length */
29632965
skb_put(skb, pkt_len);

0 commit comments

Comments
 (0)