diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-04-01 23:06:09 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-10-17 14:35:43 +0100 |
commit | 7e291d514886ac81463014078292fbe32f08ae76 (patch) | |
tree | e6dac90730b7a18f7f88eb2f9710c3ddab9a0c74 /drivers/net/ethernet/freescale/fec_main.c | |
parent | 9f8008020a8293074a65f5f23ec1f40ac97d6beb (diff) |
net:fec: unsorted hacks
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 95fad9862ef5..001db716cbf7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -109,16 +109,6 @@ static void set_multicast_list(struct net_device *ndev); #define FEC_QUIRK_HAS_CSUM (1 << 5) /* Controller has hardware vlan support */ #define FEC_QUIRK_HAS_VLAN (1 << 6) -/* ENET IP errata ERR006358 - * - * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously - * detected as not set during a prior frame transmission, then the - * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs - * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in - * frames not being transmitted until there is a 0-to-1 transition on - * ENET_TDAR[TDAR]. - */ -#define FEC_QUIRK_ERR006358 (1 << 7) static struct platform_device_id fec_devtype[] = { { @@ -138,7 +128,7 @@ static struct platform_device_id fec_devtype[] = { .name = "imx6q-fec", .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358, + FEC_QUIRK_HAS_VLAN, }, { .name = "mvf600-fec", .driver_data = FEC_QUIRK_ENET_MAC, @@ -316,13 +306,16 @@ static void fec_dump(struct net_device *ndev) for (index = 0; index < fep->tx_ring_size; index++) { bdp = fec_enet_tx_get(index, fep); - pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n", + pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p", index, index == fep->tx_next ? 'S' : ' ', index == fep->tx_dirty ? 'H' : ' ', bdp->bd.cbd_sc, bdp->bd.cbd_bufaddr, bdp->bd.cbd_datlen, fep->tx_skbuff[index]); + if (fep->flags & FEC_FLAG_BUFDESC_EX) + pr_cont(" %08lx", bdp->ebd.cbd_esc); + pr_cont("\n"); } } @@ -877,13 +870,14 @@ fec_enet_tx(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); union bufdesc_u *bdp; - unsigned short status; struct sk_buff *skb; unsigned int index = fep->tx_dirty; unsigned int pkts_compl, bytes_compl; pkts_compl = bytes_compl = 0; do { + unsigned status, cbd_esc; + if (++index >= fep->tx_ring_size) index = 0; @@ -904,25 +898,42 @@ fec_enet_tx(struct net_device *ndev) continue; /* Check for errors. */ - if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | - BD_ENET_TX_RL | BD_ENET_TX_UN | - BD_ENET_TX_CSL)) { - ndev->stats.tx_errors++; - if (status & BD_ENET_TX_HB) /* No heartbeat */ - ndev->stats.tx_heartbeat_errors++; - if (status & BD_ENET_TX_LC) /* Late collision */ - ndev->stats.tx_window_errors++; - if (status & BD_ENET_TX_RL) /* Retrans limit */ - ndev->stats.tx_aborted_errors++; - if (status & BD_ENET_TX_UN) /* Underrun */ - ndev->stats.tx_fifo_errors++; - if (status & BD_ENET_TX_CSL) /* Carrier lost */ - ndev->stats.tx_carrier_errors++; + if (fep->flags & FEC_FLAG_BUFDESC_EX) { + cbd_esc = bdp->ebd.cbd_esc; + if (cbd_esc & BD_ENET_TX_TXE) { + ndev->stats.tx_errors++; + if (cbd_esc & BD_ENET_TX_EE) { /* excess collision */ + ndev->stats.collisions += 16; + ndev->stats.tx_aborted_errors++; + } + if (cbd_esc & BD_ENET_TX_LCE) /* late collision error */ + ndev->stats.tx_window_errors++; + if (cbd_esc & (BD_ENET_TX_UE | BD_ENET_TX_FE | BD_ENET_TX_OE)) + ndev->stats.tx_fifo_errors++; + goto next; + } } else { - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; + if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | + BD_ENET_TX_RL | BD_ENET_TX_UN | + BD_ENET_TX_CSL)) { + ndev->stats.tx_errors++; + if (status & BD_ENET_TX_HB) /* No heartbeat */ + ndev->stats.tx_heartbeat_errors++; + if (status & BD_ENET_TX_LC) /* Late collision */ + ndev->stats.tx_window_errors++; + if (status & BD_ENET_TX_RL) /* Retrans limit */ + ndev->stats.tx_aborted_errors++; + if (status & BD_ENET_TX_UN) /* Underrun */ + ndev->stats.tx_fifo_errors++; + if (status & BD_ENET_TX_CSL) /* Carrier lost */ + ndev->stats.tx_carrier_errors++; + goto next; + } } + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + if (fep->flags & FEC_FLAG_BUFDESC_EX && unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { struct skb_shared_hwtstamps shhwtstamps; @@ -937,6 +948,7 @@ fec_enet_tx(struct net_device *ndev) if (status & BD_ENET_TX_DEF) ndev->stats.collisions++; + next: pkts_compl++; bytes_compl += skb->len; @@ -969,7 +981,6 @@ fec_enet_rx(struct net_device *ndev, int budget) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - unsigned short status; struct sk_buff *skb; ushort pkt_len; __u8 *data; @@ -987,6 +998,7 @@ fec_enet_rx(struct net_device *ndev, int budget) */ do { union bufdesc_u *bdp = fec_enet_rx_get(index, fep); + unsigned status, cbd_esc; status = bdp->bd.cbd_sc; if (status & BD_ENET_RX_EMPTY) @@ -1056,10 +1068,17 @@ fec_enet_rx(struct net_device *ndev, int budget) if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); + if (fep->flags & FEC_FLAG_BUFDESC_EX) { + cbd_esc = bdp->ebd.cbd_esc; + if (!(fep->flags & FEC_FLAG_RX_VLAN)) + cbd_esc &= ~BD_ENET_RX_VLAN; + } else { + cbd_esc = 0; + } + /* If this is a VLAN packet remove the VLAN Tag */ vlan_packet_rcvd = false; - if (fep->flags & FEC_FLAG_RX_VLAN && - bdp->ebd.cbd_esc & BD_ENET_RX_VLAN) { + if (cbd_esc & BD_ENET_RX_VLAN) { /* Push and remove the vlan tag */ struct vlan_hdr *vlan_header = (struct vlan_hdr *) (data + ETH_HLEN); @@ -1096,7 +1115,7 @@ fec_enet_rx(struct net_device *ndev, int budget) skb_hwtstamps(skb)); if (fep->flags & FEC_FLAG_RX_CSUM) { - if (!(bdp->ebd.cbd_esc & FLAG_RX_CSUM_ERROR)) { + if (!(cbd_esc & FLAG_RX_CSUM_ERROR)) { /* don't check it */ skb->ip_summed = CHECKSUM_UNNECESSARY; } else { |