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