iavf: new driver using new dev infra
[vpp.git] / src / plugins / dev_iavf / port.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright (c) 2023 Cisco Systems, Inc.
3  */
4
5 #include <vnet/vnet.h>
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <dev_iavf/iavf.h>
10 #include <dev_iavf/iavf_regs.h>
11 #include <dev_iavf/virtchnl.h>
12 #include <dev_iavf/virtchnl_funcs.h>
13 #include <vnet/ethernet/ethernet.h>
14
15 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
16   .class_name = "iavf",
17   .subclass_name = "port",
18 };
19
20 static const u8 default_rss_key[] = {
21   0x44, 0x39, 0x79, 0x6b, 0xb5, 0x4c, 0x50, 0x23, 0xb6, 0x75, 0xea, 0x5b, 0x12,
22   0x4f, 0x9f, 0x30, 0xb8, 0xa2, 0xc0, 0x3d, 0xdf, 0xdc, 0x4d, 0x02, 0xa0, 0x8c,
23   0x9b, 0x33, 0x4a, 0xf6, 0x4a, 0x4c, 0x05, 0xc6, 0xfa, 0x34, 0x39, 0x58, 0xd8,
24   0x55, 0x7d, 0x99, 0x58, 0x3a, 0xe1, 0x38, 0xc9, 0x2e, 0x81, 0x15, 0x03, 0x66,
25 };
26
27 const static iavf_dyn_ctln dyn_ctln_disabled = {};
28 const static iavf_dyn_ctln dyn_ctln_enabled = {
29   .clearpba = 1,
30   .interval = IAVF_ITR_INT / 2,
31   .intena = 1,
32 };
33 const static iavf_dyn_ctln dyn_ctln_wb_on_itr = {
34   .clearpba = 1,
35   .itr_indx = 1,
36   .interval = 32 / 2,
37   .wb_on_itr = 1,
38 };
39
40 vnet_dev_rv_t
41 iavf_port_vlan_strip_disable (vlib_main_t *vm, vnet_dev_port_t *port)
42 {
43   vnet_dev_t *dev = port->dev;
44   iavf_port_t *ap = vnet_dev_get_port_data (port);
45   virtchnl_vlan_caps_t vc;
46   vnet_dev_rv_t rv;
47   u32 outer, inner;
48   const u32 mask = VIRTCHNL_VLAN_ETHERTYPE_8100;
49
50   if ((ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) == 0)
51     return iavf_vc_op_disable_vlan_stripping (vm, dev);
52
53   if ((rv = iavf_vc_op_get_offload_vlan_v2_caps (vm, dev, &vc)))
54     return rv;
55
56   outer = vc.offloads.stripping_support.outer;
57   inner = vc.offloads.stripping_support.inner;
58
59   outer = outer & VIRTCHNL_VLAN_TOGGLE ? outer & mask : 0;
60   inner = inner & VIRTCHNL_VLAN_TOGGLE ? inner & mask : 0;
61
62   virtchnl_vlan_setting_t vs = {
63     .vport_id = ap->vsi_id,
64     .outer_ethertype_setting = outer,
65     .inner_ethertype_setting = inner,
66   };
67
68   return iavf_vc_op_disable_vlan_stripping_v2 (vm, dev, &vs);
69 }
70
71 vnet_dev_rv_t
72 iavf_port_init_rss (vlib_main_t *vm, vnet_dev_port_t *port)
73 {
74   vnet_dev_t *dev = port->dev;
75   iavf_port_t *ap = vnet_dev_get_port_data (port);
76   u16 keylen = clib_min (sizeof (default_rss_key), ap->rss_key_size);
77   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_key_t, key, keylen)];
78   virtchnl_rss_key_t *key = (virtchnl_rss_key_t *) buffer;
79
80   if (!port->attr.caps.rss)
81     return VNET_DEV_OK;
82
83   /* config RSS key */
84   *key = (virtchnl_rss_key_t){
85     .vsi_id = ap->vsi_id,
86     .key_len = keylen,
87   };
88
89   clib_memcpy (key->key, default_rss_key, sizeof (default_rss_key));
90
91   return iavf_vc_op_config_rss_key (vm, dev, key);
92 }
93
94 vnet_dev_rv_t
95 iavf_port_update_rss_lut (vlib_main_t *vm, vnet_dev_port_t *port)
96 {
97   vnet_dev_t *dev = port->dev;
98   iavf_port_t *ap = vnet_dev_get_port_data (port);
99   u16 lut_size = clib_min (IAVF_MAX_RSS_LUT_SIZE, ap->rss_lut_size);
100   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_lut_t, lut, lut_size)];
101   virtchnl_rss_lut_t *lut = (virtchnl_rss_lut_t *) buffer;
102   u32 enabled_rxq_bmp = 0;
103
104   if (!port->attr.caps.rss)
105     return VNET_DEV_OK;
106
107   *lut = (virtchnl_rss_lut_t){
108     .vsi_id = ap->vsi_id,
109     .lut_entries = lut_size,
110   };
111
112   foreach_vnet_dev_port_rx_queue (q, port)
113     if (q->enabled)
114       enabled_rxq_bmp |= 1ULL << q->queue_id;
115
116   /* config RSS LUT */
117   for (u32 i = 0, j; i < lut->lut_entries;)
118     foreach_set_bit_index (j, enabled_rxq_bmp)
119       {
120         lut->lut[i++] = j;
121         if (i >= lut->lut_entries)
122           break;
123       }
124
125   return iavf_vc_op_config_rss_lut (vm, dev, lut);
126 }
127
128 vnet_dev_rv_t
129 iavf_port_init_vsi_queues (vlib_main_t *vm, vnet_dev_port_t *port)
130 {
131   vnet_dev_t *dev = port->dev;
132   iavf_port_t *ap = vnet_dev_get_port_data (port);
133   virtchnl_queue_pair_info_t *qpi;
134   u16 vsi_id = ap->vsi_id;
135   u16 data_size = vlib_buffer_get_default_data_size (vm);
136   u16 max_frame_size = port->max_frame_size;
137   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_vsi_queue_config_info_t, qpair,
138                              ap->num_qp)];
139   virtchnl_vsi_queue_config_info_t *ci =
140     (virtchnl_vsi_queue_config_info_t *) buffer;
141
142   *ci = (virtchnl_vsi_queue_config_info_t){
143     .num_queue_pairs = ap->num_qp,
144     .vsi_id = vsi_id,
145   };
146
147   for (u16 i = 0; i < ap->num_qp; i++)
148     ci->qpair[i] = (virtchnl_queue_pair_info_t){
149       .rxq = { .vsi_id = vsi_id, .queue_id = i },
150       .txq = { .vsi_id = vsi_id, .queue_id = i },
151     };
152
153   foreach_vnet_dev_port_rx_queue (q, port)
154     {
155       iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (q);
156       qpi = ci->qpair + q->queue_id;
157       qpi->rxq.ring_len = q->size;
158       qpi->rxq.databuffer_size = data_size;
159       qpi->rxq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, arq->descs);
160       qpi->rxq.max_pkt_size = max_frame_size;
161     }
162
163   foreach_vnet_dev_port_tx_queue (q, port)
164     {
165       iavf_txq_t *atq = vnet_dev_get_tx_queue_data (q);
166       qpi = ci->qpair + q->queue_id;
167       qpi->txq.ring_len = q->size;
168       qpi->txq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, atq->descs);
169     }
170
171   return iavf_vc_op_config_vsi_queues (vm, dev, ci);
172 }
173
174 vnet_dev_rv_t
175 iavf_port_rx_irq_enable_disable (vlib_main_t *vm, vnet_dev_port_t *port,
176                                  int enable)
177 {
178   vnet_dev_t *dev = port->dev;
179   iavf_device_t *ad = vnet_dev_get_data (dev);
180   iavf_port_t *ap = vnet_dev_get_port_data (port);
181   u16 n_threads = vlib_get_n_threads ();
182   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_irq_map_info_t, vecmap, n_threads)];
183   virtchnl_irq_map_info_t *im = (virtchnl_irq_map_info_t *) buffer;
184   vnet_dev_rv_t rv;
185
186   if (port->attr.caps.interrupt_mode)
187     {
188       *im = (virtchnl_irq_map_info_t){
189         .num_vectors = n_threads,
190       };
191       for (u16 i = 0; i < im->num_vectors; i++)
192         im->vecmap[i] = (virtchnl_vector_map_t){
193           .vsi_id = ap->vsi_id,
194           .vector_id = i + 1,
195         };
196       if (enable)
197         foreach_vnet_dev_port_rx_queue (rxq, port)
198           if (rxq->enabled)
199             im->vecmap[rxq->rx_thread_index].rxq_map |= 1 << rxq->queue_id;
200     }
201   else
202     {
203       *im = (virtchnl_irq_map_info_t){
204         .num_vectors = 1,
205         .vecmap[0] = {
206             .vsi_id = ap->vsi_id,
207             .vector_id = 1,
208         },
209       };
210       if (enable)
211         foreach_vnet_dev_port_rx_queue (rxq, port)
212           if (rxq->enabled)
213             im->vecmap[0].rxq_map |= 1 << rxq->queue_id;
214     }
215
216   if ((rv = iavf_vc_op_config_irq_map (vm, dev, im)))
217     return rv;
218
219   for (int i = 0; i < im->num_vectors; i++)
220     {
221       u32 val;
222
223       if (enable == 0)
224         val = dyn_ctln_disabled.as_u32;
225       else if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
226         val = dyn_ctln_wb_on_itr.as_u32;
227       else
228         val = dyn_ctln_enabled.as_u32;
229
230       iavf_reg_write (ad, AVFINT_DYN_CTLN (im->vecmap[i].vector_id), val);
231     }
232
233   return rv;
234 }
235
236 vnet_dev_rv_t
237 iavf_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
238 {
239   vnet_dev_rv_t rv;
240
241   log_debug (port->dev, "port %u", port->port_id);
242
243   if ((rv = iavf_port_vlan_strip_disable (vm, port)))
244     return rv;
245
246   if ((rv = iavf_port_init_rss (vm, port)))
247     return rv;
248
249   if (port->dev->poll_stats)
250     iavf_port_add_counters (vm, port);
251
252   return VNET_DEV_OK;
253 }
254
255 static vnet_dev_rv_t
256 iavf_enable_disable_queues (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
257 {
258   iavf_port_t *ap = vnet_dev_get_port_data (port);
259
260   virtchnl_queue_select_t qs = {
261     .vsi_id = ap->vsi_id,
262   };
263
264   foreach_vnet_dev_port_rx_queue (q, port)
265     if ((enable && q->enabled) || (!enable && q->started))
266       qs.rx_queues |= 1ULL << q->queue_id;
267
268   foreach_vnet_dev_port_tx_queue (q, port)
269     if ((enable && q->enabled) || (!enable && q->started))
270       qs.tx_queues |= 1ULL << q->queue_id;
271
272   return enable ? iavf_vc_op_enable_queues (vm, port->dev, &qs) :
273                         iavf_vc_op_disable_queues (vm, port->dev, &qs);
274 }
275
276 vnet_dev_rv_t
277 iavf_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
278 {
279   vnet_dev_rv_t rv;
280
281   log_debug (port->dev, "port %u", port->port_id);
282
283   foreach_vnet_dev_port_rx_queue (q, port)
284     if (q->enabled)
285       if ((rv = iavf_rx_queue_start (vm, q)))
286         goto done;
287
288   foreach_vnet_dev_port_tx_queue (q, port)
289     if ((rv = iavf_tx_queue_start (vm, q)))
290       goto done;
291
292   if ((rv = iavf_port_update_rss_lut (vm, port)))
293     goto done;
294
295   /* configure qpairs */
296   if ((rv = iavf_port_init_vsi_queues (vm, port)))
297     goto done;
298
299   if ((rv = iavf_port_rx_irq_enable_disable (vm, port, /* enable */ 1)))
300     goto done;
301
302   if ((rv = iavf_enable_disable_queues (vm, port, 1)))
303     goto done;
304
305   if (port->dev->poll_stats)
306     vnet_dev_poll_port_add (vm, port, 1, iavf_port_poll_stats);
307
308 done:
309   if (rv)
310     {
311       foreach_vnet_dev_port_rx_queue (q, port)
312         iavf_rx_queue_stop (vm, q);
313       foreach_vnet_dev_port_tx_queue (q, port)
314         iavf_tx_queue_stop (vm, q);
315     }
316   return rv;
317 }
318
319 void
320 iavf_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
321 {
322   log_debug (port->dev, "port %u", port->port_id);
323
324   iavf_enable_disable_queues (vm, port, /* enable */ 0);
325   iavf_port_rx_irq_enable_disable (vm, port, /* disable */ 0);
326
327   if (port->dev->poll_stats)
328     vnet_dev_poll_port_remove (vm, port, iavf_port_poll_stats);
329
330   foreach_vnet_dev_port_rx_queue (rxq, port)
331     iavf_rx_queue_stop (vm, rxq);
332
333   foreach_vnet_dev_port_tx_queue (txq, port)
334     iavf_tx_queue_stop (vm, txq);
335
336   vnet_dev_port_state_change (vm, port,
337                               (vnet_dev_port_state_changes_t){
338                                 .change.link_state = 1,
339                                 .change.link_speed = 1,
340                                 .link_speed = 0,
341                                 .link_state = 0,
342                               });
343 }
344
345 vnet_dev_rv_t
346 iavf_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
347                                vnet_dev_port_cfg_change_req_t *req)
348 {
349   vnet_dev_rv_t rv = VNET_DEV_OK;
350
351   switch (req->type)
352     {
353     case VNET_DEV_PORT_CFG_MAX_FRAME_SIZE:
354       if (port->started)
355         rv = VNET_DEV_ERR_PORT_STARTED;
356       break;
357
358     case VNET_DEV_PORT_CFG_PROMISC_MODE:
359     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
360     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
361     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
362       break;
363
364     default:
365       rv = VNET_DEV_ERR_NOT_SUPPORTED;
366     };
367
368   return rv;
369 }
370
371 static vnet_dev_rv_t
372 iavf_port_add_del_eth_addr (vlib_main_t *vm, vnet_dev_port_t *port,
373                             vnet_dev_hw_addr_t *addr, int is_add,
374                             int is_primary)
375 {
376   iavf_port_t *ap = vnet_dev_get_port_data (port);
377   virtchnl_ether_addr_list_t al = {
378     .vsi_id = ap->vsi_id,
379     .num_elements = 1,
380     .list[0].primary = is_primary ? 1 : 0,
381     .list[0].extra = is_primary ? 0 : 1,
382   };
383
384   clib_memcpy (al.list[0].addr, addr, sizeof (al.list[0].addr));
385
386   return is_add ? iavf_vc_op_add_eth_addr (vm, port->dev, &al) :
387                         iavf_vc_op_del_eth_addr (vm, port->dev, &al);
388 }
389
390 vnet_dev_rv_t
391 iavf_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
392                       vnet_dev_port_cfg_change_req_t *req)
393 {
394   vnet_dev_t *dev = port->dev;
395   iavf_port_t *ap = vnet_dev_get_port_data (port);
396   vnet_dev_rv_t rv = VNET_DEV_OK;
397
398   switch (req->type)
399     {
400     case VNET_DEV_PORT_CFG_PROMISC_MODE:
401       {
402         virtchnl_promisc_info_t pi = {
403           .vsi_id = ap->vsi_id,
404           .unicast_promisc = req->promisc,
405           .multicast_promisc = req->promisc,
406         };
407
408         rv = iavf_vc_op_config_promisc_mode (vm, dev, &pi);
409       }
410       break;
411
412     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
413       rv = iavf_port_add_del_eth_addr (vm, port, &port->primary_hw_addr,
414                                        /* is_add */ 0,
415                                        /* is_primary */ 1);
416       if (rv == VNET_DEV_OK)
417         rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
418                                          /* is_add */ 1,
419                                          /* is_primary */ 1);
420       break;
421
422     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
423       rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
424                                        /* is_add */ 1,
425                                        /* is_primary */ 0);
426       break;
427
428     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
429       rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
430                                        /* is_add */ 0,
431                                        /* is_primary */ 0);
432       break;
433
434     case VNET_DEV_PORT_CFG_MAX_FRAME_SIZE:
435       break;
436
437     default:
438       return VNET_DEV_ERR_NOT_SUPPORTED;
439     };
440
441   return rv;
442 }