Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2020 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <rte_malloc.h>
6 : :
7 : : #include "octeontx_ethdev.h"
8 : : #include "octeontx_logs.h"
9 : : #include "octeontx_rxtx.h"
10 : :
11 : : static int
12 : 0 : octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag)
13 : : {
14 : : struct octeontx_vlan_info *vlan = &nic->vlan_info;
15 : : pki_port_vlan_filter_config_t fltr_conf;
16 : : int rc = 0;
17 : :
18 [ # # ]: 0 : if (vlan->filter_on == flag)
19 : : return rc;
20 : :
21 : 0 : fltr_conf.port_type = OCTTX_PORT_TYPE_NET;
22 : 0 : fltr_conf.fltr_conf = flag;
23 : :
24 : 0 : rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf);
25 [ # # ]: 0 : if (rc != 0) {
26 : 0 : octeontx_log_err("Fail to configure vlan hw filter for port %d",
27 : : nic->port_id);
28 : 0 : goto done;
29 : : }
30 : :
31 : 0 : vlan->filter_on = flag;
32 : :
33 : : done:
34 : : return rc;
35 : : }
36 : :
37 : : int
38 [ # # ]: 0 : octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
39 : : {
40 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
41 : : struct rte_eth_rxmode *rxmode;
42 : : int rc = 0;
43 : :
44 : : rxmode = &dev->data->dev_conf.rxmode;
45 : :
46 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_FILTER_MASK) {
47 [ # # ]: 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) {
48 : 0 : rc = octeontx_vlan_hw_filter(nic, true);
49 [ # # ]: 0 : if (rc)
50 : 0 : goto done;
51 : :
52 : 0 : nic->rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
53 : 0 : nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F;
54 : : } else {
55 : 0 : rc = octeontx_vlan_hw_filter(nic, false);
56 [ # # ]: 0 : if (rc)
57 : 0 : goto done;
58 : :
59 : 0 : nic->rx_offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
60 : 0 : nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F;
61 : : }
62 : : }
63 : :
64 : 0 : done:
65 : 0 : return rc;
66 : : }
67 : :
68 : : int
69 [ # # ]: 0 : octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
70 : : {
71 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
72 : : struct octeontx_vlan_info *vlan = &nic->vlan_info;
73 : : pki_port_vlan_filter_entry_config_t fltr_entry;
74 : : struct vlan_entry *entry = NULL;
75 : : int entry_count = 0;
76 : : int rc = -EINVAL;
77 : :
78 [ # # ]: 0 : if (on) {
79 [ # # ]: 0 : TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
80 [ # # ]: 0 : if (entry->vlan_id == vlan_id) {
81 : 0 : octeontx_log_dbg("Vlan Id is already set");
82 : 0 : return 0;
83 : : }
84 : : } else {
85 [ # # ]: 0 : TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
86 : 0 : entry_count++;
87 : :
88 [ # # ]: 0 : if (!entry_count)
89 : : return 0;
90 : : }
91 : :
92 : 0 : fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
93 : 0 : fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
94 : 0 : fltr_entry.vlan_id = vlan_id;
95 : 0 : fltr_entry.entry_conf = on;
96 : :
97 [ # # ]: 0 : if (on) {
98 : 0 : entry = rte_zmalloc("octeontx_nic_vlan_entry",
99 : : sizeof(struct vlan_entry), 0);
100 [ # # ]: 0 : if (!entry) {
101 : 0 : octeontx_log_err("Failed to allocate memory");
102 : 0 : return -ENOMEM;
103 : : }
104 : : }
105 : :
106 : 0 : rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
107 : : &fltr_entry);
108 [ # # ]: 0 : if (rc != 0) {
109 : 0 : octeontx_log_err("Fail to configure vlan filter entry "
110 : : "for port %d", nic->port_id);
111 : 0 : rte_free(entry);
112 : :
113 : 0 : goto done;
114 : : }
115 : :
116 [ # # ]: 0 : if (on) {
117 : 0 : entry->vlan_id = vlan_id;
118 [ # # ]: 0 : TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
119 : : } else {
120 [ # # ]: 0 : TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
121 [ # # ]: 0 : if (entry->vlan_id == vlan_id) {
122 [ # # ]: 0 : TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
123 : 0 : rte_free(entry);
124 : 0 : break;
125 : : }
126 : : }
127 : : }
128 : :
129 : 0 : done:
130 : : return rc;
131 : : }
132 : :
133 : : int
134 : 0 : octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev)
135 : : {
136 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
137 : : int rc;
138 : :
139 : 0 : TAILQ_INIT(&nic->vlan_info.fltr_tbl);
140 : :
141 : 0 : rc = octeontx_dev_vlan_offload_set(dev, RTE_ETH_VLAN_FILTER_MASK);
142 [ # # ]: 0 : if (rc)
143 : 0 : octeontx_log_err("Failed to set vlan offload rc=%d", rc);
144 : :
145 : 0 : return rc;
146 : : }
147 : :
148 : : int
149 : 0 : octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev)
150 : : {
151 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
152 : : struct octeontx_vlan_info *vlan = &nic->vlan_info;
153 : : pki_port_vlan_filter_entry_config_t fltr_entry;
154 : : struct vlan_entry *entry;
155 : : int rc = 0;
156 : :
157 [ # # ]: 0 : TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
158 : 0 : fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
159 : 0 : fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
160 : 0 : fltr_entry.vlan_id = entry->vlan_id;
161 : 0 : fltr_entry.entry_conf = 0;
162 : :
163 : 0 : rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
164 : : &fltr_entry);
165 [ # # ]: 0 : if (rc != 0) {
166 : 0 : octeontx_log_err("Fail to configure vlan filter entry "
167 : : "for port %d", nic->port_id);
168 : 0 : break;
169 : : }
170 : : }
171 : :
172 : 0 : return rc;
173 : : }
174 : :
175 : : int
176 : 0 : octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev)
177 : : {
178 : : struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
179 : : int rc, i;
180 : :
181 : 0 : rc = octeontx_bgx_port_set_link_state(nic->port_id, true);
182 [ # # ]: 0 : if (rc)
183 : 0 : goto done;
184 : :
185 : : /* Start tx queues */
186 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
187 : 0 : octeontx_dev_tx_queue_start(eth_dev, i);
188 : :
189 : 0 : done:
190 : 0 : return rc;
191 : : }
192 : :
193 : : int
194 : 0 : octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev)
195 : : {
196 : : struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
197 : : int i;
198 : :
199 : : /* Stop tx queues */
200 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
201 : 0 : octeontx_dev_tx_queue_stop(eth_dev, i);
202 : :
203 : 0 : return octeontx_bgx_port_set_link_state(nic->port_id, false);
204 : : }
205 : :
206 : : int
207 : 0 : octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev,
208 : : struct rte_eth_fc_conf *fc_conf)
209 : : {
210 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
211 : : octeontx_mbox_bgx_port_fc_cfg_t conf;
212 : : int rc;
213 : :
214 : : memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t));
215 : :
216 : 0 : rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
217 [ # # ]: 0 : if (rc)
218 : : return rc;
219 : :
220 [ # # # # ]: 0 : if (conf.rx_pause && conf.tx_pause)
221 : 0 : fc_conf->mode = RTE_ETH_FC_FULL;
222 [ # # ]: 0 : else if (conf.rx_pause)
223 : 0 : fc_conf->mode = RTE_ETH_FC_RX_PAUSE;
224 [ # # ]: 0 : else if (conf.tx_pause)
225 : 0 : fc_conf->mode = RTE_ETH_FC_TX_PAUSE;
226 : : else
227 : 0 : fc_conf->mode = RTE_ETH_FC_NONE;
228 : :
229 : : /* low_water & high_water values are in Bytes */
230 : 0 : fc_conf->low_water = conf.low_water;
231 : 0 : fc_conf->high_water = conf.high_water;
232 : :
233 : 0 : return rc;
234 : : }
235 : :
236 : : int
237 [ # # ]: 0 : octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev,
238 : : struct rte_eth_fc_conf *fc_conf)
239 : : {
240 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
241 : : struct octeontx_fc_info *fc = &nic->fc;
242 : : octeontx_mbox_bgx_port_fc_cfg_t conf;
243 : : uint8_t tx_pause, rx_pause;
244 : : uint16_t max_high_water;
245 : : int rc;
246 : :
247 [ # # # # ]: 0 : if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd ||
248 : : fc_conf->autoneg) {
249 : 0 : octeontx_log_err("Below flowctrl parameters are not supported "
250 : : "pause_time, mac_ctrl_frame_fwd and autoneg");
251 : 0 : return -EINVAL;
252 : : }
253 : :
254 [ # # ]: 0 : if (fc_conf->high_water == fc->high_water &&
255 [ # # ]: 0 : fc_conf->low_water == fc->low_water &&
256 [ # # ]: 0 : fc_conf->mode == fc->mode)
257 : : return 0;
258 : :
259 : 0 : max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES;
260 : :
261 [ # # ]: 0 : if (fc_conf->high_water > max_high_water ||
262 [ # # ]: 0 : fc_conf->high_water < fc_conf->low_water) {
263 : 0 : octeontx_log_err("Invalid high/low water values "
264 : : "High_water(in Bytes) must <= 0x%x ",
265 : : max_high_water);
266 : 0 : return -EINVAL;
267 : : }
268 : :
269 [ # # # # ]: 0 : if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) {
270 : 0 : octeontx_log_err("High/low water value must be multiple of 16");
271 : 0 : return -EINVAL;
272 : : }
273 : :
274 : 0 : rx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
275 : : (fc_conf->mode == RTE_ETH_FC_RX_PAUSE);
276 : 0 : tx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
277 : : (fc_conf->mode == RTE_ETH_FC_TX_PAUSE);
278 : :
279 : 0 : conf.high_water = fc_conf->high_water;
280 : 0 : conf.low_water = fc_conf->low_water;
281 : 0 : conf.fc_cfg = BGX_PORT_FC_CFG_SET;
282 : 0 : conf.rx_pause = rx_pause;
283 : 0 : conf.tx_pause = tx_pause;
284 : :
285 : 0 : rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
286 [ # # ]: 0 : if (rc)
287 : : return rc;
288 : :
289 : 0 : fc->high_water = fc_conf->high_water;
290 : 0 : fc->low_water = fc_conf->low_water;
291 : 0 : fc->mode = fc_conf->mode;
292 : :
293 : 0 : return rc;
294 : : }
295 : :
296 : : int
297 : 0 : octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev)
298 : : {
299 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
300 : : struct octeontx_fc_info *fc = &nic->fc;
301 : : struct rte_eth_fc_conf fc_conf;
302 : : int rc;
303 : :
304 : 0 : rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf);
305 [ # # ]: 0 : if (rc) {
306 : 0 : octeontx_log_err("Failed to get flow control info");
307 : 0 : return rc;
308 : : }
309 : :
310 : 0 : fc->def_highmark = fc_conf.high_water;
311 : 0 : fc->def_lowmark = fc_conf.low_water;
312 : 0 : fc->def_mode = fc_conf.mode;
313 : :
314 : 0 : return rc;
315 : : }
316 : :
317 : : int
318 : 0 : octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev)
319 : : {
320 : : struct octeontx_nic *nic = octeontx_pmd_priv(dev);
321 : : struct octeontx_fc_info *fc = &nic->fc;
322 : : struct rte_eth_fc_conf fc_conf;
323 : :
324 : : memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
325 : :
326 : : /* Restore flow control parameters with default values */
327 : 0 : fc_conf.high_water = fc->def_highmark;
328 : 0 : fc_conf.low_water = fc->def_lowmark;
329 : 0 : fc_conf.mode = fc->def_mode;
330 : :
331 : 0 : return octeontx_dev_flow_ctrl_set(dev, &fc_conf);
332 : : }
|