summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fec_main.c
diff options
context:
space:
mode:
authorFugang Duan <b38611@freescale.com>2014-10-10 16:25:26 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-23 16:42:26 +0300
commitaf8ae01b5a1f8cbea30e1fa6db8b8d9f104e34e9 (patch)
tree9a31b90cb804298326eb7d86f5735f00e9e37d63 /drivers/net/ethernet/freescale/fec_main.c
parent8428f73229415029c76fee3eb10d583443f8fde3 (diff)
MLK-11285-02 net:fec: add enet AVB Ubuntu Gstreamer demo support
Support Gstreamer AVB demo support. ring1 -> ClassA, ring2 -> ClassB, ring0 -> Best Effort For QoS: ring1 > ring2 > ring0 For bandwidth reverse: 50% bandwidth -> ClassA 33% bandwidth -> ClassB 17% bandwidth -> Best effort queue In general, ClassA run audio, ClassB run video. Since AVB demo use big bandwidth streaming, video cost more than 33Mbps bandwidth, and with Qos limitation: ClassA >= ClassB > Best effort, so we have to change ring2 bandwidth equal to ring1 bandwidth (50%). After validate on FPGA, AVB demo can work fine for audio and video. Signed-off-by: Fugang Duan <B38611@freescale.com> (cherry picked from commit 93d6579a7b3d2dafa721c835df5d5f7d30ed386e)
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8d94e721c47e..081887371faf 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -18,7 +18,7 @@
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2006 Macq Electronique SA.
*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
*/
#include <linux/module.h>
@@ -72,6 +72,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#define DRIVER_NAME "fec"
#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))
+static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2};
/* Pause frame feild and FIFO threshold */
#define FEC_ENET_FCE (1 << 5)
@@ -3106,10 +3107,42 @@ static int fec_set_features(struct net_device *netdev,
return 0;
}
+u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb)
+{
+ struct vlan_ethhdr *vhdr;
+ unsigned short vlan_TCI = 0;
+
+ if (skb->protocol == ntohs(ETH_P_ALL)) {
+ vhdr = (struct vlan_ethhdr *)(skb->data);
+ vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+ }
+
+ return vlan_TCI;
+}
+
+u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
+ u16 vlan_tag;
+
+ if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB))
+ return skb_tx_hash(ndev, skb);
+
+ vlan_tag = fec_enet_get_raw_vlan_tci(skb);
+ if (!vlan_tag)
+ return vlan_tag;
+
+ return fec_enet_vlan_pri_to_queue[vlan_tag >> 13];
+}
+
static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
+ .ndo_select_queue = fec_enet_select_queue,
.ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,