Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright (c) 2023 Advanced Micro Devices, Inc.
4 : : */
5 : :
6 : : #include "sfc.h"
7 : : #include "sfc_tbls.h"
8 : : #include "sfc_debug.h"
9 : :
10 : : #include <rte_ip.h>
11 : :
12 : : /* Number of bits in uint32_t type */
13 : : #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
14 : :
15 : : int
16 : 0 : sfc_tbls_attach(struct sfc_adapter *sa)
17 : : {
18 : : struct sfc_tbls *tables = &sa->hw_tables;
19 : : const struct sfc_mae *mae = &sa->mae;
20 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
21 : : int rc;
22 : :
23 : 0 : sfc_log_init(sa, "entry");
24 : :
25 [ # # ]: 0 : if (mae->status != SFC_MAE_STATUS_ADMIN ||
26 [ # # ]: 0 : !encp->enc_table_api_supported) {
27 : 0 : tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
28 : 0 : return 0;
29 : : }
30 : :
31 : 0 : tables->status = SFC_TBLS_STATUS_SUPPORTED;
32 : :
33 : 0 : rc = sfc_tbl_meta_init(sa);
34 [ # # ]: 0 : if (rc != 0)
35 : : return rc;
36 : :
37 : 0 : sfc_log_init(sa, "done");
38 : :
39 : 0 : return 0;
40 : : }
41 : :
42 : : void
43 : 0 : sfc_tbls_detach(struct sfc_adapter *sa)
44 : : {
45 : : struct sfc_tbls *tables = &sa->hw_tables;
46 : :
47 : 0 : sfc_log_init(sa, "entry");
48 : :
49 [ # # ]: 0 : if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
50 : 0 : goto done;
51 : :
52 : 0 : sfc_tbl_meta_fini(sa);
53 : :
54 : 0 : done:
55 : 0 : sfc_log_init(sa, "done");
56 : :
57 : 0 : tables->status = SFC_TBLS_STATUS_UNKNOWN;
58 : 0 : }
59 : :
60 : : int
61 : 0 : sfc_tbls_start(struct sfc_adapter *sa)
62 : : {
63 : : struct sfc_tbls *tables = &sa->hw_tables;
64 : : int rc;
65 : :
66 [ # # ]: 0 : if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
67 : 0 : rc = sfc_tbls_attach(sa);
68 : 0 : return rc;
69 : : }
70 : :
71 : : return 0;
72 : : }
73 : :
74 : : static uint32_t
75 : : sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
76 : : {
77 : : uint32_t mask;
78 : :
79 : : SFC_ASSERT(width <= SFC_TBLS_U32_BITS);
80 : :
81 : 0 : if (width == SFC_TBLS_U32_BITS)
82 : : return value;
83 : :
84 : 0 : mask = RTE_LEN2MASK(width, uint32_t);
85 : 0 : value &= mask;
86 : :
87 [ # # ]: 0 : if (lbn != 0) {
88 : 0 : mask <<= lbn;
89 : 0 : value <<= lbn;
90 : : }
91 : :
92 : 0 : return (in & (~mask)) | value;
93 : : }
94 : :
95 : : void
96 : 0 : sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
97 : : uint16_t lbn, uint16_t width, uint32_t value)
98 : : {
99 : : uint32_t data_offset = 0;
100 : :
101 [ # # ]: 0 : if (lbn >= SFC_TBLS_U32_BITS) {
102 : 0 : data_offset = lbn / SFC_TBLS_U32_BITS;
103 : :
104 : : SFC_ASSERT(data_offset < data_size);
105 : :
106 : 0 : data += data_offset;
107 : 0 : lbn %= SFC_TBLS_U32_BITS;
108 : : }
109 : :
110 [ # # ]: 0 : if (lbn + width <= SFC_TBLS_U32_BITS) {
111 [ # # ]: 0 : *data = sfc_tbls_field_update(*data, lbn, width, value);
112 : : } else {
113 : 0 : *data = sfc_tbls_field_update(*data, lbn,
114 [ # # ]: 0 : SFC_TBLS_U32_BITS - lbn, value);
115 : 0 : value >>= SFC_TBLS_U32_BITS - lbn;
116 : :
117 : : data_offset++;
118 : : SFC_ASSERT(data_offset < data_size);
119 : :
120 : : data++;
121 : 0 : *data = sfc_tbls_field_update(*data, 0,
122 [ # # ]: 0 : width + lbn - SFC_TBLS_U32_BITS,
123 : : value);
124 : : }
125 : 0 : }
126 : :
127 : : void
128 : 0 : sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
129 : : uint16_t width, uint16_t value)
130 : : {
131 : 0 : sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
132 : 0 : }
133 : :
134 : : void
135 : 0 : sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
136 : : uint16_t width, uint8_t value)
137 : : {
138 : 0 : sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
139 : 0 : }
140 : :
141 : : void
142 : 0 : sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
143 : : __rte_unused uint16_t width, const uint32_t *ip)
144 : : {
145 : : unsigned int i;
146 : : size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
147 : :
148 : : /*
149 : : * The same 128-bit container is used to store either
150 : : * an IPv4 or an IPv6 address, with an IPv4 address
151 : : * assumed to have 12 trailing zeroes.
152 : : */
153 : : SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
154 : :
155 [ # # ]: 0 : for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
156 : 0 : sfc_tbls_field_set_u32(data, data_size, lbn,
157 : 0 : SFC_TBLS_U32_BITS, ip[i]);
158 : 0 : lbn += SFC_TBLS_U32_BITS;
159 : : }
160 : 0 : }
161 : :
162 : : void
163 : 0 : sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
164 : : uint16_t lbn, uint16_t width, uint64_t value)
165 : : {
166 : : uint32_t data_offset = 0;
167 : :
168 [ # # ]: 0 : if (lbn >= SFC_TBLS_U32_BITS) {
169 : 0 : data_offset = lbn / SFC_TBLS_U32_BITS;
170 : :
171 : : SFC_ASSERT(data_offset < data_size);
172 : :
173 : 0 : data += data_offset;
174 : 0 : lbn %= SFC_TBLS_U32_BITS;
175 : : }
176 : :
177 [ # # ]: 0 : *data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
178 : 0 : value >>= SFC_TBLS_U32_BITS - lbn;
179 : 0 : width -= SFC_TBLS_U32_BITS - lbn;
180 : :
181 : : data_offset++;
182 : : SFC_ASSERT(data_offset < data_size);
183 : :
184 : 0 : data++;
185 : :
186 [ # # ]: 0 : if (width > SFC_TBLS_U32_BITS) {
187 : 0 : *data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
188 : 0 : value >>= SFC_TBLS_U32_BITS;
189 : 0 : width -= SFC_TBLS_U32_BITS;
190 : :
191 : : data_offset++;
192 : : SFC_ASSERT(data_offset < data_size);
193 : :
194 : 0 : data++;
195 : : }
196 : :
197 [ # # ]: 0 : *data = sfc_tbls_field_update(*data, 0, width, value);
198 : 0 : }
199 : :
200 : : void
201 : 0 : sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
202 : : uint16_t width, bool value)
203 : : {
204 : : SFC_ASSERT(width == 1);
205 : :
206 : 0 : sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
207 : 0 : }
|