aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
diff options
context:
space:
mode:
authorAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>2019-02-28 18:24:24 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-04-18 11:38:47 -0400
commit7b9ffc76bf5998aad8feaa26d9d3fcb65ec7a21b (patch)
tree9935f6c7b53786d7f9ce06d804aa4a42ce541ec4 /drivers/net/ethernet/intel/ice/ice_dcb_lib.c
parent0ebd3ff13ccad2940516ba522ca8d21cea4f56f6 (diff)
ice: Add code for DCB initialization part 3/4
This patch adds a new function ice_pf_dcb_cfg (and related helpers) which applies the DCB configuration obtained from the firmware. As part of this, VSIs/netdevs are updated with traffic class information. This patch requires a bit of a refactor of existing code. 1. For a MIB change event, the associated VSI is closed and brought up again. The gap between closing and opening the VSI can cause a race condition. Fix this by grabbing the rtnl_lock prior to closing the VSI and then only free it after re-opening the VSI during a MIB change event. 2. ice_sched_query_elem is used in ice_sched.c and with this patch, in ice_dcb.c as well. However, ice_dcb.c is not built when CONFIG_DCB is unset. This results in namespace warnings (ice_sched.o: Externally defined symbols with no external references) when CONFIG_DCB is unset. To avoid this move ice_sched_query_elem from ice_sched.c to ice_common.c. Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_dcb_lib.c')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dcb_lib.c204
1 files changed, 203 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
index f2dd41408652..210487a0671d 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
@@ -4,6 +4,189 @@
4#include "ice_dcb_lib.h" 4#include "ice_dcb_lib.h"
5 5
6/** 6/**
7 * ice_dcb_get_ena_tc - return bitmap of enabled TCs
8 * @dcbcfg: DCB config to evaluate for enabled TCs
9 */
10u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg)
11{
12 u8 i, num_tc, ena_tc = 1;
13
14 num_tc = ice_dcb_get_num_tc(dcbcfg);
15
16 for (i = 0; i < num_tc; i++)
17 ena_tc |= BIT(i);
18
19 return ena_tc;
20}
21
22/**
23 * ice_dcb_get_num_tc - Get the number of TCs from DCBX config
24 * @dcbcfg: config to retrieve number of TCs from
25 */
26u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
27{
28 bool tc_unused = false;
29 u8 num_tc = 0;
30 u8 ret = 0;
31 int i;
32
33 /* Scan the ETS Config Priority Table to find traffic classes
34 * enabled and create a bitmask of enabled TCs
35 */
36 for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
37 num_tc |= BIT(dcbcfg->etscfg.prio_table[i]);
38
39 /* Scan bitmask for contiguous TCs starting with TC0 */
40 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
41 if (num_tc & BIT(i)) {
42 if (!tc_unused) {
43 ret++;
44 } else {
45 pr_err("Non-contiguous TCs - Disabling DCB\n");
46 return 1;
47 }
48 } else {
49 tc_unused = true;
50 }
51 }
52
53 /* There is always at least 1 TC */
54 if (!ret)
55 ret = 1;
56
57 return ret;
58}
59
60/**
61 * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
62 * @pf: pointer to the PF struct
63 *
64 * Assumed caller has already disabled all VSIs before
65 * calling this function. Reconfiguring DCB based on
66 * local_dcbx_cfg.
67 */
68static void ice_pf_dcb_recfg(struct ice_pf *pf)
69{
70 struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
71 u8 tc_map = 0;
72 int v, ret;
73
74 /* Update each VSI */
75 ice_for_each_vsi(pf, v) {
76 if (!pf->vsi[v])
77 continue;
78
79 if (pf->vsi[v]->type == ICE_VSI_PF)
80 tc_map = ice_dcb_get_ena_tc(dcbcfg);
81 else
82 tc_map = ICE_DFLT_TRAFFIC_CLASS;
83
84 ret = ice_vsi_cfg_tc(pf->vsi[v], tc_map);
85 if (ret)
86 dev_err(&pf->pdev->dev,
87 "Failed to config TC for VSI index: %d\n",
88 pf->vsi[v]->idx);
89 else
90 ice_vsi_map_rings_to_vectors(pf->vsi[v]);
91 }
92}
93
94/**
95 * ice_pf_dcb_cfg - Apply new DCB configuration
96 * @pf: pointer to the PF struct
97 * @new_cfg: DCBX config to apply
98 */
99static int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg)
100{
101 struct ice_dcbx_cfg *old_cfg, *curr_cfg;
102 struct ice_aqc_port_ets_elem buf = { 0 };
103 int ret = 0;
104
105 curr_cfg = &pf->hw.port_info->local_dcbx_cfg;
106
107 /* Enable DCB tagging only when more than one TC */
108 if (ice_dcb_get_num_tc(new_cfg) > 1) {
109 dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n");
110 set_bit(ICE_FLAG_DCB_ENA, pf->flags);
111 } else {
112 dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n");
113 clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
114 }
115
116 if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) {
117 dev_dbg(&pf->pdev->dev, "No change in DCB config required\n");
118 return ret;
119 }
120
121 /* Store old config in case FW config fails */
122 old_cfg = devm_kzalloc(&pf->pdev->dev, sizeof(*old_cfg), GFP_KERNEL);
123 memcpy(old_cfg, curr_cfg, sizeof(*old_cfg));
124
125 /* avoid race conditions by holding the lock while disabling and
126 * re-enabling the VSI
127 */
128 rtnl_lock();
129 ice_pf_dis_all_vsi(pf, true);
130
131 memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));
132 memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
133
134 /* Only send new config to HW if we are in SW LLDP mode. Otherwise,
135 * the new config came from the HW in the first place.
136 */
137 if (pf->hw.port_info->is_sw_lldp) {
138 ret = ice_set_dcb_cfg(pf->hw.port_info);
139 if (ret) {
140 dev_err(&pf->pdev->dev, "Set DCB Config failed\n");
141 /* Restore previous settings to local config */
142 memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg));
143 goto out;
144 }
145 }
146
147 ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
148 if (ret) {
149 dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
150 goto out;
151 }
152
153 ice_pf_dcb_recfg(pf);
154
155out:
156 ice_pf_ena_all_vsi(pf, true);
157 rtnl_unlock();
158 devm_kfree(&pf->pdev->dev, old_cfg);
159 return ret;
160}
161
162/**
163 * ice_dcb_init_cfg - set the initial DCB config in SW
164 * @pf: pf to apply config to
165 */
166static int ice_dcb_init_cfg(struct ice_pf *pf)
167{
168 struct ice_dcbx_cfg *newcfg;
169 struct ice_port_info *pi;
170 int ret = 0;
171
172 pi = pf->hw.port_info;
173 newcfg = devm_kzalloc(&pf->pdev->dev, sizeof(*newcfg), GFP_KERNEL);
174 if (!newcfg)
175 return -ENOMEM;
176
177 memcpy(newcfg, &pi->local_dcbx_cfg, sizeof(*newcfg));
178 memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
179
180 dev_info(&pf->pdev->dev, "Configuring initial DCB values\n");
181 if (ice_pf_dcb_cfg(pf, newcfg))
182 ret = -EINVAL;
183
184 devm_kfree(&pf->pdev->dev, newcfg);
185
186 return ret;
187}
188
189/**
7 * ice_init_pf_dcb - initialize DCB for a PF 190 * ice_init_pf_dcb - initialize DCB for a PF
8 * @pf: pf to initiialize DCB for 191 * @pf: pf to initiialize DCB for
9 */ 192 */
@@ -12,6 +195,7 @@ int ice_init_pf_dcb(struct ice_pf *pf)
12 struct device *dev = &pf->pdev->dev; 195 struct device *dev = &pf->pdev->dev;
13 struct ice_port_info *port_info; 196 struct ice_port_info *port_info;
14 struct ice_hw *hw = &pf->hw; 197 struct ice_hw *hw = &pf->hw;
198 int err;
15 199
16 port_info = hw->port_info; 200 port_info = hw->port_info;
17 201
@@ -38,5 +222,23 @@ int ice_init_pf_dcb(struct ice_pf *pf)
38 ice_aq_start_stop_dcbx(hw, true, &dcbx_status, NULL); 222 ice_aq_start_stop_dcbx(hw, true, &dcbx_status, NULL);
39 } 223 }
40 224
41 return ice_init_dcb(hw); 225 err = ice_init_dcb(hw);
226 if (err)
227 goto dcb_init_err;
228
229 /* DCBX in FW and LLDP enabled in FW */
230 pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE;
231
232 set_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
233
234 err = ice_dcb_init_cfg(pf);
235 if (err)
236 goto dcb_init_err;
237
238 dev_info(&pf->pdev->dev, "DCBX offload supported\n");
239 return err;
240
241dcb_init_err:
242 dev_err(dev, "DCB init failed\n");
243 return err;
42} 244}