xref: /dpdk/drivers/net/sfc/sfc_tbls.c (revision bc712f1c86fc9c2bb5bb41a80e12f34e224f4c6d)
19200192fSDenis Pryazhennikov /* SPDX-License-Identifier: BSD-3-Clause
29200192fSDenis Pryazhennikov  *
39200192fSDenis Pryazhennikov  * Copyright (c) 2023 Advanced Micro Devices, Inc.
49200192fSDenis Pryazhennikov  */
59200192fSDenis Pryazhennikov 
6*bc712f1cSDenis Pryazhennikov #include "sfc.h"
79200192fSDenis Pryazhennikov #include "sfc_tbls.h"
89200192fSDenis Pryazhennikov #include "sfc_debug.h"
99200192fSDenis Pryazhennikov 
109200192fSDenis Pryazhennikov #include <rte_ip.h>
119200192fSDenis Pryazhennikov 
129200192fSDenis Pryazhennikov /* Number of bits in uint32_t type */
139200192fSDenis Pryazhennikov #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
149200192fSDenis Pryazhennikov 
15*bc712f1cSDenis Pryazhennikov int
sfc_tbls_attach(struct sfc_adapter * sa)16*bc712f1cSDenis Pryazhennikov sfc_tbls_attach(struct sfc_adapter *sa)
17*bc712f1cSDenis Pryazhennikov {
18*bc712f1cSDenis Pryazhennikov 	struct sfc_tbls *tables = &sa->hw_tables;
19*bc712f1cSDenis Pryazhennikov 	const struct sfc_mae *mae = &sa->mae;
20*bc712f1cSDenis Pryazhennikov 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
21*bc712f1cSDenis Pryazhennikov 	int rc;
22*bc712f1cSDenis Pryazhennikov 
23*bc712f1cSDenis Pryazhennikov 	sfc_log_init(sa, "entry");
24*bc712f1cSDenis Pryazhennikov 
25*bc712f1cSDenis Pryazhennikov 	if (mae->status != SFC_MAE_STATUS_ADMIN ||
26*bc712f1cSDenis Pryazhennikov 	    !encp->enc_table_api_supported) {
27*bc712f1cSDenis Pryazhennikov 		tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
28*bc712f1cSDenis Pryazhennikov 		return 0;
29*bc712f1cSDenis Pryazhennikov 	}
30*bc712f1cSDenis Pryazhennikov 
31*bc712f1cSDenis Pryazhennikov 	tables->status = SFC_TBLS_STATUS_SUPPORTED;
32*bc712f1cSDenis Pryazhennikov 
33*bc712f1cSDenis Pryazhennikov 	rc = sfc_tbl_meta_init(sa);
34*bc712f1cSDenis Pryazhennikov 	if (rc != 0)
35*bc712f1cSDenis Pryazhennikov 		return rc;
36*bc712f1cSDenis Pryazhennikov 
37*bc712f1cSDenis Pryazhennikov 	sfc_log_init(sa, "done");
38*bc712f1cSDenis Pryazhennikov 
39*bc712f1cSDenis Pryazhennikov 	return 0;
40*bc712f1cSDenis Pryazhennikov }
41*bc712f1cSDenis Pryazhennikov 
42*bc712f1cSDenis Pryazhennikov void
sfc_tbls_detach(struct sfc_adapter * sa)43*bc712f1cSDenis Pryazhennikov sfc_tbls_detach(struct sfc_adapter *sa)
44*bc712f1cSDenis Pryazhennikov {
45*bc712f1cSDenis Pryazhennikov 	struct sfc_tbls *tables = &sa->hw_tables;
46*bc712f1cSDenis Pryazhennikov 
47*bc712f1cSDenis Pryazhennikov 	sfc_log_init(sa, "entry");
48*bc712f1cSDenis Pryazhennikov 
49*bc712f1cSDenis Pryazhennikov 	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
50*bc712f1cSDenis Pryazhennikov 		goto done;
51*bc712f1cSDenis Pryazhennikov 
52*bc712f1cSDenis Pryazhennikov 	sfc_tbl_meta_fini(sa);
53*bc712f1cSDenis Pryazhennikov 
54*bc712f1cSDenis Pryazhennikov done:
55*bc712f1cSDenis Pryazhennikov 	sfc_log_init(sa, "done");
56*bc712f1cSDenis Pryazhennikov 
57*bc712f1cSDenis Pryazhennikov 	tables->status = SFC_TBLS_STATUS_UNKNOWN;
58*bc712f1cSDenis Pryazhennikov }
59*bc712f1cSDenis Pryazhennikov 
60*bc712f1cSDenis Pryazhennikov int
sfc_tbls_start(struct sfc_adapter * sa)61*bc712f1cSDenis Pryazhennikov sfc_tbls_start(struct sfc_adapter *sa)
62*bc712f1cSDenis Pryazhennikov {
63*bc712f1cSDenis Pryazhennikov 	struct sfc_tbls *tables = &sa->hw_tables;
64*bc712f1cSDenis Pryazhennikov 	int rc;
65*bc712f1cSDenis Pryazhennikov 
66*bc712f1cSDenis Pryazhennikov 	if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
67*bc712f1cSDenis Pryazhennikov 		rc = sfc_tbls_attach(sa);
68*bc712f1cSDenis Pryazhennikov 		return rc;
69*bc712f1cSDenis Pryazhennikov 	}
70*bc712f1cSDenis Pryazhennikov 
71*bc712f1cSDenis Pryazhennikov 	return 0;
72*bc712f1cSDenis Pryazhennikov }
73*bc712f1cSDenis Pryazhennikov 
749200192fSDenis Pryazhennikov static uint32_t
sfc_tbls_field_update(uint32_t in,uint16_t lbn,uint16_t width,uint32_t value)759200192fSDenis Pryazhennikov sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
769200192fSDenis Pryazhennikov {
779200192fSDenis Pryazhennikov 	uint32_t mask;
789200192fSDenis Pryazhennikov 
799200192fSDenis Pryazhennikov 	SFC_ASSERT(width <= SFC_TBLS_U32_BITS);
809200192fSDenis Pryazhennikov 
819200192fSDenis Pryazhennikov 	if (width == SFC_TBLS_U32_BITS)
829200192fSDenis Pryazhennikov 		return value;
839200192fSDenis Pryazhennikov 
849200192fSDenis Pryazhennikov 	mask = RTE_LEN2MASK(width, uint32_t);
859200192fSDenis Pryazhennikov 	value &= mask;
869200192fSDenis Pryazhennikov 
879200192fSDenis Pryazhennikov 	if (lbn != 0) {
889200192fSDenis Pryazhennikov 		mask <<= lbn;
899200192fSDenis Pryazhennikov 		value <<= lbn;
909200192fSDenis Pryazhennikov 	}
919200192fSDenis Pryazhennikov 
929200192fSDenis Pryazhennikov 	return (in & (~mask)) | value;
939200192fSDenis Pryazhennikov }
949200192fSDenis Pryazhennikov 
959200192fSDenis Pryazhennikov void
sfc_tbls_field_set_u32(uint32_t data[],__rte_unused unsigned int data_size,uint16_t lbn,uint16_t width,uint32_t value)969200192fSDenis Pryazhennikov sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
979200192fSDenis Pryazhennikov 		       uint16_t lbn, uint16_t width, uint32_t value)
989200192fSDenis Pryazhennikov {
999200192fSDenis Pryazhennikov 	uint32_t data_offset = 0;
1009200192fSDenis Pryazhennikov 
1019200192fSDenis Pryazhennikov 	if (lbn >= SFC_TBLS_U32_BITS) {
1029200192fSDenis Pryazhennikov 		data_offset = lbn / SFC_TBLS_U32_BITS;
1039200192fSDenis Pryazhennikov 
1049200192fSDenis Pryazhennikov 		SFC_ASSERT(data_offset < data_size);
1059200192fSDenis Pryazhennikov 
1069200192fSDenis Pryazhennikov 		data += data_offset;
1079200192fSDenis Pryazhennikov 		lbn %= SFC_TBLS_U32_BITS;
1089200192fSDenis Pryazhennikov 	}
1099200192fSDenis Pryazhennikov 
1109200192fSDenis Pryazhennikov 	if (lbn + width <= SFC_TBLS_U32_BITS) {
1119200192fSDenis Pryazhennikov 		*data = sfc_tbls_field_update(*data, lbn, width, value);
1129200192fSDenis Pryazhennikov 	} else {
1139200192fSDenis Pryazhennikov 		*data = sfc_tbls_field_update(*data, lbn,
1149200192fSDenis Pryazhennikov 					      SFC_TBLS_U32_BITS - lbn, value);
1159200192fSDenis Pryazhennikov 		value >>= SFC_TBLS_U32_BITS - lbn;
1169200192fSDenis Pryazhennikov 
1179200192fSDenis Pryazhennikov 		data_offset++;
1189200192fSDenis Pryazhennikov 		SFC_ASSERT(data_offset < data_size);
1199200192fSDenis Pryazhennikov 
1209200192fSDenis Pryazhennikov 		data++;
1219200192fSDenis Pryazhennikov 		*data = sfc_tbls_field_update(*data, 0,
1229200192fSDenis Pryazhennikov 					      width + lbn - SFC_TBLS_U32_BITS,
1239200192fSDenis Pryazhennikov 					      value);
1249200192fSDenis Pryazhennikov 	}
1259200192fSDenis Pryazhennikov }
1269200192fSDenis Pryazhennikov 
1279200192fSDenis Pryazhennikov void
sfc_tbls_field_set_u16(uint32_t data[],unsigned int data_size,uint16_t lbn,uint16_t width,uint16_t value)1289200192fSDenis Pryazhennikov sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
1299200192fSDenis Pryazhennikov 		       uint16_t width, uint16_t value)
1309200192fSDenis Pryazhennikov {
1319200192fSDenis Pryazhennikov 	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
1329200192fSDenis Pryazhennikov }
1339200192fSDenis Pryazhennikov 
1349200192fSDenis Pryazhennikov void
sfc_tbls_field_set_u8(uint32_t data[],unsigned int data_size,uint16_t lbn,uint16_t width,uint8_t value)1359200192fSDenis Pryazhennikov sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
1369200192fSDenis Pryazhennikov 		      uint16_t width, uint8_t value)
1379200192fSDenis Pryazhennikov {
1389200192fSDenis Pryazhennikov 	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
1399200192fSDenis Pryazhennikov }
1409200192fSDenis Pryazhennikov 
1419200192fSDenis Pryazhennikov void
sfc_tbls_field_set_ip(uint32_t data[],unsigned int data_size,uint16_t lbn,__rte_unused uint16_t width,const uint32_t * ip)1429200192fSDenis Pryazhennikov sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
1439200192fSDenis Pryazhennikov 		      __rte_unused uint16_t width, const uint32_t *ip)
1449200192fSDenis Pryazhennikov {
1459200192fSDenis Pryazhennikov 	unsigned int i;
1469200192fSDenis Pryazhennikov 	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
1479200192fSDenis Pryazhennikov 
1489200192fSDenis Pryazhennikov 	/*
1499200192fSDenis Pryazhennikov 	 * The same 128-bit container is used to store either
1509200192fSDenis Pryazhennikov 	 * an IPv4 or an IPv6 address, with an IPv4 address
1519200192fSDenis Pryazhennikov 	 * assumed to have 12 trailing zeroes.
1529200192fSDenis Pryazhennikov 	 */
1539200192fSDenis Pryazhennikov 	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
1549200192fSDenis Pryazhennikov 
1559200192fSDenis Pryazhennikov 	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
1569200192fSDenis Pryazhennikov 		sfc_tbls_field_set_u32(data, data_size, lbn,
1579200192fSDenis Pryazhennikov 				       SFC_TBLS_U32_BITS, ip[i]);
1589200192fSDenis Pryazhennikov 		lbn += SFC_TBLS_U32_BITS;
1599200192fSDenis Pryazhennikov 	}
1609200192fSDenis Pryazhennikov }
1619200192fSDenis Pryazhennikov 
1629200192fSDenis Pryazhennikov void
sfc_tbls_field_set_u64(uint32_t data[],__rte_unused unsigned int data_size,uint16_t lbn,uint16_t width,uint64_t value)1639200192fSDenis Pryazhennikov sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
1649200192fSDenis Pryazhennikov 		       uint16_t lbn, uint16_t width, uint64_t value)
1659200192fSDenis Pryazhennikov {
1669200192fSDenis Pryazhennikov 	uint32_t data_offset = 0;
1679200192fSDenis Pryazhennikov 
1689200192fSDenis Pryazhennikov 	if (lbn >= SFC_TBLS_U32_BITS) {
1699200192fSDenis Pryazhennikov 		data_offset = lbn / SFC_TBLS_U32_BITS;
1709200192fSDenis Pryazhennikov 
1719200192fSDenis Pryazhennikov 		SFC_ASSERT(data_offset < data_size);
1729200192fSDenis Pryazhennikov 
1739200192fSDenis Pryazhennikov 		data += data_offset;
1749200192fSDenis Pryazhennikov 		lbn %= SFC_TBLS_U32_BITS;
1759200192fSDenis Pryazhennikov 	}
1769200192fSDenis Pryazhennikov 
1779200192fSDenis Pryazhennikov 	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
1789200192fSDenis Pryazhennikov 	value >>= SFC_TBLS_U32_BITS - lbn;
1799200192fSDenis Pryazhennikov 	width -= SFC_TBLS_U32_BITS - lbn;
1809200192fSDenis Pryazhennikov 
1819200192fSDenis Pryazhennikov 	data_offset++;
1829200192fSDenis Pryazhennikov 	SFC_ASSERT(data_offset < data_size);
1839200192fSDenis Pryazhennikov 
1849200192fSDenis Pryazhennikov 	data++;
1859200192fSDenis Pryazhennikov 
1869200192fSDenis Pryazhennikov 	if (width > SFC_TBLS_U32_BITS) {
1879200192fSDenis Pryazhennikov 		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
1889200192fSDenis Pryazhennikov 		value >>= SFC_TBLS_U32_BITS;
1899200192fSDenis Pryazhennikov 		width -= SFC_TBLS_U32_BITS;
1909200192fSDenis Pryazhennikov 
1919200192fSDenis Pryazhennikov 		data_offset++;
1929200192fSDenis Pryazhennikov 		SFC_ASSERT(data_offset < data_size);
1939200192fSDenis Pryazhennikov 
1949200192fSDenis Pryazhennikov 		data++;
1959200192fSDenis Pryazhennikov 	}
1969200192fSDenis Pryazhennikov 
1979200192fSDenis Pryazhennikov 	*data = sfc_tbls_field_update(*data, 0, width, value);
1989200192fSDenis Pryazhennikov }
1999200192fSDenis Pryazhennikov 
2009200192fSDenis Pryazhennikov void
sfc_tbls_field_set_bit(uint32_t data[],unsigned int data_size,uint16_t lbn,uint16_t width,bool value)2019200192fSDenis Pryazhennikov sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
2029200192fSDenis Pryazhennikov 		       uint16_t width, bool value)
2039200192fSDenis Pryazhennikov {
2049200192fSDenis Pryazhennikov 	SFC_ASSERT(width == 1);
2059200192fSDenis Pryazhennikov 
2069200192fSDenis Pryazhennikov 	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
2079200192fSDenis Pryazhennikov }
208