summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/wangxun/txgbe
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:36 +0000
commit50ba0232fd5312410f1b65247e774244f89a628e (patch)
treefd8f2fc78e9e548af0ff9590276602ee6125be00 /drivers/net/ethernet/wangxun/txgbe
parentReleasing progress-linux version 6.7.12-1~progress7.99u1. (diff)
downloadlinux-50ba0232fd5312410f1b65247e774244f89a628e.tar.xz
linux-50ba0232fd5312410f1b65247e774244f89a628e.zip
Merging upstream version 6.8.9.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/ethernet/wangxun/txgbe')
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c82
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c63
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c65
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_type.h15
4 files changed, 163 insertions, 62 deletions
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 3f336a088e..db675512ce 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -7,43 +7,93 @@
#include "../libwx/wx_ethtool.h"
#include "../libwx/wx_type.h"
+#include "../libwx/wx_lib.h"
#include "txgbe_type.h"
#include "txgbe_ethtool.h"
-static int txgbe_nway_reset(struct net_device *netdev)
+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 txgbe *txgbe = netdev_to_txgbe(netdev);
+ struct wx *wx = netdev_priv(netdev);
+ u32 new_rx_count, new_tx_count;
+ struct wx_ring *temp_ring;
+ int i;
- return phylink_ethtool_nway_reset(txgbe->phylink);
-}
+ 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);
-static int txgbe_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd)
-{
- struct txgbe *txgbe = netdev_to_txgbe(netdev);
+ 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;
+ }
- return phylink_ethtool_ksettings_get(txgbe->phylink, cmd);
+ /* allocate temporary buffer to store rings in */
+ i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+ temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
+ if (!temp_ring)
+ return -ENOMEM;
+
+ txgbe_down(wx);
+
+ wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
+ kvfree(temp_ring);
+
+ txgbe_up(wx);
+
+ return 0;
}
-static int txgbe_set_link_ksettings(struct net_device *netdev,
- const struct ethtool_link_ksettings *cmd)
+static int txgbe_set_channels(struct net_device *dev,
+ struct ethtool_channels *ch)
{
- struct txgbe *txgbe = netdev_to_txgbe(netdev);
+ int err;
+
+ err = wx_set_channels(dev, ch);
+ if (err < 0)
+ return err;
- return phylink_ethtool_ksettings_set(txgbe->phylink, cmd);
+ /* 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,
.get_drvinfo = wx_get_drvinfo,
- .nway_reset = txgbe_nway_reset,
+ .nway_reset = wx_nway_reset,
.get_link = ethtool_op_get_link,
- .get_link_ksettings = txgbe_get_link_ksettings,
- .set_link_ksettings = txgbe_set_link_ksettings,
+ .get_link_ksettings = wx_get_link_ksettings,
+ .set_link_ksettings = wx_set_link_ksettings,
.get_sset_count = wx_get_sset_count,
.get_strings = wx_get_strings,
.get_ethtool_stats = wx_get_ethtool_stats,
.get_eth_mac_stats = wx_get_mac_stats,
.get_pause_stats = wx_get_pause_stats,
+ .get_pauseparam = wx_get_pauseparam,
+ .set_pauseparam = wx_set_pauseparam,
+ .get_ringparam = wx_get_ringparam,
+ .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,
+ .get_msglevel = wx_get_msglevel,
+ .set_msglevel = wx_set_msglevel,
};
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 526250102d..3b151c410a 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -86,7 +86,7 @@ static void txgbe_irq_enable(struct wx *wx, bool queues)
wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
/* unmask interrupt */
- wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
+ wx_intr_enable(wx, TXGBE_INTR_MISC);
if (queues)
wx_intr_enable(wx, TXGBE_INTR_QALL(wx));
}
@@ -145,7 +145,7 @@ static int txgbe_request_msix_irqs(struct wx *wx)
for (vector = 0; vector < wx->num_q_vectors; vector++) {
struct wx_q_vector *q_vector = wx->q_vector[vector];
- struct msix_entry *entry = &wx->msix_entries[vector];
+ struct msix_entry *entry = &wx->msix_q_entries[vector];
if (q_vector->tx.ring && q_vector->rx.ring)
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -168,7 +168,7 @@ static int txgbe_request_msix_irqs(struct wx *wx)
free_queue_irqs:
while (vector) {
vector--;
- free_irq(wx->msix_entries[vector].vector,
+ free_irq(wx->msix_q_entries[vector].vector,
wx->q_vector[vector]);
}
wx_reset_interrupt_capability(wx);
@@ -206,7 +206,6 @@ static int txgbe_request_irq(struct wx *wx)
static void txgbe_up_complete(struct wx *wx)
{
struct net_device *netdev = wx->netdev;
- struct txgbe *txgbe;
wx_control_hw(wx, true);
wx_configure_vectors(wx);
@@ -215,8 +214,7 @@ static void txgbe_up_complete(struct wx *wx)
smp_mb__before_atomic();
wx_napi_enable_all(wx);
- txgbe = netdev_to_txgbe(netdev);
- phylink_start(txgbe->phylink);
+ phylink_start(wx->phylink);
/* clear any pending interrupts, may auto mask */
rd32(wx, WX_PX_IC(0));
@@ -290,18 +288,22 @@ 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);
-
txgbe_disable_device(wx);
txgbe_reset(wx);
- phylink_stop(txgbe->phylink);
+ phylink_stop(wx->phylink);
wx_clean_all_tx_rings(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
@@ -376,6 +378,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;
@@ -502,6 +508,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,
@@ -638,6 +679,7 @@ static int txgbe_probe(struct pci_dev *pdev,
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = WX_MAX_JUMBO_FRAME_SIZE -
@@ -775,6 +817,7 @@ static void txgbe_remove(struct pci_dev *pdev)
pci_release_selected_regions(pdev,
pci_select_bars(pdev, IORESOURCE_MEM));
+ kfree(wx->rss_key);
kfree(wx->mac_table);
wx_clear_interrupt_scheme(wx);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
index b95187a084..8cddc9ddb3 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -20,6 +20,8 @@
#include "txgbe_phy.h"
#include "txgbe_hw.h"
+#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
+
static int txgbe_swnodes_register(struct txgbe *txgbe)
{
struct txgbe_nodes *nodes = &txgbe->nodes;
@@ -159,7 +161,8 @@ static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config,
phy_interface_t interface)
{
- struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev));
+ struct wx *wx = phylink_to_wx(config);
+ struct txgbe *txgbe = wx->priv;
if (interface == PHY_INTERFACE_MODE_10GBASER)
return &txgbe->xpcs->pcs;
@@ -175,7 +178,7 @@ static void txgbe_mac_config(struct phylink_config *config, unsigned int mode,
static void txgbe_mac_link_down(struct phylink_config *config,
unsigned int mode, phy_interface_t interface)
{
- struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ struct wx *wx = phylink_to_wx(config);
wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
}
@@ -186,9 +189,11 @@ static void txgbe_mac_link_up(struct phylink_config *config,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ struct wx *wx = phylink_to_wx(config);
u32 txcfg, wdg;
+ wx_fc_enable(wx, tx_pause, rx_pause);
+
txcfg = rd32(wx, WX_MAC_TX_CFG);
txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK;
@@ -217,7 +222,7 @@ static void txgbe_mac_link_up(struct phylink_config *config,
static int txgbe_mac_prepare(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
- struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ struct wx *wx = phylink_to_wx(config);
wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0);
@@ -228,7 +233,7 @@ static int txgbe_mac_prepare(struct phylink_config *config, unsigned int mode,
static int txgbe_mac_finish(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
- struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ struct wx *wx = phylink_to_wx(config);
txgbe_enable_sec_tx_path(wx);
wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);
@@ -253,10 +258,7 @@ static int txgbe_phylink_init(struct txgbe *txgbe)
phy_interface_t phy_mode;
struct phylink *phylink;
- config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL);
- if (!config)
- return -ENOMEM;
-
+ config = &wx->phylink_config;
config->dev = &wx->netdev->dev;
config->type = PHYLINK_NETDEV;
config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_100FD |
@@ -287,7 +289,7 @@ static int txgbe_phylink_init(struct txgbe *txgbe)
}
}
- txgbe->phylink = phylink;
+ wx->phylink = phylink;
return 0;
}
@@ -483,11 +485,11 @@ static void txgbe_irq_handler(struct irq_desc *desc)
TXGBE_PX_MISC_ETH_AN)) {
u32 reg = rd32(wx, TXGBE_CFG_PORT_ST);
- phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));
+ phylink_mac_change(wx->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));
}
/* unmask interrupt */
- wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
+ wx_intr_enable(wx, TXGBE_INTR_MISC);
}
static int txgbe_gpio_init(struct txgbe *txgbe)
@@ -531,7 +533,12 @@ static int txgbe_gpio_init(struct txgbe *txgbe)
sizeof(*girq->parents), GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
- girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector;
+
+ /* now only suuported on MSI-X interrupt */
+ if (!wx->msix_entry)
+ return -EPERM;
+
+ girq->parents[0] = wx->msix_entry->vector;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
@@ -551,8 +558,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
char clk_name[32];
struct clk *clk;
- snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d",
- pci_dev_id(pdev));
+ snprintf(clk_name, sizeof(clk_name), "%s.%d",
+ TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
if (IS_ERR(clk))
@@ -614,7 +621,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
info.parent = &pdev->dev;
info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
- info.name = "i2c_designware";
+ info.name = TXGBE_I2C_CLK_DEV_NAME;
info.id = pci_dev_id(pdev);
info.res = &DEFINE_RES_IRQ(pdev->irq);
@@ -701,6 +708,7 @@ static int txgbe_ext_phy_init(struct txgbe *txgbe)
int txgbe_init_phy(struct txgbe *txgbe)
{
+ struct wx *wx = txgbe->wx;
int ret;
if (txgbe->wx->media_type == sp_media_copper)
@@ -708,46 +716,48 @@ int txgbe_init_phy(struct txgbe *txgbe)
ret = txgbe_swnodes_register(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to register software nodes\n");
+ wx_err(wx, "failed to register software nodes\n");
return ret;
}
ret = txgbe_mdio_pcs_init(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret);
+ wx_err(wx, "failed to init mdio pcs: %d\n", ret);
goto err_unregister_swnode;
}
ret = txgbe_phylink_init(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to init phylink\n");
+ wx_err(wx, "failed to init phylink\n");
goto err_destroy_xpcs;
}
ret = txgbe_gpio_init(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to init gpio\n");
+ wx_err(wx, "failed to init gpio\n");
goto err_destroy_phylink;
}
ret = txgbe_clock_register(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to register clock: %d\n", ret);
+ wx_err(wx, "failed to register clock: %d\n", ret);
goto err_destroy_phylink;
}
ret = txgbe_i2c_register(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret);
+ wx_err(wx, "failed to init i2c interface: %d\n", ret);
goto err_unregister_clk;
}
ret = txgbe_sfp_register(txgbe);
if (ret) {
- wx_err(txgbe->wx, "failed to register sfp\n");
+ wx_err(wx, "failed to register sfp\n");
goto err_unregister_i2c;
}
+ wx->msix_in_use = true;
+
return 0;
err_unregister_i2c:
@@ -756,7 +766,7 @@ err_unregister_clk:
clkdev_drop(txgbe->clock);
clk_unregister(txgbe->clk);
err_destroy_phylink:
- phylink_destroy(txgbe->phylink);
+ phylink_destroy(wx->phylink);
err_destroy_xpcs:
xpcs_destroy(txgbe->xpcs);
err_unregister_swnode:
@@ -768,8 +778,8 @@ err_unregister_swnode:
void txgbe_remove_phy(struct txgbe *txgbe)
{
if (txgbe->wx->media_type == sp_media_copper) {
- phylink_disconnect_phy(txgbe->phylink);
- phylink_destroy(txgbe->phylink);
+ phylink_disconnect_phy(txgbe->wx->phylink);
+ phylink_destroy(txgbe->wx->phylink);
return;
}
@@ -777,7 +787,8 @@ void txgbe_remove_phy(struct txgbe *txgbe)
platform_device_unregister(txgbe->i2c_dev);
clkdev_drop(txgbe->clock);
clk_unregister(txgbe->clk);
- phylink_destroy(txgbe->phylink);
+ phylink_destroy(txgbe->wx->phylink);
xpcs_destroy(txgbe->xpcs);
software_node_unregister_node_group(txgbe->nodes.group);
+ txgbe->wx->msix_in_use = false;
}
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 3ba9ce43f3..270a6fd9ad 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)
@@ -122,19 +123,16 @@
#define TXGBE_DEFAULT_RX_WORK 128
#endif
-#define TXGBE_INTR_MISC(A) BIT((A)->num_q_vectors)
-#define TXGBE_INTR_QALL(A) (TXGBE_INTR_MISC(A) - 1)
+#define TXGBE_INTR_MISC BIT(0)
+#define TXGBE_INTR_QALL(A) GENMASK((A)->num_q_vectors, 1)
#define TXGBE_MAX_EITR GENMASK(11, 3)
extern char txgbe_driver_name[];
-static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev)
-{
- struct wx *wx = netdev_priv(netdev);
-
- return wx->priv;
-}
+void txgbe_down(struct wx *wx);
+void txgbe_up(struct wx *wx);
+int txgbe_setup_tc(struct net_device *dev, u8 tc);
#define NODE_PROP(_NAME, _PROP) \
(const struct software_node) { \
@@ -175,7 +173,6 @@ struct txgbe {
struct wx *wx;
struct txgbe_nodes nodes;
struct dw_xpcs *xpcs;
- struct phylink *phylink;
struct platform_device *sfp_dev;
struct platform_device *i2c_dev;
struct clk_lookup *clock;