aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale/enetc/enetc_pf.c
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@nxp.com>2019-01-22 15:29:57 +0200
committerDavid S. Miller <davem@davemloft.net>2019-01-24 21:55:53 -0800
commitd382563f541b01f6a38fb1edd762a4cfcd2ca52a (patch)
treefac624c7ec102d8cc0cbd07192d9b8dee010104a /drivers/net/ethernet/freescale/enetc/enetc_pf.c
parentenetc: Add vf to pf messaging support (diff)
downloadlinux-dev-d382563f541b01f6a38fb1edd762a4cfcd2ca52a.tar.xz
linux-dev-d382563f541b01f6a38fb1edd762a4cfcd2ca52a.zip
enetc: Add RFS and RSS support
A ternary match table is used for RFS. If multiple entries in the table match, the entry with the lowest numerical values index is chosen as the matching entry. Entries in the table are identified using an index which takes a value from 0 to PRFSCAPR[NUM_RFS]-1 when accessed by the PSI (PF). Portions of the RFS table can be assigned to each SI by the PSI (PF) driver in PSIaRFSCFGR. Assignments are cumulative, the entries assigned to SIn start after those assigned to SIn-1. The total assignments to all SIs must be equal to or less than the number available to the port as found in PRFSCAPR. For RSS, the Toeplitz hash function used requires two inputs, a 40B random secret key that is supplied through the PRSSKR0-9 registers as well as the relevant pieces of the packet header (n-tuple). The 6 LSB bits of the hash function result will then be used as a pointer to obtain the tag referenced in the 64 entry indirection table. The result will provide a winning group which will be used to help route the received packet. Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com> Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale/enetc/enetc_pf.c')
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 35cad5df71ef..7d28f5e9b46b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -435,6 +435,27 @@ static void enetc_port_setup_primary_mac_address(struct enetc_si *si)
}
}
+static void enetc_port_assign_rfs_entries(struct enetc_si *si)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_hw *hw = &si->hw;
+ int num_entries, vf_entries, i;
+ u32 val;
+
+ /* split RFS entries between functions */
+ val = enetc_port_rd(hw, ENETC_PRFSCAPR);
+ num_entries = ENETC_PRFSCAPR_GET_NUM_RFS(val);
+ vf_entries = num_entries / (pf->total_vfs + 1);
+
+ for (i = 0; i < pf->total_vfs; i++)
+ enetc_port_wr(hw, ENETC_PSIRFSCFGR(i + 1), vf_entries);
+ enetc_port_wr(hw, ENETC_PSIRFSCFGR(0),
+ num_entries - vf_entries * pf->total_vfs);
+
+ /* enable RFS on port */
+ enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE);
+}
+
static void enetc_port_si_configure(struct enetc_si *si)
{
struct enetc_pf *pf = enetc_si_priv(si);
@@ -523,6 +544,7 @@ static void enetc_configure_port_pmac(struct enetc_hw *hw)
static void enetc_configure_port(struct enetc_pf *pf)
{
+ u8 hash_key[ENETC_RSSHASH_KEY_SIZE];
struct enetc_hw *hw = &pf->si->hw;
enetc_configure_port_pmac(hw);
@@ -531,6 +553,13 @@ static void enetc_configure_port(struct enetc_pf *pf)
enetc_port_si_configure(pf->si);
+ /* set up hash key */
+ get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
+ enetc_set_rss_key(hw, hash_key);
+
+ /* split up RFS entries */
+ enetc_port_assign_rfs_entries(pf->si);
+
/* fix-up primary MAC addresses, if not set already */
enetc_port_setup_primary_mac_address(pf->si);
@@ -657,7 +686,7 @@ static int enetc_pf_set_features(struct net_device *ndev,
if (changed & NETIF_F_LOOPBACK)
enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
- return 0;
+ return enetc_set_features(ndev, features);
}
static const struct net_device_ops enetc_ndev_ops = {
@@ -701,6 +730,9 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
+ if (si->num_rss)
+ ndev->hw_features |= NETIF_F_RXHASH;
+
if (si->errata & ENETC_ERR_TXCSUM) {
ndev->hw_features &= ~NETIF_F_HW_CSUM;
ndev->features &= ~NETIF_F_HW_CSUM;