hs-test: more debug output in http3 test
[vpp.git] / src / plugins / dev_ena / aenq.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2023 Cisco Systems, Inc.
3  */
4
5 #include <vlib/vlib.h>
6 #include <vnet/dev/dev.h>
7
8 #include <dev_ena/ena.h>
9 #include <dev_ena/ena_inlines.h>
10
11 #define ENA_AENQ_POLL_INTERVAL 0.2
12
13 VLIB_REGISTER_LOG_CLASS (ena_log, static) = {
14   .class_name = "ena",
15   .subclass_name = "aenq",
16 };
17
18 void
19 ena_aenq_free (vlib_main_t *vm, vnet_dev_t *dev)
20 {
21   ena_device_t *ed = vnet_dev_get_data (dev);
22
23   log_debug (dev, "");
24
25   ASSERT (ed->aenq_started == 0);
26
27   vnet_dev_dma_mem_free (vm, dev, ed->aenq.entries);
28   ed->aenq.entries = 0;
29   ed->aenq.depth = 0;
30 }
31
32 vnet_dev_rv_t
33 ena_aenq_olloc (vlib_main_t *vm, vnet_dev_t *dev, u16 depth)
34 {
35   ena_device_t *ed = vnet_dev_get_data (dev);
36   u32 alloc_sz = sizeof (ena_aenq_entry_t) * depth;
37   vnet_dev_rv_t rv;
38
39   log_debug (dev, "");
40
41   ASSERT (ed->aenq.entries == 0);
42
43   if ((rv = vnet_dev_dma_mem_alloc (vm, dev, alloc_sz, 0,
44                                     (void **) &ed->aenq.entries)))
45     goto err;
46
47   ed->aenq.depth = depth;
48
49   return VNET_DEV_OK;
50 err:
51   ena_aenq_free (vm, dev);
52   return rv;
53 }
54
55 static ena_aenq_entry_t *
56 ena_get_next_aenq_entry (vnet_dev_t *dev)
57 {
58   ena_device_t *ed = vnet_dev_get_data (dev);
59   u16 index = ed->aenq.head & pow2_mask (ENA_ASYNC_QUEUE_LOG2_DEPTH);
60   u16 phase = 1 & (ed->aenq.head >> ENA_ASYNC_QUEUE_LOG2_DEPTH);
61   ena_aenq_entry_t *e = ed->aenq.entries + index;
62
63   if (e->phase != phase)
64     return 0;
65
66   ed->aenq.head++;
67
68   return e;
69 }
70
71 static void
72 ena_aenq_poll (vlib_main_t *vm, vnet_dev_t *dev)
73 {
74   ena_aenq_entry_t *ae;
75
76   while ((ae = ena_get_next_aenq_entry (dev)))
77     {
78       ena_device_t *ed = vnet_dev_get_data (dev);
79       vnet_dev_port_state_changes_t changes = {};
80
81       log_debug (dev, "aenq: group %u syndrome %u phase %u timestamp %lu",
82                  ae->group, ae->syndrome, ae->phase, ae->timestamp);
83
84       switch (ae->group)
85         {
86         case ENA_AENQ_GROUP_LINK_CHANGE:
87           log_debug (dev, "link_change: status %u",
88                      ae->link_change.link_status);
89           changes.link_state = 1;
90           changes.change.link_state = 1;
91           foreach_vnet_dev_port (p, dev)
92             vnet_dev_port_state_change (vm, p, changes);
93           break;
94
95         case ENA_AENQ_GROUP_NOTIFICATION:
96           log_warn (dev, "unhandled AENQ notification received [syndrome %u]",
97                     ae->syndrome);
98           break;
99
100         case ENA_AENQ_GROUP_KEEP_ALIVE:
101           if (ae->keep_alive.rx_drops || ae->keep_alive.tx_drops)
102             log_debug (dev, "keep_alive: rx_drops %lu tx_drops %lu",
103                        ae->keep_alive.rx_drops, ae->keep_alive.tx_drops);
104           ed->aenq.rx_drops = ae->keep_alive.rx_drops - ed->aenq.rx_drops0;
105           ed->aenq.tx_drops = ae->keep_alive.tx_drops - ed->aenq.tx_drops0;
106           ed->aenq.last_keepalive = vlib_time_now (vm);
107           break;
108
109         default:
110           log_debug (dev, "unknown aenq entry (group %u) %U", ae->group,
111                      format_hexdump, ae, sizeof (*ae));
112         };
113     }
114 }
115
116 vnet_dev_rv_t
117 ena_aenq_start (vlib_main_t *vm, vnet_dev_t *dev)
118 {
119   ena_device_t *ed = vnet_dev_get_data (dev);
120   u16 depth = ed->aenq.depth;
121   u32 alloc_sz = sizeof (ena_aenq_entry_t) * depth;
122
123   ASSERT (ed->aenq_started == 0);
124   ASSERT (ed->aq_started == 1);
125
126   ena_reg_aenq_caps_t aenq_caps = {
127     .depth = depth,
128     .entry_size = sizeof (ena_aenq_entry_t),
129   };
130
131   if (ena_aq_feature_is_supported (dev, ENA_ADMIN_FEAT_ID_AENQ_CONFIG))
132     {
133       ena_aq_feat_aenq_config_t aenq;
134       vnet_dev_rv_t rv;
135
136       if ((rv = ena_aq_get_feature (vm, dev, ENA_ADMIN_FEAT_ID_AENQ_CONFIG,
137                                     &aenq)))
138         {
139           log_err (dev, "aenq_start: get_Feature(AENQ_CONFIG) failed");
140           return rv;
141         }
142
143       aenq.enabled_groups.link_change = 1;
144       aenq.enabled_groups.fatal_error = 1;
145       aenq.enabled_groups.warning = 1;
146       aenq.enabled_groups.notification = 1;
147       aenq.enabled_groups.keep_alive = 1;
148       aenq.enabled_groups.as_u32 &= aenq.supported_groups.as_u32;
149       aenq.supported_groups.as_u32 = 0;
150
151       if ((rv = ena_aq_set_feature (vm, dev, ENA_ADMIN_FEAT_ID_AENQ_CONFIG,
152                                     &aenq)))
153         {
154           log_err (dev, "aenq_start: set_Feature(AENQ_CONFIG) failed");
155           return rv;
156         }
157     }
158
159   clib_memset (ed->aenq.entries, 0, alloc_sz);
160   ed->aenq.head = depth;
161
162   ena_reg_set_dma_addr (vm, dev, ENA_REG_AENQ_BASE_LO, ENA_REG_AENQ_BASE_HI,
163                         ed->aenq.entries);
164
165   ena_reg_write (dev, ENA_REG_AENQ_CAPS, &aenq_caps);
166   ena_reg_write (dev, ENA_REG_AENQ_HEAD_DB, &(u32){ depth });
167
168   ed->aenq_started = 1;
169
170   vnet_dev_poll_dev_add (vm, dev, ENA_AENQ_POLL_INTERVAL, ena_aenq_poll);
171
172   return VNET_DEV_OK;
173 }
174
175 void
176 ena_aenq_stop (vlib_main_t *vm, vnet_dev_t *dev)
177 {
178   ena_device_t *ed = vnet_dev_get_data (dev);
179   if (ed->aenq_started == 1)
180     {
181       ena_reg_aenq_caps_t aenq_caps = {};
182       vnet_dev_poll_dev_remove (vm, dev, ena_aenq_poll);
183       ena_reg_write (dev, ENA_REG_AENQ_CAPS, &aenq_caps);
184       ed->aenq_started = 0;
185     }
186 }