提交 23c9ef2b 编写于 作者: D David S. Miller

Merge branch 'mvpp2-add-RSS-support'

Maxime Chevallier says:

====================
net: mvpp2: add RSS support

This series adds support for RSS on PPv2. There already was some code to
handle the RSS tables, but the driver was missing all the classification
steps required to actually use these tables.

RSS is used through the classifier, using at least 2 lookups :
 - One using the C2 engine, a TCAM engine that match the packet based on
   some header extracted fields, assigns the default rx queue for that
   packet and tag it for RSS
 - One using the C3Hx engine, which computes the hash that's used to perform
   the lookup in the RSS table.

Since RSS spreads the load across CPUs, we need to make sure that packets
from the same flow are always assigned the same rx queue, to prevent
re-ordering.

This series therefore adds a classification step based on the Header Parser,
that separate ingress traffic into 52 flows, based on some L2, L3 and L4
parameters.

Patches 1 and 2 fix some header issues, from the driver splitting

Patches 3 to 7 make sure the correct receive queue setup is used for RSS

Patches 8 to 14 deal with the way we handle the RSS tables

Patch 15 implement basic classifier configuration, by using it to assign the
default receive queue

Patch 16 implement the ingress traffic splitting into multiple flows

Patch 17 adds RSS support, by using the needed classification steps

Patch 18 adds the required ethtool ops to configure the flow hash parameters

This was tested on MacchiatoBin, giving some nice performance improvements
using ip forwarding (going from 5Gbps to 9.6Gbps total throughput).

RSS is disabled by default.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -73,9 +73,9 @@ ...@@ -73,9 +73,9 @@
#define MVPP22_RSS_INDEX_TABLE_ENTRY(idx) (idx) #define MVPP22_RSS_INDEX_TABLE_ENTRY(idx) (idx)
#define MVPP22_RSS_INDEX_TABLE(idx) ((idx) << 8) #define MVPP22_RSS_INDEX_TABLE(idx) ((idx) << 8)
#define MVPP22_RSS_INDEX_QUEUE(idx) ((idx) << 16) #define MVPP22_RSS_INDEX_QUEUE(idx) ((idx) << 16)
#define MVPP22_RSS_TABLE_ENTRY 0x1508 #define MVPP22_RXQ2RSS_TABLE 0x1504
#define MVPP22_RSS_TABLE 0x1510
#define MVPP22_RSS_TABLE_POINTER(p) (p) #define MVPP22_RSS_TABLE_POINTER(p) (p)
#define MVPP22_RSS_TABLE_ENTRY 0x1508
#define MVPP22_RSS_WIDTH 0x150c #define MVPP22_RSS_WIDTH 0x150c
/* Classifier Registers */ /* Classifier Registers */
...@@ -87,11 +87,28 @@ ...@@ -87,11 +87,28 @@
#define MVPP2_CLS_LKP_INDEX_WAY_OFFS 6 #define MVPP2_CLS_LKP_INDEX_WAY_OFFS 6
#define MVPP2_CLS_LKP_TBL_REG 0x1818 #define MVPP2_CLS_LKP_TBL_REG 0x1818
#define MVPP2_CLS_LKP_TBL_RXQ_MASK 0xff #define MVPP2_CLS_LKP_TBL_RXQ_MASK 0xff
#define MVPP2_CLS_LKP_FLOW_PTR(flow) ((flow) << 16)
#define MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK BIT(25) #define MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK BIT(25)
#define MVPP2_CLS_FLOW_INDEX_REG 0x1820 #define MVPP2_CLS_FLOW_INDEX_REG 0x1820
#define MVPP2_CLS_FLOW_TBL0_REG 0x1824 #define MVPP2_CLS_FLOW_TBL0_REG 0x1824
#define MVPP2_CLS_FLOW_TBL0_LAST BIT(0)
#define MVPP2_CLS_FLOW_TBL0_ENG_MASK 0x7
#define MVPP2_CLS_FLOW_TBL0_OFFS 1
#define MVPP2_CLS_FLOW_TBL0_ENG(x) ((x) << 1)
#define MVPP2_CLS_FLOW_TBL0_PORT_ID_MASK 0xff
#define MVPP2_CLS_FLOW_TBL0_PORT_ID(port) ((port) << 4)
#define MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL BIT(23)
#define MVPP2_CLS_FLOW_TBL1_REG 0x1828 #define MVPP2_CLS_FLOW_TBL1_REG 0x1828
#define MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK 0x7
#define MVPP2_CLS_FLOW_TBL1_N_FIELDS(x) (x)
#define MVPP2_CLS_FLOW_TBL1_PRIO_MASK 0x3f
#define MVPP2_CLS_FLOW_TBL1_PRIO(x) ((x) << 9)
#define MVPP2_CLS_FLOW_TBL1_SEQ_MASK 0x7
#define MVPP2_CLS_FLOW_TBL1_SEQ(x) ((x) << 15)
#define MVPP2_CLS_FLOW_TBL2_REG 0x182c #define MVPP2_CLS_FLOW_TBL2_REG 0x182c
#define MVPP2_CLS_FLOW_TBL2_FLD_MASK 0x3f
#define MVPP2_CLS_FLOW_TBL2_FLD_OFFS(n) ((n) * 6)
#define MVPP2_CLS_FLOW_TBL2_FLD(n, x) ((x) << ((n) * 6))
#define MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port) (0x1980 + ((port) * 4)) #define MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port) (0x1980 + ((port) * 4))
#define MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS 3 #define MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS 3
#define MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK 0x7 #define MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK 0x7
...@@ -99,6 +116,29 @@ ...@@ -99,6 +116,29 @@
#define MVPP2_CLS_SWFWD_PCTRL_REG 0x19d0 #define MVPP2_CLS_SWFWD_PCTRL_REG 0x19d0
#define MVPP2_CLS_SWFWD_PCTRL_MASK(port) (1 << (port)) #define MVPP2_CLS_SWFWD_PCTRL_MASK(port) (1 << (port))
/* Classifier C2 engine Registers */
#define MVPP22_CLS_C2_TCAM_IDX 0x1b00
#define MVPP22_CLS_C2_TCAM_DATA0 0x1b10
#define MVPP22_CLS_C2_TCAM_DATA1 0x1b14
#define MVPP22_CLS_C2_TCAM_DATA2 0x1b18
#define MVPP22_CLS_C2_TCAM_DATA3 0x1b1c
#define MVPP22_CLS_C2_TCAM_DATA4 0x1b20
#define MVPP22_CLS_C2_PORT_ID(port) ((port) << 8)
#define MVPP22_CLS_C2_ACT 0x1b60
#define MVPP22_CLS_C2_ACT_RSS_EN(act) (((act) & 0x3) << 19)
#define MVPP22_CLS_C2_ACT_FWD(act) (((act) & 0x7) << 13)
#define MVPP22_CLS_C2_ACT_QHIGH(act) (((act) & 0x3) << 11)
#define MVPP22_CLS_C2_ACT_QLOW(act) (((act) & 0x3) << 9)
#define MVPP22_CLS_C2_ATTR0 0x1b64
#define MVPP22_CLS_C2_ATTR0_QHIGH(qh) (((qh) & 0x1f) << 24)
#define MVPP22_CLS_C2_ATTR0_QHIGH_MASK 0x1f
#define MVPP22_CLS_C2_ATTR0_QLOW(ql) (((ql) & 0x7) << 21)
#define MVPP22_CLS_C2_ATTR0_QLOW_MASK 0x7
#define MVPP22_CLS_C2_ATTR1 0x1b68
#define MVPP22_CLS_C2_ATTR2 0x1b6c
#define MVPP22_CLS_C2_ATTR2_RSS_EN BIT(30)
#define MVPP22_CLS_C2_ATTR3 0x1b70
/* Descriptor Manager Top Registers */ /* Descriptor Manager Top Registers */
#define MVPP2_RXQ_NUM_REG 0x2040 #define MVPP2_RXQ_NUM_REG 0x2040
#define MVPP2_RXQ_DESC_ADDR_REG 0x2044 #define MVPP2_RXQ_DESC_ADDR_REG 0x2044
...@@ -500,7 +540,7 @@ ...@@ -500,7 +540,7 @@
#define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) #define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
/* Dfault number of RXQs in use */ /* Dfault number of RXQs in use */
#define MVPP2_DEFAULT_RXQ 4 #define MVPP2_DEFAULT_RXQ 1
/* Max number of Rx descriptors */ /* Max number of Rx descriptors */
#define MVPP2_MAX_RXD_MAX 1024 #define MVPP2_MAX_RXD_MAX 1024
...@@ -557,6 +597,9 @@ ...@@ -557,6 +597,9 @@
#define MVPP2_BIT_TO_WORD(bit) ((bit) / 32) #define MVPP2_BIT_TO_WORD(bit) ((bit) / 32)
#define MVPP2_BIT_IN_WORD(bit) ((bit) % 32) #define MVPP2_BIT_IN_WORD(bit) ((bit) % 32)
/* RSS constants */
#define MVPP22_RSS_TABLE_ENTRIES 32
/* IPv6 max L3 address size */ /* IPv6 max L3 address size */
#define MVPP2_MAX_L3_ADDR_SIZE 16 #define MVPP2_MAX_L3_ADDR_SIZE 16
...@@ -798,6 +841,9 @@ struct mvpp2_port { ...@@ -798,6 +841,9 @@ struct mvpp2_port {
bool has_tx_irqs; bool has_tx_irqs;
u32 tx_time_coal; u32 tx_time_coal;
/* RSS indirection table */
u32 indir[MVPP22_RSS_TABLE_ENTRIES];
}; };
/* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the /* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
......
...@@ -13,15 +13,178 @@ ...@@ -13,15 +13,178 @@
#ifndef _MVPP2_CLS_H_ #ifndef _MVPP2_CLS_H_
#define _MVPP2_CLS_H_ #define _MVPP2_CLS_H_
#include "mvpp2.h"
#include "mvpp2_prs.h"
/* Classifier constants */ /* Classifier constants */
#define MVPP2_CLS_FLOWS_TBL_SIZE 512 #define MVPP2_CLS_FLOWS_TBL_SIZE 512
#define MVPP2_CLS_FLOWS_TBL_DATA_WORDS 3 #define MVPP2_CLS_FLOWS_TBL_DATA_WORDS 3
#define MVPP2_CLS_LKP_TBL_SIZE 64 #define MVPP2_CLS_LKP_TBL_SIZE 64
#define MVPP2_CLS_RX_QUEUES 256 #define MVPP2_CLS_RX_QUEUES 256
/* RSS constants */ /* Classifier flow constants */
#define MVPP22_RSS_TABLE_ENTRIES 32
#define MVPP2_FLOW_N_FIELDS 4
enum mvpp2_cls_engine {
MVPP22_CLS_ENGINE_C2 = 1,
MVPP22_CLS_ENGINE_C3A,
MVPP22_CLS_ENGINE_C3B,
MVPP22_CLS_ENGINE_C4,
MVPP22_CLS_ENGINE_C3HA = 6,
MVPP22_CLS_ENGINE_C3HB = 7,
};
#define MVPP22_CLS_HEK_OPT_MAC_DA BIT(0)
#define MVPP22_CLS_HEK_OPT_VLAN BIT(1)
#define MVPP22_CLS_HEK_OPT_L3_PROTO BIT(2)
#define MVPP22_CLS_HEK_OPT_IP4SA BIT(3)
#define MVPP22_CLS_HEK_OPT_IP4DA BIT(4)
#define MVPP22_CLS_HEK_OPT_IP6SA BIT(5)
#define MVPP22_CLS_HEK_OPT_IP6DA BIT(6)
#define MVPP22_CLS_HEK_OPT_L4SIP BIT(7)
#define MVPP22_CLS_HEK_OPT_L4DIP BIT(8)
#define MVPP22_CLS_HEK_N_FIELDS 9
#define MVPP22_CLS_HEK_L4_OPTS (MVPP22_CLS_HEK_OPT_L4SIP | \
MVPP22_CLS_HEK_OPT_L4DIP)
#define MVPP22_CLS_HEK_IP4_2T (MVPP22_CLS_HEK_OPT_IP4SA | \
MVPP22_CLS_HEK_OPT_IP4DA)
#define MVPP22_CLS_HEK_IP6_2T (MVPP22_CLS_HEK_OPT_IP6SA | \
MVPP22_CLS_HEK_OPT_IP6DA)
/* The fifth tuple in "5T" is the L4_Info field */
#define MVPP22_CLS_HEK_IP4_5T (MVPP22_CLS_HEK_IP4_2T | \
MVPP22_CLS_HEK_L4_OPTS)
#define MVPP22_CLS_HEK_IP6_5T (MVPP22_CLS_HEK_IP6_2T | \
MVPP22_CLS_HEK_L4_OPTS)
enum mvpp2_cls_field_id {
MVPP22_CLS_FIELD_MAC_DA = 0x03,
MVPP22_CLS_FIELD_VLAN = 0x06,
MVPP22_CLS_FIELD_L3_PROTO = 0x0f,
MVPP22_CLS_FIELD_IP4SA = 0x10,
MVPP22_CLS_FIELD_IP4DA = 0x11,
MVPP22_CLS_FIELD_IP6SA = 0x17,
MVPP22_CLS_FIELD_IP6DA = 0x1a,
MVPP22_CLS_FIELD_L4SIP = 0x1d,
MVPP22_CLS_FIELD_L4DIP = 0x1e,
};
enum mvpp2_cls_flow_seq {
MVPP2_CLS_FLOW_SEQ_NORMAL = 0,
MVPP2_CLS_FLOW_SEQ_FIRST1,
MVPP2_CLS_FLOW_SEQ_FIRST2,
MVPP2_CLS_FLOW_SEQ_LAST,
MVPP2_CLS_FLOW_SEQ_MIDDLE
};
/* Classifier C2 engine constants */
#define MVPP22_CLS_C2_TCAM_EN(data) ((data) << 16)
enum mvpp22_cls_c2_action {
MVPP22_C2_NO_UPD = 0,
MVPP22_C2_NO_UPD_LOCK,
MVPP22_C2_UPD,
MVPP22_C2_UPD_LOCK,
};
enum mvpp22_cls_c2_fwd_action {
MVPP22_C2_FWD_NO_UPD = 0,
MVPP22_C2_FWD_NO_UPD_LOCK,
MVPP22_C2_FWD_SW,
MVPP22_C2_FWD_SW_LOCK,
MVPP22_C2_FWD_HW,
MVPP22_C2_FWD_HW_LOCK,
MVPP22_C2_FWD_HW_LOW_LAT,
MVPP22_C2_FWD_HW_LOW_LAT_LOCK,
};
#define MVPP2_CLS_C2_TCAM_WORDS 5
#define MVPP2_CLS_C2_ATTR_WORDS 5
struct mvpp2_cls_c2_entry {
u32 index;
u32 tcam[MVPP2_CLS_C2_TCAM_WORDS];
u32 act;
u32 attr[MVPP2_CLS_C2_ATTR_WORDS];
};
/* Classifier C2 engine entries */
#define MVPP22_CLS_C2_RSS_ENTRY(port) (port)
#define MVPP22_CLS_C2_N_ENTRIES MVPP2_MAX_PORTS
/* RSS flow entries in the flow table. We have 2 entries per port for RSS.
*
* The first performs a lookup using the C2 TCAM engine, to tag the
* packet for software forwarding (needed for RSS), enable or disable RSS, and
* assign the default rx queue.
*
* The second configures the hash generation, by specifying which fields of the
* packet header are used to generate the hash, and specifies the relevant hash
* engine to use.
*/
#define MVPP22_RSS_FLOW_C2_OFFS 0
#define MVPP22_RSS_FLOW_HASH_OFFS 1
#define MVPP22_RSS_FLOW_SIZE (MVPP22_RSS_FLOW_HASH_OFFS + 1)
#define MVPP22_RSS_FLOW_C2(port) ((port) * MVPP22_RSS_FLOW_SIZE + \
MVPP22_RSS_FLOW_C2_OFFS)
#define MVPP22_RSS_FLOW_HASH(port) ((port) * MVPP22_RSS_FLOW_SIZE + \
MVPP22_RSS_FLOW_HASH_OFFS)
#define MVPP22_RSS_FLOW_FIRST(port) MVPP22_RSS_FLOW_C2(port)
/* Packet flow ID */
enum mvpp2_prs_flow {
MVPP2_FL_START = 8,
MVPP2_FL_IP4_TCP_NF_UNTAG = MVPP2_FL_START,
MVPP2_FL_IP4_UDP_NF_UNTAG,
MVPP2_FL_IP4_TCP_NF_TAG,
MVPP2_FL_IP4_UDP_NF_TAG,
MVPP2_FL_IP6_TCP_NF_UNTAG,
MVPP2_FL_IP6_UDP_NF_UNTAG,
MVPP2_FL_IP6_TCP_NF_TAG,
MVPP2_FL_IP6_UDP_NF_TAG,
MVPP2_FL_IP4_TCP_FRAG_UNTAG,
MVPP2_FL_IP4_UDP_FRAG_UNTAG,
MVPP2_FL_IP4_TCP_FRAG_TAG,
MVPP2_FL_IP4_UDP_FRAG_TAG,
MVPP2_FL_IP6_TCP_FRAG_UNTAG,
MVPP2_FL_IP6_UDP_FRAG_UNTAG,
MVPP2_FL_IP6_TCP_FRAG_TAG,
MVPP2_FL_IP6_UDP_FRAG_TAG,
MVPP2_FL_IP4_UNTAG, /* non-TCP, non-UDP, same for below */
MVPP2_FL_IP4_TAG,
MVPP2_FL_IP6_UNTAG,
MVPP2_FL_IP6_TAG,
MVPP2_FL_NON_IP_UNTAG,
MVPP2_FL_NON_IP_TAG,
MVPP2_FL_LAST,
};
struct mvpp2_cls_flow {
/* The L2-L4 traffic flow type */
int flow_type;
/* The first id in the flow table for this flow */
u16 flow_id;
/* The supported HEK fields for this flow */
u16 supported_hash_opts;
/* The Header Parser result_info that matches this flow */
struct mvpp2_prs_result_info prs_ri;
};
#define MVPP2_N_FLOWS 52
#define MVPP2_ENTRIES_PER_FLOW (MVPP2_MAX_PORTS + 1)
#define MVPP2_FLOW_C2_ENTRY(id) ((id) * MVPP2_ENTRIES_PER_FLOW)
#define MVPP2_PORT_FLOW_HASH_ENTRY(port, id) ((id) * MVPP2_ENTRIES_PER_FLOW + \
(port) + 1)
struct mvpp2_cls_flow_entry { struct mvpp2_cls_flow_entry {
u32 index; u32 index;
u32 data[MVPP2_CLS_FLOWS_TBL_DATA_WORDS]; u32 data[MVPP2_CLS_FLOWS_TBL_DATA_WORDS];
...@@ -33,7 +196,15 @@ struct mvpp2_cls_lookup_entry { ...@@ -33,7 +196,15 @@ struct mvpp2_cls_lookup_entry {
u32 data; u32 data;
}; };
void mvpp22_init_rss(struct mvpp2_port *port); void mvpp22_rss_fill_table(struct mvpp2_port *port, u32 table);
void mvpp22_rss_port_init(struct mvpp2_port *port);
void mvpp22_rss_enable(struct mvpp2_port *port);
void mvpp22_rss_disable(struct mvpp2_port *port);
int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info);
int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info);
void mvpp2_cls_init(struct mvpp2 *priv); void mvpp2_cls_init(struct mvpp2 *priv);
......
...@@ -66,7 +66,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, ...@@ -66,7 +66,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
#define MVPP2_QDIST_SINGLE_MODE 0 #define MVPP2_QDIST_SINGLE_MODE 0
#define MVPP2_QDIST_MULTI_MODE 1 #define MVPP2_QDIST_MULTI_MODE 1
static int queue_mode = MVPP2_QDIST_SINGLE_MODE; static int queue_mode = MVPP2_QDIST_MULTI_MODE;
module_param(queue_mode, int, 0444); module_param(queue_mode, int, 0444);
MODULE_PARM_DESC(queue_mode, "Set queue_mode (single=0, multi=1)"); MODULE_PARM_DESC(queue_mode, "Set queue_mode (single=0, multi=1)");
...@@ -3276,6 +3276,11 @@ static void mvpp2_irqs_deinit(struct mvpp2_port *port) ...@@ -3276,6 +3276,11 @@ static void mvpp2_irqs_deinit(struct mvpp2_port *port)
} }
} }
static bool mvpp22_rss_is_supported(void)
{
return queue_mode == MVPP2_QDIST_MULTI_MODE;
}
static int mvpp2_open(struct net_device *dev) static int mvpp2_open(struct net_device *dev)
{ {
struct mvpp2_port *port = netdev_priv(dev); struct mvpp2_port *port = netdev_priv(dev);
...@@ -3368,9 +3373,6 @@ static int mvpp2_open(struct net_device *dev) ...@@ -3368,9 +3373,6 @@ static int mvpp2_open(struct net_device *dev)
mvpp2_start_dev(port); mvpp2_start_dev(port);
if (priv->hw_version == MVPP22)
mvpp22_init_rss(port);
/* Start hardware statistics gathering */ /* Start hardware statistics gathering */
queue_delayed_work(priv->stats_queue, &port->stats_work, queue_delayed_work(priv->stats_queue, &port->stats_work,
MVPP2_MIB_COUNTERS_STATS_DELAY); MVPP2_MIB_COUNTERS_STATS_DELAY);
...@@ -3629,6 +3631,13 @@ static int mvpp2_set_features(struct net_device *dev, ...@@ -3629,6 +3631,13 @@ static int mvpp2_set_features(struct net_device *dev,
} }
} }
if (changed & NETIF_F_RXHASH) {
if (features & NETIF_F_RXHASH)
mvpp22_rss_enable(port);
else
mvpp22_rss_disable(port);
}
return 0; return 0;
} }
...@@ -3816,6 +3825,94 @@ static int mvpp2_ethtool_set_link_ksettings(struct net_device *dev, ...@@ -3816,6 +3825,94 @@ static int mvpp2_ethtool_set_link_ksettings(struct net_device *dev,
return phylink_ethtool_ksettings_set(port->phylink, cmd); return phylink_ethtool_ksettings_set(port->phylink, cmd);
} }
static int mvpp2_ethtool_get_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *info, u32 *rules)
{
struct mvpp2_port *port = netdev_priv(dev);
int ret = 0;
if (!mvpp22_rss_is_supported())
return -EOPNOTSUPP;
switch (info->cmd) {
case ETHTOOL_GRXFH:
ret = mvpp2_ethtool_rxfh_get(port, info);
break;
case ETHTOOL_GRXRINGS:
info->data = port->nrxqs;
break;
default:
return -ENOTSUPP;
}
return ret;
}
static int mvpp2_ethtool_set_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *info)
{
struct mvpp2_port *port = netdev_priv(dev);
int ret = 0;
if (!mvpp22_rss_is_supported())
return -EOPNOTSUPP;
switch (info->cmd) {
case ETHTOOL_SRXFH:
ret = mvpp2_ethtool_rxfh_set(port, info);
break;
default:
return -EOPNOTSUPP;
}
return ret;
}
static u32 mvpp2_ethtool_get_rxfh_indir_size(struct net_device *dev)
{
return mvpp22_rss_is_supported() ? MVPP22_RSS_TABLE_ENTRIES : 0;
}
static int mvpp2_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct mvpp2_port *port = netdev_priv(dev);
if (!mvpp22_rss_is_supported())
return -EOPNOTSUPP;
if (indir)
memcpy(indir, port->indir,
ARRAY_SIZE(port->indir) * sizeof(port->indir[0]));
if (hfunc)
*hfunc = ETH_RSS_HASH_CRC32;
return 0;
}
static int mvpp2_ethtool_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct mvpp2_port *port = netdev_priv(dev);
if (!mvpp22_rss_is_supported())
return -EOPNOTSUPP;
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_CRC32)
return -EOPNOTSUPP;
if (key)
return -EOPNOTSUPP;
if (indir) {
memcpy(port->indir, indir,
ARRAY_SIZE(port->indir) * sizeof(port->indir[0]));
mvpp22_rss_fill_table(port, port->id);
}
return 0;
}
/* Device ops */ /* Device ops */
static const struct net_device_ops mvpp2_netdev_ops = { static const struct net_device_ops mvpp2_netdev_ops = {
...@@ -3847,6 +3944,12 @@ static const struct ethtool_ops mvpp2_eth_tool_ops = { ...@@ -3847,6 +3944,12 @@ static const struct ethtool_ops mvpp2_eth_tool_ops = {
.set_pauseparam = mvpp2_ethtool_set_pause_param, .set_pauseparam = mvpp2_ethtool_set_pause_param,
.get_link_ksettings = mvpp2_ethtool_get_link_ksettings, .get_link_ksettings = mvpp2_ethtool_get_link_ksettings,
.set_link_ksettings = mvpp2_ethtool_set_link_ksettings, .set_link_ksettings = mvpp2_ethtool_set_link_ksettings,
.get_rxnfc = mvpp2_ethtool_get_rxnfc,
.set_rxnfc = mvpp2_ethtool_set_rxnfc,
.get_rxfh_indir_size = mvpp2_ethtool_get_rxfh_indir_size,
.get_rxfh = mvpp2_ethtool_get_rxfh,
.set_rxfh = mvpp2_ethtool_set_rxfh,
}; };
/* Used for PPv2.1, or PPv2.2 with the old Device Tree binding that /* Used for PPv2.1, or PPv2.2 with the old Device Tree binding that
...@@ -3988,8 +4091,8 @@ static int mvpp2_port_init(struct mvpp2_port *port) ...@@ -3988,8 +4091,8 @@ static int mvpp2_port_init(struct mvpp2_port *port)
MVPP2_MAX_PORTS * priv->max_port_rxqs) MVPP2_MAX_PORTS * priv->max_port_rxqs)
return -EINVAL; return -EINVAL;
if (port->nrxqs % 4 || (port->nrxqs > priv->max_port_rxqs) || if (port->nrxqs % MVPP2_DEFAULT_RXQ ||
(port->ntxqs > MVPP2_MAX_TXQ)) port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ)
return -EINVAL; return -EINVAL;
/* Disable port */ /* Disable port */
...@@ -4078,6 +4181,9 @@ static int mvpp2_port_init(struct mvpp2_port *port) ...@@ -4078,6 +4181,9 @@ static int mvpp2_port_init(struct mvpp2_port *port)
mvpp2_cls_oversize_rxq_set(port); mvpp2_cls_oversize_rxq_set(port);
mvpp2_cls_port_config(port); mvpp2_cls_port_config(port);
if (mvpp22_rss_is_supported())
mvpp22_rss_port_init(port);
/* Provide an initial Rx packet size */ /* Provide an initial Rx packet size */
port->pkt_size = MVPP2_RX_PKT_SIZE(port->dev->mtu); port->pkt_size = MVPP2_RX_PKT_SIZE(port->dev->mtu);
...@@ -4684,6 +4790,9 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -4684,6 +4790,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO | dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
NETIF_F_HW_VLAN_CTAG_FILTER; NETIF_F_HW_VLAN_CTAG_FILTER;
if (mvpp22_rss_is_supported())
dev->hw_features |= NETIF_F_RXHASH;
if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) { if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
...@@ -5014,6 +5123,12 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -5014,6 +5123,12 @@ static int mvpp2_probe(struct platform_device *pdev)
(unsigned long)of_device_get_match_data(&pdev->dev); (unsigned long)of_device_get_match_data(&pdev->dev);
} }
/* multi queue mode isn't supported on PPV2.1, fallback to single
* mode
*/
if (priv->hw_version == MVPP21)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
......
...@@ -2409,6 +2409,41 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) ...@@ -2409,6 +2409,41 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
return 0; return 0;
} }
int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
{
struct mvpp2_prs_entry pe;
u8 *ri_byte, *ri_byte_mask;
int tid, i;
memset(&pe, 0, sizeof(pe));
tid = mvpp2_prs_tcam_first_free(priv,
MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
if (tid < 0)
return tid;
pe.index = tid;
ri_byte = (u8 *)&ri;
ri_byte_mask = (u8 *)&ri_mask;
mvpp2_prs_sram_ai_update(&pe, flow, MVPP2_PRS_FLOW_ID_MASK);
mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
for (i = 0; i < 4; i++) {
mvpp2_prs_tcam_data_byte_set(&pe, i, ri_byte[i],
ri_byte_mask[i]);
}
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
mvpp2_prs_hw_write(priv, &pe);
return 0;
}
/* Set prs flow for the port */ /* Set prs flow for the port */
int mvpp2_prs_def_flow(struct mvpp2_port *port) int mvpp2_prs_def_flow(struct mvpp2_port *port)
{ {
......
...@@ -9,14 +9,15 @@ ...@@ -9,14 +9,15 @@
* License version 2. This program is licensed "as is" without any * License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#ifndef _MVPP2_PRS_H_
#define _MVPP2_PRS_H_
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/platform_device.h>
#include "mvpp2.h" #include "mvpp2.h"
#ifndef _MVPP2_PRS_H_
#define _MVPP2_PRS_H_
/* Parser constants */ /* Parser constants */
#define MVPP2_PRS_TCAM_SRAM_SIZE 256 #define MVPP2_PRS_TCAM_SRAM_SIZE 256
#define MVPP2_PRS_TCAM_WORDS 6 #define MVPP2_PRS_TCAM_WORDS 6
...@@ -223,6 +224,10 @@ ...@@ -223,6 +224,10 @@
#define MVPP2_PRS_RI_UDF7_IP6_LITE BIT(29) #define MVPP2_PRS_RI_UDF7_IP6_LITE BIT(29)
#define MVPP2_PRS_RI_DROP_MASK 0x80000000 #define MVPP2_PRS_RI_DROP_MASK 0x80000000
#define MVPP2_PRS_IP_MASK (MVPP2_PRS_RI_L3_PROTO_MASK | \
MVPP2_PRS_RI_IP_FRAG_MASK | \
MVPP2_PRS_RI_L4_PROTO_MASK)
/* Sram additional info bits assignment */ /* Sram additional info bits assignment */
#define MVPP2_PRS_IPV4_DIP_AI_BIT BIT(0) #define MVPP2_PRS_IPV4_DIP_AI_BIT BIT(0)
#define MVPP2_PRS_IPV6_NO_EXT_AI_BIT BIT(0) #define MVPP2_PRS_IPV6_NO_EXT_AI_BIT BIT(0)
...@@ -270,6 +275,11 @@ struct mvpp2_prs_entry { ...@@ -270,6 +275,11 @@ struct mvpp2_prs_entry {
u32 sram[MVPP2_PRS_SRAM_WORDS]; u32 sram[MVPP2_PRS_SRAM_WORDS];
}; };
struct mvpp2_prs_result_info {
u32 ri;
u32 ri_mask;
};
struct mvpp2_prs_shadow { struct mvpp2_prs_shadow {
bool valid; bool valid;
bool finish; bool finish;
...@@ -291,6 +301,8 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add); ...@@ -291,6 +301,8 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add);
int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type); int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type);
int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask);
int mvpp2_prs_def_flow(struct mvpp2_port *port); int mvpp2_prs_def_flow(struct mvpp2_port *port);
void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port); void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册