| From fbfda80ab4457aa001ab1ccd323c1923c5c6e654 Mon Sep 17 00:00:00 2001 |
| From: Sudarsana Reddy Kalluru <skalluru@marvell.com> |
| Date: Wed, 6 Feb 2019 14:43:45 -0800 |
| Subject: qede: Fix system crash on configuring channels. |
| |
| [ Upstream commit 0aa4febb420d91df5b56b1864a2465765da85f4b ] |
| |
| Under heavy traffic load, when changing number of channels via |
| ethtool (ethtool -L) which will cause interface to be reloaded, |
| it was observed that some packets gets transmitted on old TX |
| channel/queue id which doesn't really exist after the channel |
| configuration leads to system crash. |
| |
| Add a safeguard in the driver by validating queue id through |
| ndo_select_queue() which is called before the ndo_start_xmit(). |
| |
| Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com> |
| Signed-off-by: Ariel Elior <aelior@marvell.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/qlogic/qede/qede.h | 3 +++ |
| drivers/net/ethernet/qlogic/qede/qede_fp.c | 13 +++++++++++++ |
| drivers/net/ethernet/qlogic/qede/qede_main.c | 3 +++ |
| 3 files changed, 19 insertions(+) |
| |
| diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h |
| index 6a4d266fb8e2..d242a5724069 100644 |
| --- a/drivers/net/ethernet/qlogic/qede/qede.h |
| +++ b/drivers/net/ethernet/qlogic/qede/qede.h |
| @@ -489,6 +489,9 @@ struct qede_reload_args { |
| |
| /* Datapath functions definition */ |
| netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev); |
| +u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb, |
| + struct net_device *sb_dev, |
| + select_queue_fallback_t fallback); |
| netdev_features_t qede_features_check(struct sk_buff *skb, |
| struct net_device *dev, |
| netdev_features_t features); |
| diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c |
| index 1a78027de071..a96da16f3404 100644 |
| --- a/drivers/net/ethernet/qlogic/qede/qede_fp.c |
| +++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c |
| @@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| return NETDEV_TX_OK; |
| } |
| |
| +u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb, |
| + struct net_device *sb_dev, |
| + select_queue_fallback_t fallback) |
| +{ |
| + struct qede_dev *edev = netdev_priv(dev); |
| + int total_txq; |
| + |
| + total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc; |
| + |
| + return QEDE_TSS_COUNT(edev) ? |
| + fallback(dev, skb, NULL) % total_txq : 0; |
| +} |
| + |
| /* 8B udp header + 8B base tunnel header + 32B option length */ |
| #define QEDE_MAX_TUN_HDR_LEN 48 |
| |
| diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c |
| index 46d0f2eaa0c0..f3d9c40c4115 100644 |
| --- a/drivers/net/ethernet/qlogic/qede/qede_main.c |
| +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c |
| @@ -631,6 +631,7 @@ static const struct net_device_ops qede_netdev_ops = { |
| .ndo_open = qede_open, |
| .ndo_stop = qede_close, |
| .ndo_start_xmit = qede_start_xmit, |
| + .ndo_select_queue = qede_select_queue, |
| .ndo_set_rx_mode = qede_set_rx_mode, |
| .ndo_set_mac_address = qede_set_mac_addr, |
| .ndo_validate_addr = eth_validate_addr, |
| @@ -666,6 +667,7 @@ static const struct net_device_ops qede_netdev_vf_ops = { |
| .ndo_open = qede_open, |
| .ndo_stop = qede_close, |
| .ndo_start_xmit = qede_start_xmit, |
| + .ndo_select_queue = qede_select_queue, |
| .ndo_set_rx_mode = qede_set_rx_mode, |
| .ndo_set_mac_address = qede_set_mac_addr, |
| .ndo_validate_addr = eth_validate_addr, |
| @@ -684,6 +686,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = { |
| .ndo_open = qede_open, |
| .ndo_stop = qede_close, |
| .ndo_start_xmit = qede_start_xmit, |
| + .ndo_select_queue = qede_select_queue, |
| .ndo_set_rx_mode = qede_set_rx_mode, |
| .ndo_set_mac_address = qede_set_mac_addr, |
| .ndo_validate_addr = eth_validate_addr, |
| -- |
| 2.19.1 |
| |