Patch "net: fec: add ndo_select_queue to fix TX bandwidth fluctuations" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net: fec: add ndo_select_queue to fix TX bandwidth fluctuations

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-fec-add-ndo_select_queue-to-fix-tx-bandwidth-flu.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit c0aa37edc8b4ef705f6e4055f63c30567881ff28
Author: Fugang Duan <fugang.duan@xxxxxxx>
Date:   Mon Jun 21 14:27:37 2021 +0800

    net: fec: add ndo_select_queue to fix TX bandwidth fluctuations
    
    [ Upstream commit 52c4a1a85f4b346c39c896c0168f4a843b3385ff ]
    
    As we know that AVB is enabled by default, and the ENET IP design is
    queue 0 for best effort, queue 1&2 for AVB Class A&B. Bandwidth of each
    queue 1&2 set in driver is 50%, TX bandwidth fluctuated when selecting
    tx queues randomly with FEC_QUIRK_HAS_AVB quirk available.
    
    This patch adds ndo_select_queue callback to select queues for
    transmitting to fix this issue. It will always return queue 0 if this is
    not a vlan packet, and return queue 1 or 2 based on priority of vlan
    packet.
    
    You may complain that in fact we only use single queue for trasmitting
    if we are not targeted to VLAN. Yes, but seems we have no choice, since
    AVB is enabled when the driver probed, we can't switch this feature
    dynamicly. After compare multiple queues to single queue, TX throughput
    almost no improvement.
    
    One way we can implemet is to configure the driver to multiple queues
    with Round-robin scheme by default. Then add ndo_setup_tc callback to
    enable/disable AVB feature for users. Unfortunately, ENET AVB IP seems
    not follow the standard 802.1Qav spec. We only can program
    DMAnCFG[IDLE_SLOPE] field to calculate bandwidth fraction. And idle
    slope is restricted to certain valus (a total of 19). It's far away from
    CBS QDisc implemented in Linux TC framework. If you strongly suggest to do
    this, I think we only can support limited numbers of bandwidth and reject
    others, but it's really urgly and wried.
    
    With this patch, VLAN tagged packets route to queue 0/1/2 based on vlan
    priority; VLAN untagged packets route to queue 0.
    
    Tested-by: Frieder Schrempf <frieder.schrempf@xxxxxxxxxx>
    Reported-by: Frieder Schrempf <frieder.schrempf@xxxxxxxxxx>
    Signed-off-by: Fugang Duan <fugang.duan@xxxxxxx>
    Signed-off-by: Joakim Zhang <qiangqing.zhang@xxxxxxx>
    Reported-by: kernel test robot <lkp@xxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 960def41cc55..2cb73e850a32 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -75,6 +75,8 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
 
 #define DRIVER_NAME	"fec"
 
+static const u16 fec_enet_vlan_pri_to_queue[8] = {0, 0, 1, 1, 1, 2, 2, 2};
+
 /* Pause frame feild and FIFO threshold */
 #define FEC_ENET_FCE	(1 << 5)
 #define FEC_ENET_RSEM_V	0x84
@@ -3222,10 +3224,40 @@ static int fec_set_features(struct net_device *netdev,
 	return 0;
 }
 
+static u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb)
+{
+	struct vlan_ethhdr *vhdr;
+	unsigned short vlan_TCI = 0;
+
+	if (skb->protocol == htons(ETH_P_ALL)) {
+		vhdr = (struct vlan_ethhdr *)(skb->data);
+		vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+	}
+
+	return vlan_TCI;
+}
+
+static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
+				 struct net_device *sb_dev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	u16 vlan_tag;
+
+	if (!(fep->quirks & FEC_QUIRK_HAS_AVB))
+		return netdev_pick_tx(ndev, skb, NULL);
+
+	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_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= fec_timeout,



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux