|
@@ -1550,7 +1550,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
|
|
|
*/
|
|
|
qcount = min_t(int, vsi->alloc_queue_pairs, pf->num_lan_msix);
|
|
|
num_tc_qps = qcount / numtc;
|
|
|
- num_tc_qps = min_t(int, num_tc_qps, I40E_MAX_QUEUES_PER_TC);
|
|
|
+ num_tc_qps = min_t(int, num_tc_qps, i40e_pf_get_max_q_per_tc(pf));
|
|
|
|
|
|
/* Setup queue offset/count for all TCs for given VSI */
|
|
|
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
|
|
@@ -7469,62 +7469,139 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * i40e_config_rss - Prepare for RSS if used
|
|
|
+ * i40e_config_rss_aq - Prepare for RSS using AQ commands
|
|
|
+ * @vsi: vsi structure
|
|
|
+ * @seed: RSS hash seed
|
|
|
+ **/
|
|
|
+static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed)
|
|
|
+{
|
|
|
+ struct i40e_aqc_get_set_rss_key_data rss_key;
|
|
|
+ struct i40e_pf *pf = vsi->back;
|
|
|
+ struct i40e_hw *hw = &pf->hw;
|
|
|
+ bool pf_lut = false;
|
|
|
+ u8 *rss_lut;
|
|
|
+ int ret, i;
|
|
|
+
|
|
|
+ memset(&rss_key, 0, sizeof(rss_key));
|
|
|
+ memcpy(&rss_key, seed, sizeof(rss_key));
|
|
|
+
|
|
|
+ rss_lut = kzalloc(pf->rss_table_size, GFP_KERNEL);
|
|
|
+ if (!rss_lut)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* Populate the LUT with max no. of queues in round robin fashion */
|
|
|
+ for (i = 0; i < vsi->rss_table_size; i++)
|
|
|
+ rss_lut[i] = i % vsi->rss_size;
|
|
|
+
|
|
|
+ ret = i40e_aq_set_rss_key(hw, vsi->id, &rss_key);
|
|
|
+ if (ret) {
|
|
|
+ dev_info(&pf->pdev->dev,
|
|
|
+ "Cannot set RSS key, err %s aq_err %s\n",
|
|
|
+ i40e_stat_str(&pf->hw, ret),
|
|
|
+ i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vsi->type == I40E_VSI_MAIN)
|
|
|
+ pf_lut = true;
|
|
|
+
|
|
|
+ ret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, rss_lut,
|
|
|
+ vsi->rss_table_size);
|
|
|
+ if (ret)
|
|
|
+ dev_info(&pf->pdev->dev,
|
|
|
+ "Cannot set RSS lut, err %s aq_err %s\n",
|
|
|
+ i40e_stat_str(&pf->hw, ret),
|
|
|
+ i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * i40e_vsi_config_rss - Prepare for VSI(VMDq) RSS if used
|
|
|
+ * @vsi: VSI structure
|
|
|
+ **/
|
|
|
+static int i40e_vsi_config_rss(struct i40e_vsi *vsi)
|
|
|
+{
|
|
|
+ u8 seed[I40E_HKEY_ARRAY_SIZE];
|
|
|
+ struct i40e_pf *pf = vsi->back;
|
|
|
+
|
|
|
+ netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE);
|
|
|
+ vsi->rss_size = min_t(int, pf->rss_size, vsi->num_queue_pairs);
|
|
|
+
|
|
|
+ if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE)
|
|
|
+ return i40e_config_rss_aq(vsi, seed);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * i40e_config_rss_reg - Prepare for RSS if used
|
|
|
* @pf: board private structure
|
|
|
+ * @seed: RSS hash seed
|
|
|
**/
|
|
|
-static int i40e_config_rss(struct i40e_pf *pf)
|
|
|
+static int i40e_config_rss_reg(struct i40e_pf *pf, const u8 *seed)
|
|
|
{
|
|
|
- u32 rss_key[I40E_PFQF_HKEY_MAX_INDEX + 1];
|
|
|
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
+ u32 *seed_dw = (u32 *)seed;
|
|
|
+ u32 current_queue = 0;
|
|
|
u32 lut = 0;
|
|
|
int i, j;
|
|
|
- u64 hena;
|
|
|
- u32 reg_val;
|
|
|
|
|
|
- netdev_rss_key_fill(rss_key, sizeof(rss_key));
|
|
|
+ /* Fill out hash function seed */
|
|
|
for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
|
|
|
- wr32(hw, I40E_PFQF_HKEY(i), rss_key[i]);
|
|
|
+ wr32(hw, I40E_PFQF_HKEY(i), seed_dw[i]);
|
|
|
+
|
|
|
+ for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) {
|
|
|
+ lut = 0;
|
|
|
+ for (j = 0; j < 4; j++) {
|
|
|
+ if (current_queue == vsi->rss_size)
|
|
|
+ current_queue = 0;
|
|
|
+ lut |= ((current_queue) << (8 * j));
|
|
|
+ current_queue++;
|
|
|
+ }
|
|
|
+ wr32(&pf->hw, I40E_PFQF_HLUT(i), lut);
|
|
|
+ }
|
|
|
+ i40e_flush(hw);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * i40e_config_rss - Prepare for RSS if used
|
|
|
+ * @pf: board private structure
|
|
|
+ **/
|
|
|
+static int i40e_config_rss(struct i40e_pf *pf)
|
|
|
+{
|
|
|
+ struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
|
|
+ u8 seed[I40E_HKEY_ARRAY_SIZE];
|
|
|
+ struct i40e_hw *hw = &pf->hw;
|
|
|
+ u32 reg_val;
|
|
|
+ u64 hena;
|
|
|
+
|
|
|
+ netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE);
|
|
|
|
|
|
/* By default we enable TCP/UDP with IPv4/IPv6 ptypes */
|
|
|
hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) |
|
|
|
((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32);
|
|
|
- hena |= I40E_DEFAULT_RSS_HENA;
|
|
|
+ hena |= i40e_pf_get_default_rss_hena(pf);
|
|
|
+
|
|
|
wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
|
|
|
wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
|
|
|
|
|
|
vsi->rss_size = min_t(int, pf->rss_size, vsi->num_queue_pairs);
|
|
|
|
|
|
- /* Check capability and Set table size and register per hw expectation*/
|
|
|
+ /* Determine the RSS table size based on the hardware capabilities */
|
|
|
reg_val = rd32(hw, I40E_PFQF_CTL_0);
|
|
|
- if (pf->rss_table_size == 512)
|
|
|
- reg_val |= I40E_PFQF_CTL_0_HASHLUTSIZE_512;
|
|
|
- else
|
|
|
- reg_val &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_512;
|
|
|
+ reg_val = (pf->rss_table_size == 512) ?
|
|
|
+ (reg_val | I40E_PFQF_CTL_0_HASHLUTSIZE_512) :
|
|
|
+ (reg_val & ~I40E_PFQF_CTL_0_HASHLUTSIZE_512);
|
|
|
wr32(hw, I40E_PFQF_CTL_0, reg_val);
|
|
|
|
|
|
- /* Populate the LUT with max no. of queues in round robin fashion */
|
|
|
- for (i = 0, j = 0; i < pf->rss_table_size; i++, j++) {
|
|
|
-
|
|
|
- /* The assumption is that lan qp count will be the highest
|
|
|
- * qp count for any PF VSI that needs RSS.
|
|
|
- * If multiple VSIs need RSS support, all the qp counts
|
|
|
- * for those VSIs should be a power of 2 for RSS to work.
|
|
|
- * If LAN VSI is the only consumer for RSS then this requirement
|
|
|
- * is not necessary.
|
|
|
- */
|
|
|
- if (j == vsi->rss_size)
|
|
|
- j = 0;
|
|
|
- /* lut = 4-byte sliding window of 4 lut entries */
|
|
|
- lut = (lut << 8) | (j &
|
|
|
- (BIT(pf->hw.func_caps.rss_table_entry_width) - 1));
|
|
|
- /* On i = 3, we have 4 entries in lut; write to the register */
|
|
|
- if ((i & 3) == 3)
|
|
|
- wr32(hw, I40E_PFQF_HLUT(i >> 2), lut);
|
|
|
- }
|
|
|
- i40e_flush(hw);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE)
|
|
|
+ return i40e_config_rss_aq(pf->vsi[pf->lan_vsi], seed);
|
|
|
+ else
|
|
|
+ return i40e_config_rss_reg(pf, seed);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -7765,9 +7842,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
|
|
|
}
|
|
|
|
|
|
if (pf->hw.func_caps.vmdq) {
|
|
|
- pf->flags |= I40E_FLAG_VMDQ_ENABLED;
|
|
|
pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
|
|
|
- pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ;
|
|
|
+ pf->flags |= I40E_FLAG_VMDQ_ENABLED;
|
|
|
}
|
|
|
|
|
|
#ifdef I40E_FCOE
|
|
@@ -8948,6 +9024,10 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ if ((pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) &&
|
|
|
+ (vsi->type == I40E_VSI_VMDQ2)) {
|
|
|
+ ret = i40e_vsi_config_rss(vsi);
|
|
|
+ }
|
|
|
return vsi;
|
|
|
|
|
|
err_rings:
|