forked from Ivasoft/openwrt
mvebu: backport upstream ethernet driver improvements and enable buffer manager support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Wed, 9 Dec 2015 18:23:50 +0100
|
||||
Subject: [PATCH] net: mvneta: Add naive RSS support
|
||||
|
||||
This patch adds the support for the RSS related ethtool
|
||||
function. Currently it only uses one entry in the indirection table which
|
||||
allows associating an mvneta interface to a given CPU.
|
||||
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Tested-by: Marcin Wojtas <mw@semihalf.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -261,6 +261,11 @@
|
||||
|
||||
#define MVNETA_TX_MTU_MAX 0x3ffff
|
||||
|
||||
+/* The RSS lookup table actually has 256 entries but we do not use
|
||||
+ * them yet
|
||||
+ */
|
||||
+#define MVNETA_RSS_LU_TABLE_SIZE 1
|
||||
+
|
||||
/* TSO header size */
|
||||
#define TSO_HEADER_SIZE 128
|
||||
|
||||
@@ -382,6 +387,8 @@ struct mvneta_port {
|
||||
unsigned int use_inband_status:1;
|
||||
|
||||
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
|
||||
+
|
||||
+ u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
|
||||
};
|
||||
|
||||
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
|
||||
@@ -1067,7 +1074,7 @@ static void mvneta_defaults_set(struct m
|
||||
if ((rxq % max_cpu) == cpu)
|
||||
rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
|
||||
|
||||
- if (cpu == rxq_def)
|
||||
+ if (cpu == pp->rxq_def)
|
||||
txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
|
||||
|
||||
mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
|
||||
@@ -2508,6 +2515,18 @@ static void mvneta_percpu_unmask_interru
|
||||
MVNETA_MISCINTR_INTR_MASK);
|
||||
}
|
||||
|
||||
+static void mvneta_percpu_mask_interrupt(void *arg)
|
||||
+{
|
||||
+ struct mvneta_port *pp = arg;
|
||||
+
|
||||
+ /* All the queue are masked, but actually only the ones
|
||||
+ * maped to this CPU will be masked
|
||||
+ */
|
||||
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
|
||||
+ mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
|
||||
+ mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
|
||||
+}
|
||||
+
|
||||
static void mvneta_start_dev(struct mvneta_port *pp)
|
||||
{
|
||||
unsigned int cpu;
|
||||
@@ -3231,6 +3250,106 @@ static int mvneta_ethtool_get_sset_count
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
+static u32 mvneta_ethtool_get_rxfh_indir_size(struct net_device *dev)
|
||||
+{
|
||||
+ return MVNETA_RSS_LU_TABLE_SIZE;
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_get_rxnfc(struct net_device *dev,
|
||||
+ struct ethtool_rxnfc *info,
|
||||
+ u32 *rules __always_unused)
|
||||
+{
|
||||
+ switch (info->cmd) {
|
||||
+ case ETHTOOL_GRXRINGS:
|
||||
+ info->data = rxq_number;
|
||||
+ return 0;
|
||||
+ case ETHTOOL_GRXFH:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mvneta_config_rss(struct mvneta_port *pp)
|
||||
+{
|
||||
+ int cpu;
|
||||
+ u32 val;
|
||||
+
|
||||
+ netif_tx_stop_all_queues(pp->dev);
|
||||
+
|
||||
+ for_each_online_cpu(cpu)
|
||||
+ smp_call_function_single(cpu, mvneta_percpu_mask_interrupt,
|
||||
+ pp, true);
|
||||
+
|
||||
+ /* We have to synchronise on the napi of each CPU */
|
||||
+ for_each_online_cpu(cpu) {
|
||||
+ struct mvneta_pcpu_port *pcpu_port =
|
||||
+ per_cpu_ptr(pp->ports, cpu);
|
||||
+
|
||||
+ napi_synchronize(&pcpu_port->napi);
|
||||
+ napi_disable(&pcpu_port->napi);
|
||||
+ }
|
||||
+
|
||||
+ pp->rxq_def = pp->indir[0];
|
||||
+
|
||||
+ /* Update unicast mapping */
|
||||
+ mvneta_set_rx_mode(pp->dev);
|
||||
+
|
||||
+ /* Update val of portCfg register accordingly with all RxQueue types */
|
||||
+ val = MVNETA_PORT_CONFIG_DEFL_VALUE(pp->rxq_def);
|
||||
+ mvreg_write(pp, MVNETA_PORT_CONFIG, val);
|
||||
+
|
||||
+ /* Update the elected CPU matching the new rxq_def */
|
||||
+ mvneta_percpu_elect(pp);
|
||||
+
|
||||
+ /* We have to synchronise on the napi of each CPU */
|
||||
+ for_each_online_cpu(cpu) {
|
||||
+ struct mvneta_pcpu_port *pcpu_port =
|
||||
+ per_cpu_ptr(pp->ports, cpu);
|
||||
+
|
||||
+ napi_enable(&pcpu_port->napi);
|
||||
+ }
|
||||
+
|
||||
+ netif_tx_start_all_queues(pp->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
+ const u8 *key, const u8 hfunc)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+ /* We require at least one supported parameter to be changed
|
||||
+ * and no change in any of the unsupported parameters
|
||||
+ */
|
||||
+ if (key ||
|
||||
+ (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!indir)
|
||||
+ return 0;
|
||||
+
|
||||
+ memcpy(pp->indir, indir, MVNETA_RSS_LU_TABLE_SIZE);
|
||||
+
|
||||
+ return mvneta_config_rss(pp);
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
||||
+ u8 *hfunc)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+
|
||||
+ if (hfunc)
|
||||
+ *hfunc = ETH_RSS_HASH_TOP;
|
||||
+
|
||||
+ if (!indir)
|
||||
+ return 0;
|
||||
+
|
||||
+ memcpy(indir, pp->indir, MVNETA_RSS_LU_TABLE_SIZE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct net_device_ops mvneta_netdev_ops = {
|
||||
.ndo_open = mvneta_open,
|
||||
.ndo_stop = mvneta_stop,
|
||||
@@ -3255,6 +3374,10 @@ const struct ethtool_ops mvneta_eth_tool
|
||||
.get_strings = mvneta_ethtool_get_strings,
|
||||
.get_ethtool_stats = mvneta_ethtool_get_stats,
|
||||
.get_sset_count = mvneta_ethtool_get_sset_count,
|
||||
+ .get_rxfh_indir_size = mvneta_ethtool_get_rxfh_indir_size,
|
||||
+ .get_rxnfc = mvneta_ethtool_get_rxnfc,
|
||||
+ .get_rxfh = mvneta_ethtool_get_rxfh,
|
||||
+ .set_rxfh = mvneta_ethtool_set_rxfh,
|
||||
};
|
||||
|
||||
/* Initialize hw */
|
||||
@@ -3446,6 +3569,8 @@ static int mvneta_probe(struct platform_
|
||||
|
||||
pp->rxq_def = rxq_def;
|
||||
|
||||
+ pp->indir[0] = rxq_def;
|
||||
+
|
||||
pp->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(pp->clk)) {
|
||||
err = PTR_ERR(pp->clk);
|
||||
Reference in New Issue
Block a user