Commit 0f9b232b authored by Don Skidmore's avatar Don Skidmore Committed by Jeff Kirsher

ixgbe: add support for X550 extended RSS support

The new X550 family of MAC's will have a larger RSS hash (16 -> 64).
It will also support individual VF to have their own independent RSS
hash key.  This patch will enable this functionality
Signed-off-by: default avatarDon Skidmore <donald.c.skidmore@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 9079e416
...@@ -300,16 +300,17 @@ enum ixgbe_ring_f_enum { ...@@ -300,16 +300,17 @@ enum ixgbe_ring_f_enum {
RING_F_ARRAY_SIZE /* must be last in enum set */ RING_F_ARRAY_SIZE /* must be last in enum set */
}; };
#define IXGBE_MAX_RSS_INDICES 16 #define IXGBE_MAX_RSS_INDICES 16
#define IXGBE_MAX_VMDQ_INDICES 64 #define IXGBE_MAX_RSS_INDICES_X550 64
#define IXGBE_MAX_FDIR_INDICES 63 /* based on q_vector limit */ #define IXGBE_MAX_VMDQ_INDICES 64
#define IXGBE_MAX_FCOE_INDICES 8 #define IXGBE_MAX_FDIR_INDICES 63 /* based on q_vector limit */
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1) #define IXGBE_MAX_FCOE_INDICES 8
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1) #define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define IXGBE_MAX_L2A_QUEUES 4 #define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define IXGBE_BAD_L2A_QUEUE 3 #define IXGBE_MAX_L2A_QUEUES 4
#define IXGBE_MAX_MACVLANS 31 #define IXGBE_BAD_L2A_QUEUE 3
#define IXGBE_MAX_DCBMACVLANS 8 #define IXGBE_MAX_MACVLANS 31
#define IXGBE_MAX_DCBMACVLANS 8
struct ixgbe_ring_feature { struct ixgbe_ring_feature {
u16 limit; /* upper limit on feature indices */ u16 limit; /* upper limit on feature indices */
...@@ -764,6 +765,21 @@ struct ixgbe_adapter { ...@@ -764,6 +765,21 @@ struct ixgbe_adapter {
unsigned long fwd_bitmask; /* Bitmask indicating in use pools */ unsigned long fwd_bitmask; /* Bitmask indicating in use pools */
}; };
static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
{
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
return IXGBE_MAX_RSS_INDICES;
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
return IXGBE_MAX_RSS_INDICES_X550;
default:
return 0;
}
}
struct ixgbe_fdir_filter { struct ixgbe_fdir_filter {
struct hlist_node fdir_node; struct hlist_node fdir_node;
union ixgbe_atr_input filter; union ixgbe_atr_input filter;
......
...@@ -2927,7 +2927,7 @@ static unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter) ...@@ -2927,7 +2927,7 @@ static unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter)
max_combined = IXGBE_MAX_FDIR_INDICES; max_combined = IXGBE_MAX_FDIR_INDICES;
} else { } else {
/* support up to 16 queues with RSS */ /* support up to 16 queues with RSS */
max_combined = IXGBE_MAX_RSS_INDICES; max_combined = ixgbe_max_rss_indices(adapter);
} }
return max_combined; return max_combined;
...@@ -2975,6 +2975,7 @@ static int ixgbe_set_channels(struct net_device *dev, ...@@ -2975,6 +2975,7 @@ static int ixgbe_set_channels(struct net_device *dev,
{ {
struct ixgbe_adapter *adapter = netdev_priv(dev); struct ixgbe_adapter *adapter = netdev_priv(dev);
unsigned int count = ch->combined_count; unsigned int count = ch->combined_count;
u8 max_rss_indices = ixgbe_max_rss_indices(adapter);
/* verify they are not requesting separate vectors */ /* verify they are not requesting separate vectors */
if (!count || ch->rx_count || ch->tx_count) if (!count || ch->rx_count || ch->tx_count)
...@@ -2991,9 +2992,9 @@ static int ixgbe_set_channels(struct net_device *dev, ...@@ -2991,9 +2992,9 @@ static int ixgbe_set_channels(struct net_device *dev,
/* update feature limits from largest to smallest supported values */ /* update feature limits from largest to smallest supported values */
adapter->ring_feature[RING_F_FDIR].limit = count; adapter->ring_feature[RING_F_FDIR].limit = count;
/* cap RSS limit at 16 */ /* cap RSS limit */
if (count > IXGBE_MAX_RSS_INDICES) if (count > max_rss_indices)
count = IXGBE_MAX_RSS_INDICES; count = max_rss_indices;
adapter->ring_feature[RING_F_RSS].limit = count; adapter->ring_feature[RING_F_RSS].limit = count;
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
......
...@@ -3217,7 +3217,9 @@ static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed) ...@@ -3217,7 +3217,9 @@ static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed)
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 reta = 0; u32 reta = 0;
int i, j; int i, j;
int reta_entries = 128;
u16 rss_i = adapter->ring_feature[RING_F_RSS].indices; u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
int indices_multi;
/* /*
* Program table for at least 2 queues w/ SR-IOV so that VFs can * Program table for at least 2 queues w/ SR-IOV so that VFs can
...@@ -3231,22 +3233,67 @@ static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed) ...@@ -3231,22 +3233,67 @@ static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed)
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]); IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
/* Fill out the redirection table as follows:
* 82598: 128 (8 bit wide) entries containing pair of 4 bit RSS indices
* 82599/X540: 128 (8 bit wide) entries containing 4 bit RSS index
* X550: 512 (8 bit wide) entries containing 6 bit RSS index
*/
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
indices_multi = 0x11;
else
indices_multi = 0x1;
switch (adapter->hw.mac.type) {
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
reta_entries = 512;
default:
break;
}
/* Fill out redirection table */ /* Fill out redirection table */
for (i = 0, j = 0; i < 128; i++, j++) { for (i = 0, j = 0; i < reta_entries; i++, j++) {
if (j == rss_i)
j = 0;
reta = (reta << 8) | (j * indices_multi);
if ((i & 3) == 3) {
if (i < 128)
IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
else
IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
reta);
}
}
}
static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter, const u32 *seed)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 vfreta = 0;
u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
unsigned int pf_pool = adapter->num_vfs;
int i, j;
/* Fill out hash function seeds */
for (i = 0; i < 10; i++)
IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool), seed[i]);
/* Fill out the redirection table */
for (i = 0, j = 0; i < 64; i++, j++) {
if (j == rss_i) if (j == rss_i)
j = 0; j = 0;
/* reta = 4-byte sliding window of vfreta = (vfreta << 8) | j;
* 0x00..(indices-1)(indices-1)00..etc. */
reta = (reta << 8) | (j * 0x11);
if ((i & 3) == 3) if ((i & 3) == 3)
IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); IXGBE_WRITE_REG(hw, IXGBE_PFVFRETA(i >> 2, pf_pool),
vfreta);
} }
} }
static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 mrqc = 0, rss_field = 0; u32 mrqc = 0, rss_field = 0, vfmrqc = 0;
u32 rss_key[10]; u32 rss_key[10];
u32 rxcsum; u32 rxcsum;
...@@ -3292,9 +3339,24 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) ...@@ -3292,9 +3339,24 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
netdev_rss_key_fill(rss_key, sizeof(rss_key)); netdev_rss_key_fill(rss_key, sizeof(rss_key));
ixgbe_setup_reta(adapter, rss_key); if ((hw->mac.type >= ixgbe_mac_X550) &&
mrqc |= rss_field; (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) {
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); unsigned int pf_pool = adapter->num_vfs;
/* Enable VF RSS mode */
mrqc |= IXGBE_MRQC_MULTIPLE_RSS;
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
/* Setup RSS through the VF registers */
ixgbe_setup_vfreta(adapter, rss_key);
vfmrqc = IXGBE_MRQC_RSSEN;
vfmrqc |= rss_field;
IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), vfmrqc);
} else {
ixgbe_setup_reta(adapter, rss_key);
mrqc |= rss_field;
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
} }
/** /**
...@@ -5056,7 +5118,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -5056,7 +5118,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
hw->subsystem_device_id = pdev->subsystem_device; hw->subsystem_device_id = pdev->subsystem_device;
/* Set common capability flags and settings */ /* Set common capability flags and settings */
rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus()); rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
adapter->ring_feature[RING_F_RSS].limit = rss; adapter->ring_feature[RING_F_RSS].limit = rss;
adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
......
...@@ -221,7 +221,8 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter) ...@@ -221,7 +221,8 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
if (adapter->ring_feature[RING_F_VMDQ].limit == 1) { if (adapter->ring_feature[RING_F_VMDQ].limit == 1) {
adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus()); rss = min_t(int, ixgbe_max_rss_indices(adapter),
num_online_cpus());
} else { } else {
rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus()); rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus());
} }
......
...@@ -297,6 +297,7 @@ struct ixgbe_thermal_sensor_data { ...@@ -297,6 +297,7 @@ struct ixgbe_thermal_sensor_data {
#define IXGBE_IMIRVP 0x05AC0 #define IXGBE_IMIRVP 0x05AC0
#define IXGBE_VMD_CTL 0x0581C #define IXGBE_VMD_CTL 0x0581C
#define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */
#define IXGBE_ERETA(_i) (0x0EE80 + ((_i) * 4)) /* 96 of these (0-95) */
#define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */
/* Registers for setting up RSS on X550 with SRIOV /* Registers for setting up RSS on X550 with SRIOV
...@@ -2016,6 +2017,7 @@ enum { ...@@ -2016,6 +2017,7 @@ enum {
#define IXGBE_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IXGBE_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define IXGBE_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define IXGBE_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000
#define IXGBE_MRQC_MULTIPLE_RSS 0x00002000
#define IXGBE_MRQC_L3L4TXSWEN 0x00008000 #define IXGBE_MRQC_L3L4TXSWEN 0x00008000
#define IXGBE_FWSM_TS_ENABLED 0x1 #define IXGBE_FWSM_TS_ENABLED 0x1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment