blob: 43a144901acf1b1eb27ace08db0262bb61225e37 [file] [log] [blame]
Manjunathappa Prakashf3b29442020-01-08 00:17:56 -08001/*
2 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "qdf_module.h"
18#include "dp_types.h"
19#include "hal_rx_flow.h"
20
21#if defined(WLAN_SUPPORT_RX_FISA)
22void hal_rx_dump_fse_table(struct hal_rx_fst *fst)
23{
24 int i = 0;
25 struct rx_flow_search_entry *fse =
26 (struct rx_flow_search_entry *)fst->base_vaddr;
27
28 dp_info("Number flow table entries %d", fst->add_flow_count);
29 for (i = 0; i < fst->max_entries; i++) {
30 if (fse[i].valid) {
31 dp_info("index %d:"
32 " src_ip_127_96 0x%x"
33 " src_ip_95_640 0x%x"
34 " src_ip_63_32 0x%x"
35 " src_ip_31_0 0x%x"
36 " dest_ip_127_96 0x%x"
37 " dest_ip_95_64 0x%x"
38 " dest_ip_63_32 0x%x"
39 " dest_ip_31_0 0x%x"
40 " src_port 0x%x"
41 " dest_port 0x%x"
42 " l4_protocol 0x%x"
43 " valid 0x%x"
44 " reo_destination_indication 0x%x"
45 " msdu_drop 0x%x"
46 " reo_destination_handler 0x%x"
47 " metadata 0x%x"
48 " aggregation_count0x%x"
49 " lro_eligible 0x%x"
50 " msdu_count 0x%x"
51 " msdu_byte_count 0x%x"
52 " timestamp 0x%x"
53 " cumulative_l4_checksum 0x%x"
54 " cumulative_ip_length 0x%x"
55 " tcp_sequence_number 0x%x",
56 i,
57 fse[i].src_ip_127_96,
58 fse[i].src_ip_95_64,
59 fse[i].src_ip_63_32,
60 fse[i].src_ip_31_0,
61 fse[i].dest_ip_127_96,
62 fse[i].dest_ip_95_64,
63 fse[i].dest_ip_63_32,
64 fse[i].dest_ip_31_0,
65 fse[i].src_port,
66 fse[i].dest_port,
67 fse[i].l4_protocol,
68 fse[i].valid,
69 fse[i].reo_destination_indication,
70 fse[i].msdu_drop,
71 fse[i].reo_destination_handler,
72 fse[i].metadata,
73 fse[i].aggregation_count,
74 fse[i].lro_eligible,
75 fse[i].msdu_count,
76 fse[i].msdu_byte_count,
77 fse[i].timestamp,
78 fse[i].cumulative_l4_checksum,
79 fse[i].cumulative_ip_length,
80 fse[i].tcp_sequence_number);
81 }
82 }
83}
84#else
85void hal_rx_dump_fse_table(struct hal_rx_fst *fst)
86{
87}
88#endif
89
90/**
91 * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST
92 * @fst: Pointer to the Rx Flow Search Table
93 * @table_offset: offset into the table where the flow is to be setup
94 * @flow: Flow Parameters
95 *
96 * Return: Success/Failure
97 */
98#ifdef WLAN_SUPPORT_RX_FLOW_TAG
99void *
100hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset,
101 struct hal_rx_flow *flow)
102{
103 uint8_t *fse;
104 bool fse_valid;
105
106 if (table_offset >= fst->max_entries) {
107 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
108 "HAL FSE table offset %u exceeds max entries %u",
109 table_offset, fst->max_entries);
110 return NULL;
111 }
112
113 fse = (uint8_t *)fst->base_vaddr +
114 (table_offset * HAL_RX_FST_ENTRY_SIZE);
115
116 fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID);
117
118 if (fse_valid) {
119 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
120 "HAL FSE %pK already valid", fse);
121 return NULL;
122 }
123
124 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) =
125 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96,
126 qdf_htonl(flow->tuple_info.src_ip_127_96));
127
128 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) =
129 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64,
130 qdf_htonl(flow->tuple_info.src_ip_95_64));
131
132 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) =
133 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32,
134 qdf_htonl(flow->tuple_info.src_ip_63_32));
135
136 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) =
137 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0,
138 qdf_htonl(flow->tuple_info.src_ip_31_0));
139
140 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) =
141 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96,
142 qdf_htonl(flow->tuple_info.dest_ip_127_96));
143
144 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) =
145 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64,
146 qdf_htonl(flow->tuple_info.dest_ip_95_64));
147
148 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) =
149 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32,
150 qdf_htonl(flow->tuple_info.dest_ip_63_32));
151
152 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) =
153 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0,
154 qdf_htonl(flow->tuple_info.dest_ip_31_0));
155
156 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT);
157 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |=
158 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT,
159 (flow->tuple_info.dest_port));
160
161 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT);
162 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |=
163 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT,
164 (flow->tuple_info.src_port));
165
166 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL);
167 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |=
168 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL,
169 flow->tuple_info.l4_protocol);
170
171 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER);
172 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |=
173 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER,
174 flow->reo_destination_handler);
175
176 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID);
177 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |=
178 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1);
179
180 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA);
181 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) =
182 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA,
183 flow->fse_metadata);
184
185 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION);
186 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION) |=
187 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_11,
188 REO_DESTINATION_INDICATION,
189 flow->reo_destination_indication);
190
191 /* Reset all the other fields in FSE */
192 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9);
193 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_DROP);
194 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, RESERVED_11);
195 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT);
196 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT);
197 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP);
198
199 return fse;
200}
201#elif defined(WLAN_SUPPORT_RX_FISA)
202/**
203 * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST
204 * @fst: Pointer to the Rx Flow Search Table
205 * @table_offset: offset into the table where the flow is to be setup
206 * @flow: Flow Parameters
207 *
208 * Flow table entry fields are updated in host byte order, little endian order.
209 *
210 * Return: Success/Failure
211 */
212void *
213hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset,
214 struct hal_rx_flow *flow)
215{
216 uint8_t *fse;
217 bool fse_valid;
218
219 if (table_offset >= fst->max_entries) {
220 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
221 "HAL FSE table offset %u exceeds max entries %u",
222 table_offset, fst->max_entries);
223 return NULL;
224 }
225
226 fse = (uint8_t *)fst->base_vaddr +
227 (table_offset * HAL_RX_FST_ENTRY_SIZE);
228
229 fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID);
230
231 if (fse_valid) {
232 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
233 "HAL FSE %pK already valid", fse);
234 return NULL;
235 }
236
237 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) =
238 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96,
239 (flow->tuple_info.src_ip_127_96));
240
241 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) =
242 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64,
243 (flow->tuple_info.src_ip_95_64));
244
245 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) =
246 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32,
247 (flow->tuple_info.src_ip_63_32));
248
249 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) =
250 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0,
251 (flow->tuple_info.src_ip_31_0));
252
253 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) =
254 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96,
255 (flow->tuple_info.dest_ip_127_96));
256
257 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) =
258 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64,
259 (flow->tuple_info.dest_ip_95_64));
260
261 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) =
262 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32,
263 (flow->tuple_info.dest_ip_63_32));
264
265 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) =
266 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0,
267 (flow->tuple_info.dest_ip_31_0));
268
269 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT);
270 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |=
271 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT,
272 (flow->tuple_info.dest_port));
273
274 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT);
275 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |=
276 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT,
277 (flow->tuple_info.src_port));
278
279 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL);
280 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |=
281 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL,
282 flow->tuple_info.l4_protocol);
283
284 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER);
285 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |=
286 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER,
287 flow->reo_destination_handler);
288
289 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID);
290 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |=
291 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1);
292
293 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA);
294 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) =
295 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA,
296 (flow->fse_metadata));
297
298 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION);
299 HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION) |=
300 HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9,
301 REO_DESTINATION_INDICATION,
302 flow->reo_destination_indication);
303
304 /* Reset all the other fields in FSE */
305 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9);
306 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, MSDU_DROP);
307 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT);
308 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT);
309 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP);
310
311 return fse;
312}
313#endif /* WLAN_SUPPORT_RX_FISA */
314qdf_export_symbol(hal_rx_flow_setup_fse);
315
316/**
317 * hal_rx_flow_delete_entry() - Delete a flow from the Rx Flow Search Table
318 * @fst: Pointer to the Rx Flow Search Table
319 * @hal_rx_fse: Pointer to the Rx Flow that is to be deleted from the FST
320 *
321 * Return: Success/Failure
322 */
323inline QDF_STATUS
324hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse)
325{
326 uint8_t *fse = (uint8_t *)hal_rx_fse;
327
328 if (!HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID))
329 return QDF_STATUS_E_NOENT;
330
331 HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID);
332
333 return QDF_STATUS_SUCCESS;
334}
335qdf_export_symbol(hal_rx_flow_delete_entry);
336
337/**
338 * hal_rx_fst_key_configure() - Configure the Toeplitz key in the FST
339 * @fst: Pointer to the Rx Flow Search Table
340 *
341 * Return: Success/Failure
342 */
343static void hal_rx_fst_key_configure(struct hal_rx_fst *fst)
344{
345 uint8_t key_bytes[HAL_FST_HASH_KEY_SIZE_BYTES];
346
347 qdf_mem_copy(key_bytes, fst->key, HAL_FST_HASH_KEY_SIZE_BYTES);
348
349 /**
350 * The Toeplitz algorithm as per the Microsoft spec works in a
351 * “big-endian” manner, using the MSBs of the key to hash the
352 * initial bytes of the input going on to use up the lower order bits
353 * of the key to hash further bytes of the input until the LSBs of the
354 * key are used finally.
355 *
356 * So first, rightshift 320-bit input key 5 times to get 315 MS bits
357 */
358 key_bitwise_shift_left(key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES, 5);
359 key_reverse(fst->shifted_key, key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES);
360}
361
362/**
363 * hal_rx_fst_get_base() - Retrieve the virtual base address of the Rx FST
364 * @fst: Pointer to the Rx Flow Search Table
365 *
366 * Return: Success/Failure
367 */
368static inline void *hal_rx_fst_get_base(struct hal_rx_fst *fst)
369{
370 return fst->base_vaddr;
371}
372
373/**
374 * hal_rx_fst_get_fse_size() - Retrieve the size of each entry(flow) in Rx FST
375 *
376 * Return: size of each entry/flow in Rx FST
377 */
378static inline uint32_t hal_rx_fst_get_fse_size(void)
379{
380 return HAL_RX_FST_ENTRY_SIZE;
381}
382
383/**
384 * hal_rx_flow_get_tuple_info() - Retrieve the 5-tuple flow info for an entry
385 * @hal_fse: Pointer to the Flow in Rx FST
386 * @tuple_info: 5-tuple info of the flow returned to the caller
387 *
388 * Return: Success/Failure
389 */
390QDF_STATUS hal_rx_flow_get_tuple_info(void *hal_fse,
391 struct hal_flow_tuple_info *tuple_info)
392{
393 if (!hal_fse || !tuple_info)
394 return QDF_STATUS_E_INVAL;
395
396 if (!HAL_GET_FLD(hal_fse, RX_FLOW_SEARCH_ENTRY_9, VALID))
397 return QDF_STATUS_E_NOENT;
398
399 tuple_info->src_ip_127_96 =
400 qdf_ntohl(HAL_GET_FLD(hal_fse,
401 RX_FLOW_SEARCH_ENTRY_0,
402 SRC_IP_127_96));
403 tuple_info->src_ip_95_64 =
404 qdf_ntohl(HAL_GET_FLD(hal_fse,
405 RX_FLOW_SEARCH_ENTRY_1,
406 SRC_IP_95_64));
407 tuple_info->src_ip_63_32 =
408 qdf_ntohl(HAL_GET_FLD(hal_fse,
409 RX_FLOW_SEARCH_ENTRY_2,
410 SRC_IP_63_32));
411 tuple_info->src_ip_31_0 =
412 qdf_ntohl(HAL_GET_FLD(hal_fse,
413 RX_FLOW_SEARCH_ENTRY_3,
414 SRC_IP_31_0));
415 tuple_info->dest_ip_127_96 =
416 qdf_ntohl(HAL_GET_FLD(hal_fse,
417 RX_FLOW_SEARCH_ENTRY_4,
418 DEST_IP_127_96));
419 tuple_info->dest_ip_95_64 =
420 qdf_ntohl(HAL_GET_FLD(hal_fse,
421 RX_FLOW_SEARCH_ENTRY_5,
422 DEST_IP_95_64));
423 tuple_info->dest_ip_63_32 =
424 qdf_ntohl(HAL_GET_FLD(hal_fse,
425 RX_FLOW_SEARCH_ENTRY_6,
426 DEST_IP_63_32));
427 tuple_info->dest_ip_31_0 =
428 qdf_ntohl(HAL_GET_FLD(hal_fse,
429 RX_FLOW_SEARCH_ENTRY_7,
430 DEST_IP_31_0));
431 tuple_info->dest_port = HAL_GET_FLD(hal_fse,
432 RX_FLOW_SEARCH_ENTRY_8,
433 DEST_PORT);
434 tuple_info->src_port = HAL_GET_FLD(hal_fse,
435 RX_FLOW_SEARCH_ENTRY_8,
436 SRC_PORT);
437 tuple_info->l4_protocol = HAL_GET_FLD(hal_fse,
438 RX_FLOW_SEARCH_ENTRY_9,
439 L4_PROTOCOL);
440
441 return QDF_STATUS_SUCCESS;
442}
443
444/**
445 * hal_flow_toeplitz_create_cache() - Calculate hashes for each possible
446 * byte value with the key taken as is
447 *
448 * @fst: FST Handle
449 * @key: Hash Key
450 *
451 * Return: Success/Failure
452 */
453static void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst)
454{
455 int bit;
456 int val;
457 int i;
458 uint8_t *key = fst->shifted_key;
459
460 /*
461 * Initialise to first 32 bits of the key; shift in further key material
462 * through the loop
463 */
464 uint32_t cur_key = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) |
465 key[3];
466
467 for (i = 0; i < HAL_FST_HASH_KEY_SIZE_BYTES; i++) {
468 uint8_t new_key_byte;
469 uint32_t shifted_key[8];
470
471 if (i + 4 < HAL_FST_HASH_KEY_SIZE_BYTES)
472 new_key_byte = key[i + 4];
473 else
474 new_key_byte = 0;
475
476 shifted_key[0] = cur_key;
477
478 for (bit = 1; bit < 8; bit++) {
479 /*
480 * For each iteration, shift out one more bit of the
481 * current key and shift in one more bit of the new key
482 * material
483 */
484 shifted_key[bit] = cur_key << bit |
485 new_key_byte >> (8 - bit);
486 }
487
488 for (val = 0; val < (1 << 8); val++) {
489 uint32_t hash = 0;
490 int mask;
491
492 /*
493 * For each bit set in the input, XOR in
494 * the appropriately shifted key
495 */
496 for (bit = 0, mask = 1 << 7; bit < 8; bit++, mask >>= 1)
497 if ((val & mask))
498 hash ^= shifted_key[bit];
499
500 fst->key_cache[i][val] = hash;
501 }
502
503 cur_key = cur_key << 8 | new_key_byte;
504 }
505}
506
507/**
508 * hal_rx_fst_attach() - Initialize Rx flow search table in HW FST
509 *
510 * @qdf_dev: QDF device handle
511 * @hal_fst_base_paddr: Pointer to the physical base address of the Rx FST
512 * @max_entries: Max number of flows allowed in the FST
513 * @max_search: Number of collisions allowed in the hash-based FST
514 * @hash_key: Toeplitz key used for the hash FST
515 *
516 * Return:
517 */
518struct hal_rx_fst *
519hal_rx_fst_attach(qdf_device_t qdf_dev,
520 uint64_t *hal_fst_base_paddr, uint16_t max_entries,
521 uint16_t max_search, uint8_t *hash_key)
522{
523 struct hal_rx_fst *fst = qdf_mem_malloc(sizeof(struct hal_rx_fst));
524
525 if (!fst) {
526 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
527 FL("hal fst allocation failed,"));
528 return NULL;
529 }
530
531 qdf_mem_set(fst, 0, sizeof(struct hal_rx_fst));
532
533 fst->key = hash_key;
534 fst->max_skid_length = max_search;
535 fst->max_entries = max_entries;
536 fst->hash_mask = max_entries - 1;
537
538 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
539 "HAL FST allocation %x %d * %d\n", fst,
540 fst->max_entries, HAL_RX_FST_ENTRY_SIZE);
541
542 fst->base_vaddr = (uint8_t *)qdf_mem_alloc_consistent(qdf_dev,
543 qdf_dev->dev,
544 (fst->max_entries * HAL_RX_FST_ENTRY_SIZE),
545 &fst->base_paddr);
546
547 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
548 "hal_rx_fst base address 0x%x", fst->base_paddr);
549 if (!fst->base_vaddr) {
550 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
551 FL("hal fst->base_vaddr allocation failed"));
552 qdf_mem_free(fst);
553 return NULL;
554 }
555 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG,
556 (void *)fst->key, HAL_FST_HASH_KEY_SIZE_BYTES);
557
558 qdf_mem_set((uint8_t *)fst->base_vaddr, 0,
559 (fst->max_entries * HAL_RX_FST_ENTRY_SIZE));
560
561 hal_rx_fst_key_configure(fst);
562 hal_flow_toeplitz_create_cache(fst);
563 *hal_fst_base_paddr = (uint64_t)fst->base_paddr;
564 return fst;
565}
566qdf_export_symbol(hal_rx_fst_attach);
567
568/**
569 * hal_rx_fst_detach() - De-init the Rx flow search table from HW
570 *
571 * @rx_fst: Pointer to the Rx FST
572 * @qdf_dev: QDF device handle
573 *
574 * Return:
575 */
576void hal_rx_fst_detach(struct hal_rx_fst *rx_fst,
577 qdf_device_t qdf_dev)
578{
579 if (!rx_fst || !qdf_dev)
580 return;
581
582 qdf_mem_free_consistent(qdf_dev, qdf_dev->dev,
583 rx_fst->max_entries * HAL_RX_FST_ENTRY_SIZE,
584 rx_fst->base_vaddr, rx_fst->base_paddr, 0);
585
586 qdf_mem_free(rx_fst);
587}
588qdf_export_symbol(hal_rx_fst_detach);
589
590/**
591 * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key
592 *
593 * @hal_fst: FST Handle
594 * @flow: Flow Parameters
595 *
596 * Return: Success/Failure
597 */
598uint32_t
599hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow)
600{
601 int i, j;
602 uint32_t hash = 0;
603 struct hal_rx_fst *fst = (struct hal_rx_fst *)hal_fst;
604 uint32_t input[HAL_FST_HASH_KEY_SIZE_WORDS];
605 uint8_t *tuple;
606
607 qdf_mem_zero(input, HAL_FST_HASH_KEY_SIZE_BYTES);
608 *(uint32_t *)&input[0] = qdf_htonl(flow->tuple_info.src_ip_127_96);
609 *(uint32_t *)&input[1] = qdf_htonl(flow->tuple_info.src_ip_95_64);
610 *(uint32_t *)&input[2] = qdf_htonl(flow->tuple_info.src_ip_63_32);
611 *(uint32_t *)&input[3] = qdf_htonl(flow->tuple_info.src_ip_31_0);
612 *(uint32_t *)&input[4] = qdf_htonl(flow->tuple_info.dest_ip_127_96);
613 *(uint32_t *)&input[5] = qdf_htonl(flow->tuple_info.dest_ip_95_64);
614 *(uint32_t *)&input[6] = qdf_htonl(flow->tuple_info.dest_ip_63_32);
615 *(uint32_t *)&input[7] = qdf_htonl(flow->tuple_info.dest_ip_31_0);
616 *(uint32_t *)&input[8] = (flow->tuple_info.dest_port << 16) |
617 (flow->tuple_info.src_port);
618 *(uint32_t *)&input[9] = flow->tuple_info.l4_protocol;
619
620 tuple = (uint8_t *)input;
621 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
622 tuple, sizeof(input));
623 for (i = 0, j = HAL_FST_HASH_DATA_SIZE - 1;
624 i < HAL_FST_HASH_KEY_SIZE_BYTES && j >= 0; i++, j--) {
625 hash ^= fst->key_cache[i][tuple[j]];
626 }
627
628 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
629 "Hash value %u %u truncated hash %u\n", hash,
630 (hash >> 12), (hash >> 12) % (fst->max_entries));
631
632 hash >>= 12;
633 hash &= (fst->max_entries - 1);
634
635 return hash;
636}
637qdf_export_symbol(hal_flow_toeplitz_hash);
638
639/**
640 * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table
641 *
642 * @hal_fst: HAL Rx FST Handle
643 * @flow_hash: Flow hash computed from flow tuple
644 *
645 * Return: hash index truncated to the size of the hash table
646 */
647uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash)
648{
649 uint32_t trunc_hash = flow_hash;
650
651 /* Take care of hash wrap around scenario */
652 if (flow_hash >= hal_fst->max_entries)
653 trunc_hash &= hal_fst->hash_mask;
654 return trunc_hash;
655}
656qdf_export_symbol(hal_rx_get_hal_hash);
657
658/**
659 * hal_rx_insert_flow_entry() - Add a flow into the FST table
660 *
661 * @hal_fst: HAL Rx FST Handle
662 * @flow_hash: Flow hash computed from flow tuple
663 * @flow_tuple_info: Flow tuple used to compute the hash
664 * @flow_index: Hash index of the flow in the table when inserted successfully
665 *
666 * Return: Success if flow is inserted into the table, error otherwise
667 */
668QDF_STATUS
669hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash,
670 void *flow_tuple_info, uint32_t *flow_idx)
671{
672 int i;
673 void *hal_fse;
674 uint32_t hal_hash;
675 struct hal_flow_tuple_info hal_tuple_info = { 0 };
676 QDF_STATUS status;
677
678 for (i = 0; i < fst->max_skid_length; i++) {
679 hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i));
680 hal_fse = (uint8_t *)fst->base_vaddr +
681 (hal_hash * HAL_RX_FST_ENTRY_SIZE);
682 status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info);
683 if (status == QDF_STATUS_E_NOENT)
684 break;
685
686 /* Find the matching flow entry in HW FST */
687 if (!qdf_mem_cmp(&hal_tuple_info,
688 flow_tuple_info,
689 sizeof(struct hal_flow_tuple_info))) {
690 dp_err("Duplicate flow entry in FST %u at skid %u ",
691 hal_hash, i);
692 return QDF_STATUS_E_EXISTS;
693 }
694 }
695 if (i == fst->max_skid_length) {
696 dp_err("Max skid length reached for hash %u", flow_hash);
697 return QDF_STATUS_E_RANGE;
698 }
699 *flow_idx = hal_hash;
700 dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d",
701 flow_hash, i, hal_fse, *flow_idx);
702
703 return QDF_STATUS_SUCCESS;
704}
705qdf_export_symbol(hal_rx_insert_flow_entry);
706
707/**
708 * hal_rx_find_flow_from_tuple() - Find a flow in the FST table
709 *
710 * @fst: HAL Rx FST Handle
711 * @flow_hash: Flow hash computed from flow tuple
712 * @flow_tuple_info: Flow tuple used to compute the hash
713 * @flow_index: Hash index of the flow in the table when found
714 *
715 * Return: Success if matching flow is found in the table, error otherwise
716 */
717QDF_STATUS
718hal_rx_find_flow_from_tuple(struct hal_rx_fst *fst, uint32_t flow_hash,
719 void *flow_tuple_info, uint32_t *flow_idx)
720{
721 int i;
722 void *hal_fse;
723 uint32_t hal_hash;
724 struct hal_flow_tuple_info hal_tuple_info = { 0 };
725 QDF_STATUS status;
726
727 for (i = 0; i < fst->max_skid_length; i++) {
728 hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i));
729 hal_fse = (uint8_t *)fst->base_vaddr +
730 (hal_hash * HAL_RX_FST_ENTRY_SIZE);
731 status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info);
732 if (status != QDF_STATUS_SUCCESS)
733 continue;
734
735 /* Find the matching flow entry in HW FST */
736 if (!qdf_mem_cmp(&hal_tuple_info,
737 flow_tuple_info,
738 sizeof(struct hal_flow_tuple_info))) {
739 break;
740 }
741 }
742
743 if (i == fst->max_skid_length) {
744 dp_err("Max skid length reached for hash %u", flow_hash);
745 return QDF_STATUS_E_RANGE;
746 }
747
748 *flow_idx = hal_hash;
749 dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d",
750 flow_hash, i, hal_fse, *flow_idx);
751
752 return QDF_STATUS_SUCCESS;
753}
754qdf_export_symbol(hal_rx_find_flow_from_tuple);