netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun
@ 2023-11-22 10:22 Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 1/5] net: wangxun: add flow control support Jiawen Wu
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Provide ethtool functions to operate pause param, ring param, coalesce
channel number and msglevel, for driver txgbe/ngbe.

This patch set needs to be applied base on commit 8ba2c459668c, which
was applied to upstream netdev/net.

Jiawen Wu (5):
  net: wangxun: add flow control support
  net: wangxun: add ethtool_ops for ring parameters
  net: wangxun: add coalesce options support
  net: wangxun: add ethtool_ops for channel number
  net: wangxun: add ethtool_ops for msglevel

 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 200 +++++++++++++
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |  18 ++
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 280 ++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_hw.h    |   1 +
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |  99 ++++++-
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |   2 +
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |  75 ++++-
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 101 +++++++
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c |  64 ++--
 drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c |   2 +
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h |   5 +
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    |  84 ++++++
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   |  47 ++-
 .../net/ethernet/wangxun/txgbe/txgbe_phy.c    |   4 +
 .../net/ethernet/wangxun/txgbe/txgbe_type.h   |   5 +
 15 files changed, 953 insertions(+), 34 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
@ 2023-11-22 10:22 ` Jiawen Wu
  2023-11-22 16:15   ` Andrew Lunn
  2023-11-22 10:22 ` [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters Jiawen Wu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Add support to set pause params with ethtool -A and get pause
params with ethtool -a, for ethernet driver txgbe and ngbe.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 186 ++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_hw.h    |   1 +
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |  43 ++++
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  |  32 +++
 drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c |   2 +
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    |  18 ++
 .../net/ethernet/wangxun/txgbe/txgbe_phy.c    |   4 +
 7 files changed, 286 insertions(+)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 533e912af089..40897419a970 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1158,6 +1158,81 @@ static void wx_set_rxpba(struct wx *wx)
 	wr32(wx, WX_TDM_PB_THRE(0), txpbthresh);
 }
 
+#define WX_ETH_FRAMING 20
+
+/**
+ * wx_hpbthresh - calculate high water mark for flow control
+ *
+ * @wx: board private structure to calculate for
+ **/
+static int wx_hpbthresh(struct wx *wx)
+{
+	struct net_device *dev = wx->netdev;
+	int link, tc, kb, marker;
+	u32 dv_id, rx_pba;
+
+	/* Calculate max LAN frame size */
+	link = dev->mtu + ETH_HLEN + ETH_FCS_LEN + WX_ETH_FRAMING;
+	tc = link;
+
+	/* Calculate delay value for device */
+	dv_id = WX_DV(link, tc);
+
+	/* Delay value is calculated in bit times convert to KB */
+	kb = WX_BT2KB(dv_id);
+	rx_pba = rd32(wx, WX_RDB_PB_SZ(0)) >> WX_RDB_PB_SZ_SHIFT;
+
+	marker = rx_pba - kb;
+
+	/* It is possible that the packet buffer is not large enough
+	 * to provide required headroom. In this case throw an error
+	 * to user and a do the best we can.
+	 */
+	if (marker < 0) {
+		dev_warn(&wx->pdev->dev,
+			 "Packet Buffer can not provide enough headroom to support flow control. Decrease MTU or number of traffic classes\n");
+		marker = tc + 1;
+	}
+
+	return marker;
+}
+
+/**
+ * wx_lpbthresh - calculate low water mark for flow control
+ *
+ * @wx: board private structure to calculate for
+ **/
+static int wx_lpbthresh(struct wx *wx)
+{
+	struct net_device *dev = wx->netdev;
+	u32 dv_id;
+	int tc;
+
+	/* Calculate max LAN frame size */
+	tc = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
+
+	/* Calculate delay value for device */
+	dv_id = WX_LOW_DV(tc);
+
+	/* Delay value is calculated in bit times convert to KB */
+	return WX_BT2KB(dv_id);
+}
+
+/**
+ * wx_pbthresh_setup - calculate and setup high low water marks
+ *
+ * @wx: board private structure to calculate for
+ **/
+static void wx_pbthresh_setup(struct wx *wx)
+{
+	wx->fc.high_water = wx_hpbthresh(wx);
+	wx->fc.low_water = wx_lpbthresh(wx);
+
+	/* Low water marks must not be larger than high water marks */
+	if (wx->fc.low_water > wx->fc.high_water)
+		wx->fc.low_water = 0;
+}
+
 static void wx_configure_port(struct wx *wx)
 {
 	u32 value, i;
@@ -1584,6 +1659,7 @@ static void wx_configure_isb(struct wx *wx)
 void wx_configure(struct wx *wx)
 {
 	wx_set_rxpba(wx);
+	wx_pbthresh_setup(wx);
 	wx_configure_port(wx);
 
 	wx_set_rx_mode(wx->netdev);
@@ -1785,6 +1861,11 @@ int wx_sw_init(struct wx *wx)
 		return -ENOMEM;
 	}
 
+	wx->fc.pause_time = WX_DEFAULT_FCPAUSE;
+	wx->fc.disable_fc_autoneg = false;
+	wx->fc.rx_pause = true;
+	wx->fc.tx_pause = true;
+
 	return 0;
 }
 EXPORT_SYMBOL(wx_sw_init);
@@ -2003,6 +2084,111 @@ int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
 }
 EXPORT_SYMBOL(wx_vlan_rx_kill_vid);
 
+static void wx_enable_rx_drop(struct wx *wx, struct wx_ring *ring)
+{
+	u16 reg_idx = ring->reg_idx;
+	u32 srrctl;
+
+	srrctl = rd32(wx, WX_PX_RR_CFG(reg_idx));
+	srrctl |= WX_PX_RR_CFG_DROP_EN;
+
+	wr32(wx, WX_PX_RR_CFG(reg_idx), srrctl);
+}
+
+static void wx_disable_rx_drop(struct wx *wx, struct wx_ring *ring)
+{
+	u16 reg_idx = ring->reg_idx;
+	u32 srrctl;
+
+	srrctl = rd32(wx, WX_PX_RR_CFG(reg_idx));
+	srrctl &= ~WX_PX_RR_CFG_DROP_EN;
+
+	wr32(wx, WX_PX_RR_CFG(reg_idx), srrctl);
+}
+
+/**
+ *  wx_fc_enable - Enable flow control
+ *  @wx: pointer to hardware structure
+ *
+ *  Enable flow control according to the current settings.
+ **/
+int wx_fc_enable(struct wx *wx)
+{
+	u32 mflcn_reg, fccfg_reg, reg;
+	u32 fcrtl, fcrth;
+	int i;
+
+	/* Validate the water mark configuration */
+	if (!wx->fc.pause_time)
+		return -EINVAL;
+
+	/* Low water mark of zero causes XOFF floods */
+	if (wx->fc.tx_pause && wx->fc.high_water) {
+		if (!wx->fc.low_water || wx->fc.low_water >= wx->fc.high_water) {
+			wx_err(wx, "Invalid water mark configuration\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Disable any previous flow control settings */
+	mflcn_reg = rd32(wx, WX_MAC_RX_FLOW_CTRL);
+	mflcn_reg &= ~WX_MAC_RX_FLOW_CTRL_RFE;
+
+	fccfg_reg = rd32(wx, WX_RDB_RFCC);
+	fccfg_reg &= ~WX_RDB_RFCC_RFCE_802_3X;
+
+	if (wx->fc.rx_pause)
+		mflcn_reg |= WX_MAC_RX_FLOW_CTRL_RFE;
+	if (wx->fc.tx_pause)
+		fccfg_reg |= WX_RDB_RFCC_RFCE_802_3X;
+
+	/* Set 802.3x based flow control settings. */
+	wr32(wx, WX_MAC_RX_FLOW_CTRL, mflcn_reg);
+	wr32(wx, WX_RDB_RFCC, fccfg_reg);
+
+	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
+	if (wx->fc.tx_pause && wx->fc.high_water) {
+		fcrtl = (wx->fc.low_water << 10) | WX_RDB_RFCL_XONE;
+		wr32(wx, WX_RDB_RFCL, fcrtl);
+		fcrth = (wx->fc.high_water << 10) | WX_RDB_RFCH_XOFFE;
+	} else {
+		wr32(wx, WX_RDB_RFCL, 0);
+		/* In order to prevent Tx hangs when the internal Tx
+		 * switch is enabled we must set the high water mark
+		 * to the Rx packet buffer size - 24KB.  This allows
+		 * the Tx switch to function even under heavy Rx
+		 * workloads.
+		 */
+		fcrth = rd32(wx, WX_RDB_PB_SZ(0)) - 24576;
+	}
+
+	wr32(wx, WX_RDB_RFCH, fcrth);
+
+	/* Configure pause time */
+	reg = wx->fc.pause_time * 0x00010001;
+	wr32(wx, WX_RDB_RFCV, reg);
+
+	/* Configure flow control refresh threshold value */
+	wr32(wx, WX_RDB_RFCRT, wx->fc.pause_time / 2);
+
+	/*  We should set the drop enable bit if:
+	 *  Number of Rx queues > 1 and flow control is disabled
+	 *
+	 *  This allows us to avoid head of line blocking for security
+	 *  and performance reasons.
+	 */
+	if (wx->num_rx_queues > 1 && !wx->fc.tx_pause) {
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx_enable_rx_drop(wx, wx->rx_ring[i]);
+	} else {
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx_disable_rx_drop(wx, wx->rx_ring[i]);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_fc_enable);
+
 /**
  * wx_update_stats - Update the board statistics counters.
  * @wx: board private structure
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
index 12c20a7c364d..480d596cb70f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
@@ -41,6 +41,7 @@ int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
 int wx_sw_init(struct wx *wx);
 int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
 int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
+int wx_fc_enable(struct wx *wx);
 void wx_update_stats(struct wx *wx);
 void wx_clear_hw_cntrs(struct wx *wx);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 165e82de772e..dc217437ec56 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -130,6 +130,15 @@
 #define WX_RDB_PFCMACDAH             0x19214
 #define WX_RDB_LXOFFTXC              0x19218
 #define WX_RDB_LXONTXC               0x1921C
+/* Flow Control Registers */
+#define WX_RDB_RFCV                  0x19200
+#define WX_RDB_RFCL                  0x19220
+#define WX_RDB_RFCL_XONE             BIT(31)
+#define WX_RDB_RFCH                  0x19260
+#define WX_RDB_RFCH_XOFFE            BIT(31)
+#define WX_RDB_RFCRT                 0x192A0
+#define WX_RDB_RFCC                  0x192A4
+#define WX_RDB_RFCC_RFCE_802_3X      BIT(3)
 /* ring assignment */
 #define WX_RDB_PL_CFG(_i)            (0x19300 + ((_i) * 4))
 #define WX_RDB_PL_CFG_L4HDR          BIT(1)
@@ -330,6 +339,7 @@ enum WX_MSCA_CMD_value {
 #define WX_PX_MPRC(_i)               (0x01020 + ((_i) * 0x40))
 /* PX_RR_CFG bit definitions */
 #define WX_PX_RR_CFG_VLAN            BIT(31)
+#define WX_PX_RR_CFG_DROP_EN         BIT(30)
 #define WX_PX_RR_CFG_SPLIT_MODE      BIT(26)
 #define WX_PX_RR_CFG_RR_THER_SHIFT   16
 #define WX_PX_RR_CFG_RR_HDR_SZ       GENMASK(15, 12)
@@ -367,6 +377,29 @@ enum WX_MSCA_CMD_value {
 #define WX_MAC_STATE_MODIFIED        0x2
 #define WX_MAC_STATE_IN_USE          0x4
 
+/* BitTimes (BT) conversion */
+#define WX_BT2KB(BT)         (((BT) + (8 * 1024 - 1)) / (8 * 1024))
+#define WX_B2BT(BT)          ((BT) * 8)
+/* Calculate Interface Delay */
+#define WX_PHY_D     12800
+#define WX_MAC_D     4096
+#define WX_XAUI_D    (2 * 1024)
+#define WX_ID        (WX_MAC_D + WX_XAUI_D + WX_PHY_D)
+/* Calculate PCI Bus delay for low thresholds */
+#define WX_PCI_DELAY 10000
+
+/* Calculate delay value in bit times */
+#define WX_DV(_max_frame_link, _max_frame_tc) \
+	((36 * (WX_B2BT(_max_frame_link) + 672 + (2 * 5556) + (2 * WX_ID) + 6144) / \
+	  25 + 1) +  2 * WX_B2BT(_max_frame_tc))
+
+/* Calculate low threshold delay values */
+#define WX_LOW_DV(_max_frame_tc) \
+	(2 * (2 * WX_B2BT(_max_frame_tc) + (36 * WX_PCI_DELAY / 25) + 1))
+
+/* flow control */
+#define WX_DEFAULT_FCPAUSE           0xFFFF
+
 #define WX_MAX_RXD                   8192
 #define WX_MAX_TXD                   8192
 
@@ -880,6 +913,15 @@ enum wx_isb_idx {
 	WX_ISB_MAX
 };
 
+struct wx_fc_info {
+	u32 high_water; /* Flow Ctrl High-water */
+	u32 low_water; /* Flow Ctrl Low-water */
+	u16 pause_time; /* Flow Control Pause timer */
+	bool disable_fc_autoneg; /* Do not autonegotiate FC */
+	bool tx_pause;
+	bool rx_pause;
+};
+
 /* Statistics counters collected by the MAC */
 struct wx_hw_stats {
 	u64 gprc;
@@ -920,6 +962,7 @@ struct wx {
 	enum sp_media_type media_type;
 	struct wx_eeprom_info eeprom;
 	struct wx_addr_filter_info addr_ctrl;
+	struct wx_fc_info fc;
 	struct wx_mac_addr *mac_table;
 	u16 device_id;
 	u16 vendor_id;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index afbdf6919071..5baa89118600 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -41,6 +41,36 @@ static int ngbe_set_wol(struct net_device *netdev,
 	return 0;
 }
 
+static void ngbe_get_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	pause->autoneg = !wx->fc.disable_fc_autoneg;
+	pause->tx_pause = wx->fc.tx_pause;
+	pause->rx_pause = wx->fc.rx_pause;
+}
+
+static int ngbe_set_pauseparam(struct net_device *netdev,
+			       struct ethtool_pauseparam *pause)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	if (!wx->phydev)
+		return -ENODEV;
+
+	if (!phy_validate_pause(wx->phydev, pause))
+		return -EINVAL;
+
+	wx->fc.disable_fc_autoneg = !pause->autoneg;
+	wx->fc.tx_pause = pause->tx_pause;
+	wx->fc.rx_pause = pause->rx_pause;
+
+	phy_set_asym_pause(wx->phydev, pause->rx_pause, pause->tx_pause);
+
+	return 0;
+}
+
 static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
@@ -54,6 +84,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_ethtool_stats	= wx_get_ethtool_stats,
 	.get_eth_mac_stats	= wx_get_mac_stats,
 	.get_pause_stats	= wx_get_pause_stats,
+	.get_pauseparam		= ngbe_get_pauseparam,
+	.set_pauseparam		= ngbe_set_pauseparam,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c
index 6302ecca71bb..2fc8e526e983 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c
@@ -62,6 +62,8 @@ static void ngbe_handle_link_change(struct net_device *dev)
 	struct phy_device *phydev;
 	u32 lan_speed, reg;
 
+	wx_fc_enable(wx);
+
 	phydev = wx->phydev;
 	if (!(wx->link != phydev->link ||
 	      wx->speed != phydev->speed ||
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 3f336a088e43..8812d92d8b58 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -33,6 +33,22 @@ static int txgbe_set_link_ksettings(struct net_device *netdev,
 	return phylink_ethtool_ksettings_set(txgbe->phylink, cmd);
 }
 
+static void txgbe_get_pauseparam(struct net_device *netdev,
+				 struct ethtool_pauseparam *pause)
+{
+	struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+	phylink_ethtool_get_pauseparam(txgbe->phylink, pause);
+}
+
+static int txgbe_set_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+	return phylink_ethtool_set_pauseparam(txgbe->phylink, pause);
+}
+
 static const struct ethtool_ops txgbe_ethtool_ops = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.nway_reset		= txgbe_nway_reset,
@@ -44,6 +60,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.get_ethtool_stats	= wx_get_ethtool_stats,
 	.get_eth_mac_stats	= wx_get_mac_stats,
 	.get_pause_stats	= wx_get_pause_stats,
+	.get_pauseparam		= txgbe_get_pauseparam,
+	.set_pauseparam		= txgbe_set_pauseparam,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
index b6c06adb8656..472523f4a8e4 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -189,6 +189,10 @@ static void txgbe_mac_link_up(struct phylink_config *config,
 	struct wx *wx = netdev_priv(to_net_dev(config->dev));
 	u32 txcfg, wdg;
 
+	wx->fc.tx_pause = tx_pause;
+	wx->fc.rx_pause = rx_pause;
+	wx_fc_enable(wx);
+
 	txcfg = rd32(wx, WX_MAC_TX_CFG);
 	txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK;
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters
  2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 1/5] net: wangxun: add flow control support Jiawen Wu
@ 2023-11-22 10:22 ` Jiawen Wu
  2023-11-22 16:24   ` Andrew Lunn
  2023-11-22 10:22 ` [PATCH net-next 3/5] net: wangxun: add coalesce options support Jiawen Wu
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Support to query RX/TX depth with ethtool -g, and change RX/TX depth
with ethtool -G.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 18 +++++
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |  4 +
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   | 76 +++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |  1 +
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |  6 ++
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 48 ++++++++++++
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c |  4 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h |  3 +
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    | 45 +++++++++++
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   |  8 +-
 .../net/ethernet/wangxun/txgbe/txgbe_type.h   |  3 +
 11 files changed, 213 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index ddc5f6d20b9c..2a09d1df3b0f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -185,3 +185,21 @@ void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
 	}
 }
 EXPORT_SYMBOL(wx_get_drvinfo);
+
+void wx_get_ringparam(struct net_device *netdev,
+		      struct ethtool_ringparam *ring,
+		      struct kernel_ethtool_ringparam *kernel_ring,
+		      struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	ring->rx_max_pending = WX_MAX_RXD;
+	ring->tx_max_pending = WX_MAX_TXD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = wx->rx_ring_count;
+	ring->tx_pending = wx->tx_ring_count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+EXPORT_SYMBOL(wx_get_ringparam);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
index 16d1a09369a6..77545d0eec56 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
@@ -13,4 +13,8 @@ void wx_get_mac_stats(struct net_device *netdev,
 void wx_get_pause_stats(struct net_device *netdev,
 			struct ethtool_pause_stats *stats);
 void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info);
+void wx_get_ringparam(struct net_device *netdev,
+		      struct ethtool_ringparam *ring,
+		      struct kernel_ethtool_ringparam *kernel_ring,
+		      struct netlink_ext_ack *extack);
 #endif /* _WX_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 2823861e5a92..6645aff415f8 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -2741,4 +2741,80 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
 }
 EXPORT_SYMBOL(wx_set_features);
 
+int wx_set_ring(struct wx *wx, u32 new_tx_count, u32 new_rx_count)
+{
+	struct wx_ring *temp_ring;
+	int i, err = 0;
+
+	/* allocate temporary buffer to store rings in */
+	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+	temp_ring = vmalloc(i * sizeof(struct wx_ring));
+
+	if (!temp_ring)
+		return -ENOMEM;
+
+	/* Setup new Tx resources and free the old Tx resources in that order.
+	 * We can then assign the new resources to the rings via a memcpy.
+	 * The advantage to this approach is that we are guaranteed to still
+	 * have resources even in the case of an allocation failure.
+	 */
+	if (new_tx_count != wx->tx_ring_count) {
+		for (i = 0; i < wx->num_tx_queues; i++) {
+			memcpy(&temp_ring[i], wx->tx_ring[i],
+			       sizeof(struct wx_ring));
+
+			temp_ring[i].count = new_tx_count;
+			err = wx_setup_tx_resources(&temp_ring[i]);
+			if (err) {
+				while (i) {
+					i--;
+					wx_free_tx_resources(&temp_ring[i]);
+				}
+				goto err_setup;
+			}
+		}
+
+		for (i = 0; i < wx->num_tx_queues; i++) {
+			wx_free_tx_resources(wx->tx_ring[i]);
+
+			memcpy(wx->tx_ring[i], &temp_ring[i],
+			       sizeof(struct wx_ring));
+		}
+
+		wx->tx_ring_count = new_tx_count;
+	}
+
+	/* Repeat the process for the Rx rings if needed */
+	if (new_rx_count != wx->rx_ring_count) {
+		for (i = 0; i < wx->num_rx_queues; i++) {
+			memcpy(&temp_ring[i], wx->rx_ring[i],
+			       sizeof(struct wx_ring));
+
+			temp_ring[i].count = new_rx_count;
+			err = wx_setup_rx_resources(&temp_ring[i]);
+			if (err) {
+				while (i) {
+					i--;
+					wx_free_rx_resources(&temp_ring[i]);
+				}
+				goto err_setup;
+			}
+		}
+
+		for (i = 0; i < wx->num_rx_queues; i++) {
+			wx_free_rx_resources(wx->rx_ring[i]);
+			memcpy(wx->rx_ring[i], &temp_ring[i],
+			       sizeof(struct wx_ring));
+		}
+
+		wx->rx_ring_count = new_rx_count;
+	}
+
+err_setup:
+	vfree(temp_ring);
+
+	return err;
+}
+EXPORT_SYMBOL(wx_set_ring);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index df1f4a5951f0..b4bf11684a1d 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -29,5 +29,6 @@ int wx_setup_resources(struct wx *wx);
 void wx_get_stats64(struct net_device *netdev,
 		    struct rtnl_link_stats64 *stats);
 int wx_set_features(struct net_device *netdev, netdev_features_t features);
+int wx_set_ring(struct wx *wx, u32 new_tx_count, u32 new_rx_count);
 
 #endif /* _NGBE_LIB_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index dc217437ec56..bdb2c3d33197 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -402,6 +402,12 @@ enum WX_MSCA_CMD_value {
 
 #define WX_MAX_RXD                   8192
 #define WX_MAX_TXD                   8192
+#define WX_MIN_RXD                   128
+#define WX_MIN_TXD                   128
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define WX_REQ_RX_DESCRIPTOR_MULTIPLE   8
+#define WX_REQ_TX_DESCRIPTOR_MULTIPLE   8
 
 #define WX_MAX_JUMBO_FRAME_SIZE      9432 /* max payload 9414 */
 #define VMDQ_P(p)                    p
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 5baa89118600..42bd82b03488 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -7,7 +7,10 @@
 
 #include "../libwx/wx_ethtool.h"
 #include "../libwx/wx_type.h"
+#include "../libwx/wx_lib.h"
+#include "../libwx/wx_hw.h"
 #include "ngbe_ethtool.h"
+#include "ngbe_type.h"
 
 static void ngbe_get_wol(struct net_device *netdev,
 			 struct ethtool_wolinfo *wol)
@@ -71,6 +74,49 @@ static int ngbe_set_pauseparam(struct net_device *netdev,
 	return 0;
 }
 
+static int ngbe_set_ringparam(struct net_device *netdev,
+			      struct ethtool_ringparam *ring,
+			      struct kernel_ethtool_ringparam *kernel_ring,
+			      struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+	u32 new_rx_count, new_tx_count;
+	int i, err = 0;
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+		return -EINVAL;
+
+	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
+	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+	if (new_tx_count == wx->tx_ring_count &&
+	    new_rx_count == wx->rx_ring_count)
+		return 0;
+
+	if (!netif_running(wx->netdev)) {
+		for (i = 0; i < wx->num_tx_queues; i++)
+			wx->tx_ring[i]->count = new_tx_count;
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx->rx_ring[i]->count = new_rx_count;
+		wx->tx_ring_count = new_tx_count;
+		wx->rx_ring_count = new_rx_count;
+
+		return 0;
+	}
+
+	ngbe_down(wx);
+
+	err = wx_set_ring(wx, new_tx_count, new_rx_count);
+
+	wx_configure(wx);
+	ngbe_up(wx);
+
+	return err;
+}
+
 static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
@@ -86,6 +132,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_pause_stats	= wx_get_pause_stats,
 	.get_pauseparam		= ngbe_get_pauseparam,
 	.set_pauseparam		= ngbe_set_pauseparam,
+	.get_ringparam		= wx_get_ringparam,
+	.set_ringparam		= ngbe_set_ringparam,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 8db804543e66..0c0b2f7bdf74 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -334,7 +334,7 @@ static void ngbe_disable_device(struct wx *wx)
 	wx_update_stats(wx);
 }
 
-static void ngbe_down(struct wx *wx)
+void ngbe_down(struct wx *wx)
 {
 	phy_stop(wx->phydev);
 	ngbe_disable_device(wx);
@@ -342,7 +342,7 @@ static void ngbe_down(struct wx *wx)
 	wx_clean_all_rx_rings(wx);
 }
 
-static void ngbe_up(struct wx *wx)
+void ngbe_up(struct wx *wx)
 {
 	wx_configure_vectors(wx);
 
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index ff754d69bdf6..0a98080a197a 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -130,4 +130,7 @@
 
 extern char ngbe_driver_name[];
 
+void ngbe_down(struct wx *wx);
+void ngbe_up(struct wx *wx);
+
 #endif /* _NGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 8812d92d8b58..abbccef81557 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -7,6 +7,7 @@
 
 #include "../libwx/wx_ethtool.h"
 #include "../libwx/wx_type.h"
+#include "../libwx/wx_lib.h"
 #include "txgbe_type.h"
 #include "txgbe_ethtool.h"
 
@@ -49,6 +50,48 @@ static int txgbe_set_pauseparam(struct net_device *netdev,
 	return phylink_ethtool_set_pauseparam(txgbe->phylink, pause);
 }
 
+static int txgbe_set_ringparam(struct net_device *netdev,
+			       struct ethtool_ringparam *ring,
+			       struct kernel_ethtool_ringparam *kernel_ring,
+			       struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+	u32 new_rx_count, new_tx_count;
+	int i, err = 0;
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+		return -EINVAL;
+
+	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
+	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+	if (new_tx_count == wx->tx_ring_count &&
+	    new_rx_count == wx->rx_ring_count)
+		return 0;
+
+	if (!netif_running(wx->netdev)) {
+		for (i = 0; i < wx->num_tx_queues; i++)
+			wx->tx_ring[i]->count = new_tx_count;
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx->rx_ring[i]->count = new_rx_count;
+		wx->tx_ring_count = new_tx_count;
+		wx->rx_ring_count = new_rx_count;
+
+		return 0;
+	}
+
+	txgbe_down(wx);
+
+	err = wx_set_ring(wx, new_tx_count, new_rx_count);
+
+	txgbe_up(wx);
+
+	return err;
+}
+
 static const struct ethtool_ops txgbe_ethtool_ops = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.nway_reset		= txgbe_nway_reset,
@@ -62,6 +105,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.get_pause_stats	= wx_get_pause_stats,
 	.get_pauseparam		= txgbe_get_pauseparam,
 	.set_pauseparam		= txgbe_set_pauseparam,
+	.get_ringparam		= wx_get_ringparam,
+	.set_ringparam		= txgbe_set_ringparam,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 526250102db2..9b1b92fa318f 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -290,7 +290,7 @@ static void txgbe_disable_device(struct wx *wx)
 	wx_update_stats(wx);
 }
 
-static void txgbe_down(struct wx *wx)
+void txgbe_down(struct wx *wx)
 {
 	struct txgbe *txgbe = netdev_to_txgbe(wx->netdev);
 
@@ -302,6 +302,12 @@ static void txgbe_down(struct wx *wx)
 	wx_clean_all_rx_rings(wx);
 }
 
+void txgbe_up(struct wx *wx)
+{
+	wx_configure(wx);
+	txgbe_up_complete(wx);
+}
+
 /**
  *  txgbe_init_type_code - Initialize the shared code
  *  @wx: pointer to hardware structure
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 3ba9ce43f394..13a2f3f53c39 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -129,6 +129,9 @@
 
 extern char txgbe_driver_name[];
 
+void txgbe_down(struct wx *wx);
+void txgbe_up(struct wx *wx);
+
 static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev)
 {
 	struct wx *wx = netdev_priv(netdev);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next 3/5] net: wangxun: add coalesce options support
  2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 1/5] net: wangxun: add flow control support Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters Jiawen Wu
@ 2023-11-22 10:22 ` Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number Jiawen Wu
  2023-11-22 10:22 ` [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel Jiawen Wu
  4 siblings, 0 replies; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Support to show RX/TX coalesce with ethtool -c and set RX/TX
coalesce with ethtool -C.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 101 ++++++++++++++++++
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |   8 ++
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |   2 +-
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |   1 +
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |   1 +
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  |   4 +
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    |   4 +
 7 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 2a09d1df3b0f..abd2f4c92654 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -8,6 +8,7 @@
 #include "wx_type.h"
 #include "wx_ethtool.h"
 #include "wx_hw.h"
+#include "wx_lib.h"
 
 struct wx_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -203,3 +204,103 @@ void wx_get_ringparam(struct net_device *netdev,
 	ring->rx_jumbo_pending = 0;
 }
 EXPORT_SYMBOL(wx_get_ringparam);
+
+int wx_get_coalesce(struct net_device *netdev,
+		    struct ethtool_coalesce *ec,
+		    struct kernel_ethtool_coalesce *kernel_coal,
+		    struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	ec->tx_max_coalesced_frames_irq = wx->tx_work_limit;
+	/* only valid if in constant ITR mode */
+	if (wx->rx_itr_setting <= 1)
+		ec->rx_coalesce_usecs = wx->rx_itr_setting;
+	else
+		ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2;
+
+	/* if in mixed tx/rx queues per vector mode, report only rx settings */
+	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
+		return 0;
+
+	/* only valid if in constant ITR mode */
+	if (wx->tx_itr_setting <= 1)
+		ec->tx_coalesce_usecs = wx->tx_itr_setting;
+	else
+		ec->tx_coalesce_usecs = wx->tx_itr_setting >> 2;
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_get_coalesce);
+
+int wx_set_coalesce(struct net_device *netdev,
+		    struct ethtool_coalesce *ec,
+		    struct kernel_ethtool_coalesce *kernel_coal,
+		    struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+	u16 tx_itr_param, rx_itr_param;
+	struct wx_q_vector *q_vector;
+	u16 max_eitr;
+	int i;
+
+	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count) {
+		/* reject Tx specific changes in case of mixed RxTx vectors */
+		if (ec->tx_coalesce_usecs)
+			return -EINVAL;
+	}
+
+	if (ec->tx_max_coalesced_frames_irq)
+		wx->tx_work_limit = ec->tx_max_coalesced_frames_irq;
+
+	if (wx->mac.type == wx_mac_sp)
+		max_eitr = WX_SP_MAX_EITR;
+	else
+		max_eitr = WX_EM_MAX_EITR;
+
+	if ((ec->rx_coalesce_usecs > (max_eitr >> 2)) ||
+	    (ec->tx_coalesce_usecs > (max_eitr >> 2)))
+		return -EINVAL;
+
+	if (ec->rx_coalesce_usecs > 1)
+		wx->rx_itr_setting = ec->rx_coalesce_usecs << 2;
+	else
+		wx->rx_itr_setting = ec->rx_coalesce_usecs;
+
+	if (wx->rx_itr_setting == 1)
+		rx_itr_param = WX_20K_ITR;
+	else
+		rx_itr_param = wx->rx_itr_setting;
+
+	if (ec->tx_coalesce_usecs > 1)
+		wx->tx_itr_setting = ec->tx_coalesce_usecs << 2;
+	else
+		wx->tx_itr_setting = ec->tx_coalesce_usecs;
+
+	if (wx->tx_itr_setting == 1) {
+		if (wx->mac.type == wx_mac_sp)
+			tx_itr_param = WX_12K_ITR;
+		else
+			tx_itr_param = WX_20K_ITR;
+	} else {
+		tx_itr_param = wx->tx_itr_setting;
+	}
+
+	/* mixed Rx/Tx */
+	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
+		wx->tx_itr_setting = wx->rx_itr_setting;
+
+	for (i = 0; i < wx->num_q_vectors; i++) {
+		q_vector = wx->q_vector[i];
+		if (q_vector->tx.count && !q_vector->rx.count)
+			/* tx only */
+			q_vector->itr = tx_itr_param;
+		else
+			/* rx only or mixed */
+			q_vector->itr = rx_itr_param;
+		wx_write_eitr(q_vector);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_set_coalesce);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
index 77545d0eec56..3a80f8e63719 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
@@ -17,4 +17,12 @@ void wx_get_ringparam(struct net_device *netdev,
 		      struct ethtool_ringparam *ring,
 		      struct kernel_ethtool_ringparam *kernel_ring,
 		      struct netlink_ext_ack *extack);
+int wx_get_coalesce(struct net_device *netdev,
+		    struct ethtool_coalesce *ec,
+		    struct kernel_ethtool_coalesce *kernel_coal,
+		    struct netlink_ext_ack *extack);
+int wx_set_coalesce(struct net_device *netdev,
+		    struct ethtool_coalesce *ec,
+		    struct kernel_ethtool_coalesce *kernel_coal,
+		    struct netlink_ext_ack *extack);
 #endif /* _WX_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 6645aff415f8..9eb9ab8fe581 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -2150,7 +2150,7 @@ static void wx_set_ivar(struct wx *wx, s8 direction,
  * when it needs to update EITR registers at runtime.  Hardware
  * specific quirks/differences are taken care of here.
  */
-static void wx_write_eitr(struct wx_q_vector *q_vector)
+void wx_write_eitr(struct wx_q_vector *q_vector)
 {
 	struct wx *wx = q_vector->wx;
 	int v_idx = q_vector->v_idx;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index b4bf11684a1d..159d2e34ced9 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -21,6 +21,7 @@ void wx_free_irq(struct wx *wx);
 int wx_setup_isb_resources(struct wx *wx);
 void wx_free_isb_resources(struct wx *wx);
 u32 wx_misc_isb(struct wx *wx, enum wx_isb_idx idx);
+void wx_write_eitr(struct wx_q_vector *q_vector);
 void wx_configure_vectors(struct wx *wx);
 void wx_clean_all_rx_rings(struct wx *wx);
 void wx_clean_all_tx_rings(struct wx *wx);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index bdb2c3d33197..8c795f908d1e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -314,6 +314,7 @@ enum WX_MSCA_CMD_value {
 #define WX_PX_IVAR_ALLOC_VAL         0x80 /* Interrupt Allocation valid */
 #define WX_7K_ITR                    595
 #define WX_12K_ITR                   336
+#define WX_20K_ITR                   200
 #define WX_SP_MAX_EITR               0x00000FF8U
 #define WX_EM_MAX_EITR               0x00007FFCU
 
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 42bd82b03488..712e0308c397 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -118,6 +118,8 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 }
 
 static const struct ethtool_ops ngbe_ethtool_ops = {
+	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
 	.get_drvinfo		= wx_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
@@ -134,6 +136,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.set_pauseparam		= ngbe_set_pauseparam,
 	.get_ringparam		= wx_get_ringparam,
 	.set_ringparam		= ngbe_set_ringparam,
+	.get_coalesce		= wx_get_coalesce,
+	.set_coalesce		= wx_set_coalesce,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index abbccef81557..fe055b006a4e 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -93,6 +93,8 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 }
 
 static const struct ethtool_ops txgbe_ethtool_ops = {
+	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
 	.get_drvinfo		= wx_get_drvinfo,
 	.nway_reset		= txgbe_nway_reset,
 	.get_link		= ethtool_op_get_link,
@@ -107,6 +109,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.set_pauseparam		= txgbe_set_pauseparam,
 	.get_ringparam		= wx_get_ringparam,
 	.set_ringparam		= txgbe_set_ringparam,
+	.get_coalesce		= wx_get_coalesce,
+	.set_coalesce		= wx_set_coalesce,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number
  2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
                   ` (2 preceding siblings ...)
  2023-11-22 10:22 ` [PATCH net-next 3/5] net: wangxun: add coalesce options support Jiawen Wu
@ 2023-11-22 10:22 ` Jiawen Wu
  2023-11-22 16:35   ` Andrew Lunn
  2023-11-22 10:22 ` [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel Jiawen Wu
  4 siblings, 1 reply; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Add support to get RX/TX queue number with ethtool -l, and set RX/TX
queue number with ethtool -L.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 65 +++++++++++++
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |  4 +
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 94 +++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   | 21 ++++-
 drivers/net/ethernet/wangxun/libwx/wx_type.h  | 25 ++++-
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 15 +++
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 60 +++++++-----
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h |  2 +
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    | 15 +++
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   | 39 ++++++++
 .../net/ethernet/wangxun/txgbe/txgbe_type.h   |  2 +
 11 files changed, 312 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index abd2f4c92654..4e467aa1cc19 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -304,3 +304,68 @@ int wx_set_coalesce(struct net_device *netdev,
 	return 0;
 }
 EXPORT_SYMBOL(wx_set_coalesce);
+
+static unsigned int wx_max_channels(struct wx *wx)
+{
+	unsigned int max_combined;
+
+	if (!(wx->msix_entries)) {
+		/* We only support one q_vector without MSI-X */
+		max_combined = 1;
+	} else {
+		/* support up to max allowed queues with RSS */
+		if (wx->mac.type == wx_mac_sp)
+			max_combined = 63;
+		else
+			max_combined = 8;
+	}
+
+	return max_combined;
+}
+
+void wx_get_channels(struct net_device *dev,
+		     struct ethtool_channels *ch)
+{
+	struct wx *wx = netdev_priv(dev);
+
+	/* report maximum channels */
+	ch->max_combined = wx_max_channels(wx);
+
+	/* report info for other vector */
+	if (wx->msix_entries) {
+		ch->max_other = 1;
+		ch->other_count = 1;
+	}
+
+	/* record RSS queues */
+	ch->combined_count = wx->ring_feature[RING_F_RSS].indices;
+
+	/* nothing else to report if RSS is disabled */
+	if (ch->combined_count == 1)
+		return;
+}
+EXPORT_SYMBOL(wx_get_channels);
+
+int wx_set_channels(struct net_device *dev,
+		    struct ethtool_channels *ch)
+{
+	unsigned int count = ch->combined_count;
+	struct wx *wx = netdev_priv(dev);
+
+	/* verify they are not requesting separate vectors */
+	if (!count || ch->rx_count || ch->tx_count)
+		return -EINVAL;
+
+	/* verify other_count has not changed */
+	if (ch->other_count != 1)
+		return -EINVAL;
+
+	/* verify the number of channels does not exceed hardware limits */
+	if (count > wx_max_channels(wx))
+		return -EINVAL;
+
+	wx->ring_feature[RING_F_RSS].limit = count;
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_set_channels);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
index 3a80f8e63719..5b5af3689c04 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
@@ -25,4 +25,8 @@ int wx_set_coalesce(struct net_device *netdev,
 		    struct ethtool_coalesce *ec,
 		    struct kernel_ethtool_coalesce *kernel_coal,
 		    struct netlink_ext_ack *extack);
+void wx_get_channels(struct net_device *dev,
+		     struct ethtool_channels *ch);
+int wx_set_channels(struct net_device *dev,
+		    struct ethtool_channels *ch);
 #endif /* _WX_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 40897419a970..bad56bba26fc 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1597,6 +1597,71 @@ static void wx_restore_vlan(struct wx *wx)
 		wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
 }
 
+static void wx_store_reta(struct wx *wx)
+{
+	u8 *indir_tbl = wx->rss_indir_tbl;
+	u32 reta = 0;
+	u32 i;
+
+	/* Fill out the redirection table as follows:
+	 *  - 8 bit wide entries containing 4 bit RSS index
+	 */
+	for (i = 0; i < 128; i++) {
+		reta |= indir_tbl[i] << (i & 0x3) * 8;
+		if ((i & 3) == 3) {
+			wr32(wx, WX_RDB_RSSTBL(i >> 2), reta);
+			reta = 0;
+		}
+	}
+}
+
+static void wx_setup_reta(struct wx *wx)
+{
+	u16 rss_i = wx->ring_feature[RING_F_RSS].indices;
+	u32 i, j;
+
+	/* Fill out hash function seeds */
+	for (i = 0; i < 10; i++)
+		wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]);
+
+	/* Fill out redirection table */
+	memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl));
+
+	for (i = 0, j = 0; i < 128; i++, j++) {
+		if (j == rss_i)
+			j = 0;
+
+		wx->rss_indir_tbl[i] = j;
+	}
+
+	wx_store_reta(wx);
+}
+
+static void wx_setup_mrqc(struct wx *wx)
+{
+	u32 rss_field = 0;
+
+	/* Disable indicating checksum in descriptor, enables RSS hash */
+	wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD);
+
+	/* Perform hash on these packet types */
+	rss_field = WX_RDB_RA_CTL_RSS_IPV4 |
+		    WX_RDB_RA_CTL_RSS_IPV4_TCP |
+		    WX_RDB_RA_CTL_RSS_IPV4_UDP |
+		    WX_RDB_RA_CTL_RSS_IPV6 |
+		    WX_RDB_RA_CTL_RSS_IPV6_TCP |
+		    WX_RDB_RA_CTL_RSS_IPV6_UDP;
+
+	netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key));
+
+	wx_setup_reta(wx);
+
+	if (wx->rss_enabled)
+		rss_field |= WX_RDB_RA_CTL_RSS_EN;
+
+	wr32(wx, WX_RDB_RA_CTL, rss_field);
+}
+
 /**
  * wx_configure_rx - Configure Receive Unit after Reset
  * @wx: pointer to private structure
@@ -1629,6 +1694,8 @@ void wx_configure_rx(struct wx *wx)
 		wr32(wx, WX_PSR_CTL, psrctl);
 	}
 
+	wx_setup_mrqc(wx);
+
 	/* set_rx_buffer_len must be called before ring initialization */
 	wx_set_rx_buffer_len(wx);
 
@@ -1826,6 +1893,28 @@ int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count)
 }
 EXPORT_SYMBOL(wx_get_pcie_msix_counts);
 
+/**
+ * wx_init_rss_key - Initialize wx RSS key
+ * @wx: device handle
+ *
+ * Allocates and initializes the RSS key if it is not allocated.
+ **/
+static inline int wx_init_rss_key(struct wx *wx)
+{
+	u32 *rss_key;
+
+	if (!wx->rss_key) {
+		rss_key = kzalloc(WX_RSS_KEY_SIZE, GFP_KERNEL);
+		if (unlikely(!rss_key))
+			return -ENOMEM;
+
+		netdev_rss_key_fill(rss_key, WX_RSS_KEY_SIZE);
+		wx->rss_key = rss_key;
+	}
+
+	return 0;
+}
+
 int wx_sw_init(struct wx *wx)
 {
 	struct pci_dev *pdev = wx->pdev;
@@ -1861,6 +1950,11 @@ int wx_sw_init(struct wx *wx)
 		return -ENOMEM;
 	}
 
+	if (wx_init_rss_key(wx)) {
+		wx_err(wx, "rss key allocation failed\n");
+		return -ENOMEM;
+	}
+
 	wx->fc.pause_time = WX_DEFAULT_FCPAUSE;
 	wx->fc.disable_fc_autoneg = false;
 	wx->fc.rx_pause = true;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 9eb9ab8fe581..b97162fc9550 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -1636,6 +1636,12 @@ EXPORT_SYMBOL(wx_napi_disable_all);
  **/
 static void wx_set_rss_queues(struct wx *wx)
 {
+	struct wx_ring_feature *f;
+
+	/* set mask for 16 queue limit of RSS */
+	f = &wx->ring_feature[RING_F_RSS];
+	f->indices = f->limit;
+
 	wx->num_rx_queues = wx->mac.max_rx_queues;
 	wx->num_tx_queues = wx->mac.max_tx_queues;
 }
@@ -1713,9 +1719,11 @@ static int wx_set_interrupt_capability(struct wx *wx)
 	if (ret == 0 || (ret == -ENOMEM))
 		return ret;
 
-	wx->num_rx_queues = 1;
-	wx->num_tx_queues = 1;
-	wx->num_q_vectors = 1;
+	/* Disable RSS */
+	dev_warn(&wx->pdev->dev, "Disabling RSS support\n");
+	wx->ring_feature[RING_F_RSS].limit = 1;
+
+	wx_set_num_queues(wx);
 
 	/* minmum one for queue, one for misc*/
 	nvecs = 1;
@@ -2726,11 +2734,14 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_t changed = netdev->features ^ features;
 	struct wx *wx = netdev_priv(netdev);
 
-	if (changed & NETIF_F_RXHASH)
+	if (features & NETIF_F_RXHASH) {
 		wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
 		      WX_RDB_RA_CTL_RSS_EN);
-	else
+		wx->rss_enabled = true;
+	} else {
 		wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
+		wx->rss_enabled = false;
+	}
 
 	if (changed &
 	    (NETIF_F_HW_VLAN_CTAG_RX |
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 8c795f908d1e..45a98e23591d 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -146,8 +146,16 @@
 #define WX_RDB_PL_CFG_L2HDR          BIT(3)
 #define WX_RDB_PL_CFG_TUN_TUNHDR     BIT(4)
 #define WX_RDB_PL_CFG_TUN_OUTL2HDR   BIT(5)
+#define WX_RDB_RSSTBL(_i)            (0x19400 + ((_i) * 4))
+#define WX_RDB_RSSRK(_i)             (0x19480 + ((_i) * 4))
 #define WX_RDB_RA_CTL                0x194F4
 #define WX_RDB_RA_CTL_RSS_EN         BIT(2) /* RSS Enable */
+#define WX_RDB_RA_CTL_RSS_IPV4_TCP   BIT(16)
+#define WX_RDB_RA_CTL_RSS_IPV4       BIT(17)
+#define WX_RDB_RA_CTL_RSS_IPV6       BIT(20)
+#define WX_RDB_RA_CTL_RSS_IPV6_TCP   BIT(21)
+#define WX_RDB_RA_CTL_RSS_IPV4_UDP   BIT(22)
+#define WX_RDB_RA_CTL_RSS_IPV6_UDP   BIT(23)
 
 /******************************* PSR Registers *******************************/
 /* psr control */
@@ -912,6 +920,19 @@ struct wx_q_vector {
 	struct wx_ring ring[] ____cacheline_internodealigned_in_smp;
 };
 
+struct wx_ring_feature {
+	u16 limit;      /* upper limit on feature indices */
+	u16 indices;    /* current value of indices */
+	u16 mask;       /* Mask used for feature to ring mapping */
+	u16 offset;     /* offset to start of feature */
+};
+
+enum wx_ring_f_enum {
+	RING_F_NONE = 0,
+	RING_F_RSS,
+	RING_F_ARRAY_SIZE  /* must be last in enum set */
+};
+
 enum wx_isb_idx {
 	WX_ISB_HEADER,
 	WX_ISB_MISC,
@@ -1018,6 +1039,7 @@ struct wx {
 
 	unsigned int queues_per_pool;
 	struct msix_entry *msix_entries;
+	struct wx_ring_feature ring_feature[RING_F_ARRAY_SIZE];
 
 	/* misc interrupt status block */
 	dma_addr_t isb_dma;
@@ -1025,8 +1047,9 @@ struct wx {
 	u32 isb_tag[WX_ISB_MAX];
 
 #define WX_MAX_RETA_ENTRIES 128
+#define WX_RSS_INDIR_TBL_MAX 64
 	u8 rss_indir_tbl[WX_MAX_RETA_ENTRIES];
-
+	bool rss_enabled;
 #define WX_RSS_KEY_SIZE     40  /* size of RSS Hash Key in bytes */
 	u32 *rss_key;
 	u32 wol;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 712e0308c397..e4ac46242965 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -117,6 +117,19 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 	return err;
 }
 
+static int ngbe_set_channels(struct net_device *dev,
+			     struct ethtool_channels *ch)
+{
+	int err;
+
+	err = wx_set_channels(dev, ch);
+	if (err < 0)
+		return err;
+
+	/* use setup TC to update any traffic class queue mapping */
+	return ngbe_setup_tc(dev, netdev_get_num_tc(dev));
+}
+
 static const struct ethtool_ops ngbe_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
@@ -138,6 +151,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.set_ringparam		= ngbe_set_ringparam,
 	.get_coalesce		= wx_get_coalesce,
 	.set_coalesce		= wx_set_coalesce,
+	.get_channels		= wx_get_channels,
+	.set_channels		= ngbe_set_channels,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 0c0b2f7bdf74..c9dc885f8527 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -79,28 +79,6 @@ static void ngbe_init_type_code(struct wx *wx)
 	}
 }
 
-/**
- * ngbe_init_rss_key - Initialize wx RSS key
- * @wx: device handle
- *
- * Allocates and initializes the RSS key if it is not allocated.
- **/
-static inline int ngbe_init_rss_key(struct wx *wx)
-{
-	u32 *rss_key;
-
-	if (!wx->rss_key) {
-		rss_key = kzalloc(WX_RSS_KEY_SIZE, GFP_KERNEL);
-		if (unlikely(!rss_key))
-			return -ENOMEM;
-
-		netdev_rss_key_fill(rss_key, WX_RSS_KEY_SIZE);
-		wx->rss_key = rss_key;
-	}
-
-	return 0;
-}
-
 /**
  * ngbe_sw_init - Initialize general software structures
  * @wx: board private structure to initialize
@@ -134,8 +112,9 @@ static int ngbe_sw_init(struct wx *wx)
 		dev_err(&pdev->dev, "Do not support MSI-X\n");
 	wx->mac.max_msix_vectors = msix_count;
 
-	if (ngbe_init_rss_key(wx))
-		return -ENOMEM;
+	wx->ring_feature[RING_F_RSS].limit = min_t(int, NGBE_MAX_RSS_INDICES,
+						   num_online_cpus());
+	wx->rss_enabled = true;
 
 	/* enable itr by default in dynamic mode */
 	wx->rx_itr_setting = 1;
@@ -480,6 +459,39 @@ static void ngbe_shutdown(struct pci_dev *pdev)
 	}
 }
 
+/**
+ * ngbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @dev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int ngbe_setup_tc(struct net_device *dev, u8 tc)
+{
+	struct wx *wx = netdev_priv(dev);
+
+	/* Hardware has to reinitialize queues and interrupts to
+	 * match packet buffer alignment. Unfortunately, the
+	 * hardware is not flexible enough to do this dynamically.
+	 */
+	if (netif_running(dev))
+		ngbe_close(dev);
+
+	wx_clear_interrupt_scheme(wx);
+
+	if (tc)
+		netdev_set_num_tc(dev, tc);
+	else
+		netdev_reset_tc(dev);
+
+	wx_init_interrupt_scheme(wx);
+
+	if (netif_running(dev))
+		ngbe_open(dev);
+
+	return 0;
+}
+
 static const struct net_device_ops ngbe_netdev_ops = {
 	.ndo_open               = ngbe_open,
 	.ndo_stop               = ngbe_close,
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 0a98080a197a..f4dc4acbedae 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -105,6 +105,7 @@
 #define NGBE_FW_CMD_ST_FAIL			0x70657376
 
 #define NGBE_MAX_FDIR_INDICES			7
+#define NGBE_MAX_RSS_INDICES			8
 
 #define NGBE_MAX_RX_QUEUES			(NGBE_MAX_FDIR_INDICES + 1)
 #define NGBE_MAX_TX_QUEUES			(NGBE_MAX_FDIR_INDICES + 1)
@@ -132,5 +133,6 @@ extern char ngbe_driver_name[];
 
 void ngbe_down(struct wx *wx);
 void ngbe_up(struct wx *wx);
+int ngbe_setup_tc(struct net_device *dev, u8 tc);
 
 #endif /* _NGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index fe055b006a4e..36cbc4e799b3 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -92,6 +92,19 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 	return err;
 }
 
+static int txgbe_set_channels(struct net_device *dev,
+			      struct ethtool_channels *ch)
+{
+	int err;
+
+	err = wx_set_channels(dev, ch);
+	if (err < 0)
+		return err;
+
+	/* use setup TC to update any traffic class queue mapping */
+	return txgbe_setup_tc(dev, netdev_get_num_tc(dev));
+}
+
 static const struct ethtool_ops txgbe_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
@@ -111,6 +124,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.set_ringparam		= txgbe_set_ringparam,
 	.get_coalesce		= wx_get_coalesce,
 	.set_coalesce		= wx_set_coalesce,
+	.get_channels		= wx_get_channels,
+	.set_channels		= txgbe_set_channels,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 9b1b92fa318f..b2e9feb88aac 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -382,6 +382,10 @@ static int txgbe_sw_init(struct wx *wx)
 		wx_err(wx, "Do not support MSI-X\n");
 	wx->mac.max_msix_vectors = msix_count;
 
+	wx->ring_feature[RING_F_RSS].limit = min_t(int, TXGBE_MAX_RSS_INDICES,
+						   num_online_cpus());
+	wx->rss_enabled = true;
+
 	/* enable itr by default in dynamic mode */
 	wx->rx_itr_setting = 1;
 	wx->tx_itr_setting = 1;
@@ -508,6 +512,41 @@ static void txgbe_shutdown(struct pci_dev *pdev)
 	}
 }
 
+/**
+ * txgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @dev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int txgbe_setup_tc(struct net_device *dev, u8 tc)
+{
+	struct wx *wx = netdev_priv(dev);
+
+	/* Hardware has to reinitialize queues and interrupts to
+	 * match packet buffer alignment. Unfortunately, the
+	 * hardware is not flexible enough to do this dynamically.
+	 */
+	if (netif_running(dev))
+		txgbe_close(dev);
+	else
+		txgbe_reset(wx);
+
+	wx_clear_interrupt_scheme(wx);
+
+	if (tc)
+		netdev_set_num_tc(dev, tc);
+	else
+		netdev_reset_tc(dev);
+
+	wx_init_interrupt_scheme(wx);
+
+	if (netif_running(dev))
+		txgbe_open(dev);
+
+	return 0;
+}
+
 static const struct net_device_ops txgbe_netdev_ops = {
 	.ndo_open               = txgbe_open,
 	.ndo_stop               = txgbe_close,
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 13a2f3f53c39..e99f927c8b77 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -98,6 +98,7 @@
 
 #define TXGBE_MAX_MSIX_VECTORS          64
 #define TXGBE_MAX_FDIR_INDICES          63
+#define TXGBE_MAX_RSS_INDICES           63
 
 #define TXGBE_MAX_RX_QUEUES   (TXGBE_MAX_FDIR_INDICES + 1)
 #define TXGBE_MAX_TX_QUEUES   (TXGBE_MAX_FDIR_INDICES + 1)
@@ -131,6 +132,7 @@ extern char txgbe_driver_name[];
 
 void txgbe_down(struct wx *wx);
 void txgbe_up(struct wx *wx);
+int txgbe_setup_tc(struct net_device *dev, u8 tc);
 
 static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev)
 {
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel
  2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
                   ` (3 preceding siblings ...)
  2023-11-22 10:22 ` [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number Jiawen Wu
@ 2023-11-22 10:22 ` Jiawen Wu
  2023-11-22 16:36   ` Andrew Lunn
  4 siblings, 1 reply; 17+ messages in thread
From: Jiawen Wu @ 2023-11-22 10:22 UTC (permalink / raw)
  To: netdev, davem, edumazet, kuba, pabeni, linux, andrew, horms
  Cc: mengyuanlou, Jiawen Wu

Add support to get and set msglevel for driver txgbe and ngbe.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_ethtool.c  | 16 ++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_ethtool.h  |  2 ++
 drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c |  2 ++
 .../net/ethernet/wangxun/txgbe/txgbe_ethtool.c   |  2 ++
 4 files changed, 22 insertions(+)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 4e467aa1cc19..f76227f2f544 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -369,3 +369,19 @@ int wx_set_channels(struct net_device *dev,
 	return 0;
 }
 EXPORT_SYMBOL(wx_set_channels);
+
+u32 wx_get_msglevel(struct net_device *netdev)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	return wx->msg_enable;
+}
+EXPORT_SYMBOL(wx_get_msglevel);
+
+void wx_set_msglevel(struct net_device *netdev, u32 data)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	wx->msg_enable = data;
+}
+EXPORT_SYMBOL(wx_set_msglevel);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
index 5b5af3689c04..73b6d7003569 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
@@ -29,4 +29,6 @@ void wx_get_channels(struct net_device *dev,
 		     struct ethtool_channels *ch);
 int wx_set_channels(struct net_device *dev,
 		    struct ethtool_channels *ch);
+u32 wx_get_msglevel(struct net_device *netdev);
+void wx_set_msglevel(struct net_device *netdev, u32 data);
 #endif /* _WX_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index e4ac46242965..caeaf1dd95b7 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -153,6 +153,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.set_coalesce		= wx_set_coalesce,
 	.get_channels		= wx_get_channels,
 	.set_channels		= ngbe_set_channels,
+	.get_msglevel		= wx_get_msglevel,
+	.set_msglevel		= wx_set_msglevel,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 36cbc4e799b3..18408af6a860 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -126,6 +126,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.set_coalesce		= wx_set_coalesce,
 	.get_channels		= wx_get_channels,
 	.set_channels		= txgbe_set_channels,
+	.get_msglevel		= wx_get_msglevel,
+	.set_msglevel		= wx_set_msglevel,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 10:22 ` [PATCH net-next 1/5] net: wangxun: add flow control support Jiawen Wu
@ 2023-11-22 16:15   ` Andrew Lunn
  2023-11-22 16:30     ` Russell King (Oracle)
  2023-11-23  9:20     ` Jiawen Wu
  0 siblings, 2 replies; 17+ messages in thread
From: Andrew Lunn @ 2023-11-22 16:15 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> +	/* Calculate max LAN frame size */
> +	link = dev->mtu + ETH_HLEN + ETH_FCS_LEN + WX_ETH_FRAMING;
> +	tc = link;
> +
> +	/* Calculate delay value for device */
> +	dv_id = WX_DV(link, tc);

That looks odd. tc == link. So why pass both? Or is it a typo?

> +/* BitTimes (BT) conversion */
> +#define WX_BT2KB(BT)         (((BT) + (8 * 1024 - 1)) / (8 * 1024))
> +#define WX_B2BT(BT)          ((BT) * 8)
> +/* Calculate Interface Delay */
> +#define WX_PHY_D     12800
> +#define WX_MAC_D     4096
> +#define WX_XAUI_D    (2 * 1024)
> +#define WX_ID        (WX_MAC_D + WX_XAUI_D + WX_PHY_D)
> +/* Calculate PCI Bus delay for low thresholds */
> +#define WX_PCI_DELAY 10000
> +
> +/* Calculate delay value in bit times */
> +#define WX_DV(_max_frame_link, _max_frame_tc) \
> +	((36 * (WX_B2BT(_max_frame_link) + 672 + (2 * 5556) + (2 * WX_ID) + 6144) / \
> +	  25 + 1) +  2 * WX_B2BT(_max_frame_tc))
> +
> +/* Calculate low threshold delay values */
> +#define WX_LOW_DV(_max_frame_tc) \
> +	(2 * (2 * WX_B2BT(_max_frame_tc) + (36 * WX_PCI_DELAY / 25) + 1))

There is too much magic here. Please make these functions, and add
comments explaining what is going on here.

> +static void ngbe_get_pauseparam(struct net_device *netdev,
> +				struct ethtool_pauseparam *pause)
> +{
> +	struct wx *wx = netdev_priv(netdev);
> +
> +	pause->autoneg = !wx->fc.disable_fc_autoneg;

Maybe call it enable_fs_autoneg, since that is what the kAPI uses?

> +static int ngbe_set_pauseparam(struct net_device *netdev,
> +			       struct ethtool_pauseparam *pause)
> +{
> +	struct wx *wx = netdev_priv(netdev);
> +
> +	if (!wx->phydev)
> +		return -ENODEV;
> +
> +	if (!phy_validate_pause(wx->phydev, pause))
> +		return -EINVAL;
> +
> +	wx->fc.disable_fc_autoneg = !pause->autoneg;
> +	wx->fc.tx_pause = pause->tx_pause;
> +	wx->fc.rx_pause = pause->rx_pause;
> +
> +	phy_set_asym_pause(wx->phydev, pause->rx_pause, pause->tx_pause);

You should only be doing this if pause->autoneg is true. If it is
false, you ignore the results from autoneg, and just configure the
hardware as indicated by pause->{tr}x_pause.

phylink makes this a lot easier, because it hides away all these
details. You might want to convert to phylink. Everybody gets is wrong
with phylib, but correct with phylink.

	 Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters
  2023-11-22 10:22 ` [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters Jiawen Wu
@ 2023-11-22 16:24   ` Andrew Lunn
  2023-11-23  9:25     ` Jiawen Wu
  2023-11-30  3:32     ` Jiawen Wu
  0 siblings, 2 replies; 17+ messages in thread
From: Andrew Lunn @ 2023-11-22 16:24 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> +int wx_set_ring(struct wx *wx, u32 new_tx_count, u32 new_rx_count)
> +{
> +	struct wx_ring *temp_ring;
> +	int i, err = 0;
> +
> +	/* allocate temporary buffer to store rings in */
> +	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
> +	temp_ring = vmalloc(i * sizeof(struct wx_ring));

So it is O.K. for the pages to be scattered around the physical
address space, not contiguous. Does this memory ever get passed to the
hardware?

> +static int ngbe_set_ringparam(struct net_device *netdev,
> +			      struct ethtool_ringparam *ring,
> +			      struct kernel_ethtool_ringparam *kernel_ring,
> +			      struct netlink_ext_ack *extack)
> +{
> +	struct wx *wx = netdev_priv(netdev);
> +	u32 new_rx_count, new_tx_count;
> +	int i, err = 0;
> +
> +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> +		return -EINVAL;

EOPNOTSUP would be better, to indicate you don't support it, not that
it is invalid.

> +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> +		return -EINVAL;

Same here.

> +
> +	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
> +	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
> +
> +	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
> +	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
> +
> +	if (new_tx_count == wx->tx_ring_count &&
> +	    new_rx_count == wx->rx_ring_count)
> +		return 0;
> +
> +	if (!netif_running(wx->netdev)) {
> +		for (i = 0; i < wx->num_tx_queues; i++)
> +			wx->tx_ring[i]->count = new_tx_count;
> +		for (i = 0; i < wx->num_rx_queues; i++)
> +			wx->rx_ring[i]->count = new_rx_count;
> +		wx->tx_ring_count = new_tx_count;
> +		wx->rx_ring_count = new_rx_count;
> +
> +		return 0;
> +	}
> +
> +	txgbe_down(wx);
> +
> +	err = wx_set_ring(wx, new_tx_count, new_rx_count);
> +
> +	txgbe_up(wx);
> +
> +	return err;

Could most of this be moved into the library? It looks pretty similar
for the two devices.

    Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 16:15   ` Andrew Lunn
@ 2023-11-22 16:30     ` Russell King (Oracle)
  2023-11-22 17:24       ` Andrew Lunn
  2023-11-23  9:20     ` Jiawen Wu
  1 sibling, 1 reply; 17+ messages in thread
From: Russell King (Oracle) @ 2023-11-22 16:30 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jiawen Wu, netdev, davem, edumazet, kuba, pabeni, horms, mengyuanlou

On Wed, Nov 22, 2023 at 05:15:05PM +0100, Andrew Lunn wrote:
> > +static void ngbe_get_pauseparam(struct net_device *netdev,
> > +				struct ethtool_pauseparam *pause)
> > +{
> > +	struct wx *wx = netdev_priv(netdev);
> > +
> > +	pause->autoneg = !wx->fc.disable_fc_autoneg;
> 
> Maybe call it enable_fs_autoneg, since that is what the kAPI uses?

fs?

> > +	wx->fc.disable_fc_autoneg = !pause->autoneg;
> > +	wx->fc.tx_pause = pause->tx_pause;
> > +	wx->fc.rx_pause = pause->rx_pause;
> > +
> > +	phy_set_asym_pause(wx->phydev, pause->rx_pause, pause->tx_pause);
> 
> You should only be doing this if pause->autoneg is true. If it is
> false, you ignore the results from autoneg, and just configure the
> hardware as indicated by pause->{tr}x_pause.

However, if autoneg is supported, but pause autoneg is disabled, there
is still the need to update the PHY's advertisement so the remote end
knows what's going on, as documented in the user API:

" * If the link is autonegotiated, drivers should use
  * mii_advertise_flowctrl() or similar code to set the advertised
  * pause frame capabilities based on the @rx_pause and @tx_pause flags,
  * even if @autoneg is zero. ... "

You are correct that when !pause->autoneg, tx_pause/rx_pause are to be
used in place of the negotiated versions.

Also... when getting the pause parameters, tx_pause/rx_pause _should_
reflect what was set for these parameters via the set function, *not*
the current state affected by negotiation.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number
  2023-11-22 10:22 ` [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number Jiawen Wu
@ 2023-11-22 16:35   ` Andrew Lunn
  0 siblings, 0 replies; 17+ messages in thread
From: Andrew Lunn @ 2023-11-22 16:35 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> +int wx_set_channels(struct net_device *dev,
> +		    struct ethtool_channels *ch)
> +{
> +	unsigned int count = ch->combined_count;
> +	struct wx *wx = netdev_priv(dev);
> +
> +	/* verify they are not requesting separate vectors */
> +	if (!count || ch->rx_count || ch->tx_count)
> +		return -EINVAL;

I think EOPNOTSUPP here. Its a but fuzzy when you use EINVAL and when
to use EINVAL. If its a feature you don't support at all, use
EOPNOTSUPP. If its a feature you do support, but the value is out of
range for what the hardware can do, then EINVAL.

So here, the configuration is asking for something you cannot support,
split RX and TX configuration. So EOPNOTSUPP.

> +
> +	/* verify other_count has not changed */
> +	if (ch->other_count != 1)
> +		return -EINVAL;
> +
> +	/* verify the number of channels does not exceed hardware limits */
> +	if (count > wx_max_channels(wx))
> +		return -EINVAL;

Here it is out of range, so EINVAL is correct.

Please think about this for the whole patchset, and the driver in
general.

> +
> +	wx->ring_feature[RING_F_RSS].limit = count;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(wx_set_channels);
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
> index 3a80f8e63719..5b5af3689c04 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
> @@ -25,4 +25,8 @@ int wx_set_coalesce(struct net_device *netdev,
>  		    struct ethtool_coalesce *ec,
>  		    struct kernel_ethtool_coalesce *kernel_coal,
>  		    struct netlink_ext_ack *extack);
> +void wx_get_channels(struct net_device *dev,
> +		     struct ethtool_channels *ch);
> +int wx_set_channels(struct net_device *dev,
> +		    struct ethtool_channels *ch);
>  #endif /* _WX_ETHTOOL_H_ */
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> index 40897419a970..bad56bba26fc 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> @@ -1597,6 +1597,71 @@ static void wx_restore_vlan(struct wx *wx)
>  		wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
>  }
>  
> +static void wx_store_reta(struct wx *wx)
> +{
> +	u8 *indir_tbl = wx->rss_indir_tbl;
> +	u32 reta = 0;
> +	u32 i;
> +
> +	/* Fill out the redirection table as follows:
> +	 *  - 8 bit wide entries containing 4 bit RSS index
> +	 */
> +	for (i = 0; i < 128; i++) {
> +		reta |= indir_tbl[i] << (i & 0x3) * 8;
> +		if ((i & 3) == 3) {
> +			wr32(wx, WX_RDB_RSSTBL(i >> 2), reta);
> +			reta = 0;
> +		}
> +	}
> +}
> +
> +static void wx_setup_reta(struct wx *wx)
> +{
> +	u16 rss_i = wx->ring_feature[RING_F_RSS].indices;
> +	u32 i, j;
> +
> +	/* Fill out hash function seeds */
> +	for (i = 0; i < 10; i++)
> +		wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]);
> +
> +	/* Fill out redirection table */
> +	memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl));
> +
> +	for (i = 0, j = 0; i < 128; i++, j++) {
> +		if (j == rss_i)
> +			j = 0;
> +
> +		wx->rss_indir_tbl[i] = j;
> +	}
> +
> +	wx_store_reta(wx);
> +}

There are a lot of magic numbers here, 10, 128 etc. It would be good
to add #define to document what they are.

> +/**
> + * wx_init_rss_key - Initialize wx RSS key
> + * @wx: device handle
> + *
> + * Allocates and initializes the RSS key if it is not allocated.
> + **/
> +static inline int wx_init_rss_key(struct wx *wx)

No inline functions in .c files. Let the compiler decide.

> +{
> +	u32 *rss_key;
> +
> +	if (!wx->rss_key) {
> +		rss_key = kzalloc(WX_RSS_KEY_SIZE, GFP_KERNEL);
> +		if (unlikely(!rss_key))
> +			return -ENOMEM;
> +
> +		netdev_rss_key_fill(rss_key, WX_RSS_KEY_SIZE);
> +		wx->rss_key = rss_key;
> +	}
> +
> +	return 0;
> +}
> +
>  int wx_sw_init(struct wx *wx)
>  {
>  	struct pci_dev *pdev = wx->pdev;
> @@ -1861,6 +1950,11 @@ int wx_sw_init(struct wx *wx)
>  		return -ENOMEM;
>  	}
>  
> +	if (wx_init_rss_key(wx)) {
> +		wx_err(wx, "rss key allocation failed\n");
> +		return -ENOMEM;

Return the error code wx_init_rss_key() returns.

       Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel
  2023-11-22 10:22 ` [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel Jiawen Wu
@ 2023-11-22 16:36   ` Andrew Lunn
  0 siblings, 0 replies; 17+ messages in thread
From: Andrew Lunn @ 2023-11-22 16:36 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

On Wed, Nov 22, 2023 at 06:22:26PM +0800, Jiawen Wu wrote:
> Add support to get and set msglevel for driver txgbe and ngbe.
> 
> Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 16:30     ` Russell King (Oracle)
@ 2023-11-22 17:24       ` Andrew Lunn
  2023-11-22 17:26         ` Russell King (Oracle)
  0 siblings, 1 reply; 17+ messages in thread
From: Andrew Lunn @ 2023-11-22 17:24 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Jiawen Wu, netdev, davem, edumazet, kuba, pabeni, horms, mengyuanlou

> However, if autoneg is supported, but pause autoneg is disabled, there
> is still the need to update the PHY's advertisement so the remote end
> knows what's going on, as documented in the user API:
> 
> " * If the link is autonegotiated, drivers should use
>   * mii_advertise_flowctrl() or similar code to set the advertised
>   * pause frame capabilities based on the @rx_pause and @tx_pause flags,
>   * even if @autoneg is zero. ... "
> 
> You are correct that when !pause->autoneg, tx_pause/rx_pause are to be
> used in place of the negotiated versions.
> 
> Also... when getting the pause parameters, tx_pause/rx_pause _should_
> reflect what was set for these parameters via the set function, *not*
> the current state affected by negotiation.

All good reasons to just use phylink which handles all this for you.

    Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 17:24       ` Andrew Lunn
@ 2023-11-22 17:26         ` Russell King (Oracle)
  0 siblings, 0 replies; 17+ messages in thread
From: Russell King (Oracle) @ 2023-11-22 17:26 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jiawen Wu, netdev, davem, edumazet, kuba, pabeni, horms, mengyuanlou

On Wed, Nov 22, 2023 at 06:24:22PM +0100, Andrew Lunn wrote:
> > However, if autoneg is supported, but pause autoneg is disabled, there
> > is still the need to update the PHY's advertisement so the remote end
> > knows what's going on, as documented in the user API:
> > 
> > " * If the link is autonegotiated, drivers should use
> >   * mii_advertise_flowctrl() or similar code to set the advertised
> >   * pause frame capabilities based on the @rx_pause and @tx_pause flags,
> >   * even if @autoneg is zero. ... "
> > 
> > You are correct that when !pause->autoneg, tx_pause/rx_pause are to be
> > used in place of the negotiated versions.
> > 
> > Also... when getting the pause parameters, tx_pause/rx_pause _should_
> > reflect what was set for these parameters via the set function, *not*
> > the current state affected by negotiation.
> 
> All good reasons to just use phylink which handles all this for you.

Indeed... consistent implementation and therefore behaviour (assuming
users of phylink are implemented correctly!) :)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH net-next 1/5] net: wangxun: add flow control support
  2023-11-22 16:15   ` Andrew Lunn
  2023-11-22 16:30     ` Russell King (Oracle)
@ 2023-11-23  9:20     ` Jiawen Wu
  1 sibling, 0 replies; 17+ messages in thread
From: Jiawen Wu @ 2023-11-23  9:20 UTC (permalink / raw)
  To: 'Andrew Lunn'
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

On Thursday, November 23, 2023 12:15 AM, Andrew Lunn wrote:
> > +	/* Calculate max LAN frame size */
> > +	link = dev->mtu + ETH_HLEN + ETH_FCS_LEN + WX_ETH_FRAMING;
> > +	tc = link;
> > +
> > +	/* Calculate delay value for device */
> > +	dv_id = WX_DV(link, tc);
> 
> That looks odd. tc == link. So why pass both? Or is it a typo?

This is because I've temporarily removed the FCOE related code,
as something to support later. So now tc == link, which looks odd.
 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters
  2023-11-22 16:24   ` Andrew Lunn
@ 2023-11-23  9:25     ` Jiawen Wu
  2023-11-23 15:14       ` Andrew Lunn
  2023-11-30  3:32     ` Jiawen Wu
  1 sibling, 1 reply; 17+ messages in thread
From: Jiawen Wu @ 2023-11-23  9:25 UTC (permalink / raw)
  To: 'Andrew Lunn'
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> > +	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
> > +	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
> > +
> > +	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
> > +	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
> > +
> > +	if (new_tx_count == wx->tx_ring_count &&
> > +	    new_rx_count == wx->rx_ring_count)
> > +		return 0;
> > +
> > +	if (!netif_running(wx->netdev)) {
> > +		for (i = 0; i < wx->num_tx_queues; i++)
> > +			wx->tx_ring[i]->count = new_tx_count;
> > +		for (i = 0; i < wx->num_rx_queues; i++)
> > +			wx->rx_ring[i]->count = new_rx_count;
> > +		wx->tx_ring_count = new_tx_count;
> > +		wx->rx_ring_count = new_rx_count;
> > +
> > +		return 0;
> > +	}
> > +
> > +	txgbe_down(wx);
> > +
> > +	err = wx_set_ring(wx, new_tx_count, new_rx_count);
> > +
> > +	txgbe_up(wx);
> > +
> > +	return err;
> 
> Could most of this be moved into the library? It looks pretty similar
> for the two devices.

I tried to move them into the library, but *_down() and *_up() here
involves some different flows for the two devices, it's not easy to handle.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters
  2023-11-23  9:25     ` Jiawen Wu
@ 2023-11-23 15:14       ` Andrew Lunn
  0 siblings, 0 replies; 17+ messages in thread
From: Andrew Lunn @ 2023-11-23 15:14 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> I tried to move them into the library, but *_down() and *_up() here
> involves some different flows for the two devices, it's not easy to handle.
 
O.K. Thanks for the explanation.

     Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters
  2023-11-22 16:24   ` Andrew Lunn
  2023-11-23  9:25     ` Jiawen Wu
@ 2023-11-30  3:32     ` Jiawen Wu
  1 sibling, 0 replies; 17+ messages in thread
From: Jiawen Wu @ 2023-11-30  3:32 UTC (permalink / raw)
  To: 'Andrew Lunn'
  Cc: netdev, davem, edumazet, kuba, pabeni, linux, horms, mengyuanlou

> > +int wx_set_ring(struct wx *wx, u32 new_tx_count, u32 new_rx_count)
> > +{
> > +	struct wx_ring *temp_ring;
> > +	int i, err = 0;
> > +
> > +	/* allocate temporary buffer to store rings in */
> > +	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
> > +	temp_ring = vmalloc(i * sizeof(struct wx_ring));
> 
> So it is O.K. for the pages to be scattered around the physical
> address space, not contiguous. Does this memory ever get passed to the
> hardware?

No, this memory is only used to temporarily store ring info. It will be freed after
restoring the ring info.


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-11-30  3:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-22 10:22 [PATCH net-next 0/5] Implement more ethtool_ops for Wangxun Jiawen Wu
2023-11-22 10:22 ` [PATCH net-next 1/5] net: wangxun: add flow control support Jiawen Wu
2023-11-22 16:15   ` Andrew Lunn
2023-11-22 16:30     ` Russell King (Oracle)
2023-11-22 17:24       ` Andrew Lunn
2023-11-22 17:26         ` Russell King (Oracle)
2023-11-23  9:20     ` Jiawen Wu
2023-11-22 10:22 ` [PATCH net-next 2/5] net: wangxun: add ethtool_ops for ring parameters Jiawen Wu
2023-11-22 16:24   ` Andrew Lunn
2023-11-23  9:25     ` Jiawen Wu
2023-11-23 15:14       ` Andrew Lunn
2023-11-30  3:32     ` Jiawen Wu
2023-11-22 10:22 ` [PATCH net-next 3/5] net: wangxun: add coalesce options support Jiawen Wu
2023-11-22 10:22 ` [PATCH net-next 4/5] net: wangxun: add ethtool_ops for channel number Jiawen Wu
2023-11-22 16:35   ` Andrew Lunn
2023-11-22 10:22 ` [PATCH net-next 5/5] net: wangxun: add ethtool_ops for msglevel Jiawen Wu
2023-11-22 16:36   ` Andrew Lunn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).