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