xref: /dpdk/drivers/net/cxgbe/clip_tbl.c (revision e12a0166c80f65e35408f4715b2f3a60763c3741)
13f2c1e20SShagun Agrawal /* SPDX-License-Identifier: BSD-3-Clause
23f2c1e20SShagun Agrawal  * Copyright(c) 2018 Chelsio Communications.
33f2c1e20SShagun Agrawal  * All rights reserved.
43f2c1e20SShagun Agrawal  */
53f2c1e20SShagun Agrawal 
689c8bd95SRahul Lakkireddy #include "base/common.h"
73f2c1e20SShagun Agrawal #include "clip_tbl.h"
83f2c1e20SShagun Agrawal 
93f2c1e20SShagun Agrawal /**
103f2c1e20SShagun Agrawal  * Allocate clip entry in HW with associated IPV4/IPv6 address
113f2c1e20SShagun Agrawal  */
clip6_get_mbox(const struct rte_eth_dev * dev,const u32 * lip)123f2c1e20SShagun Agrawal static int clip6_get_mbox(const struct rte_eth_dev *dev, const u32 *lip)
133f2c1e20SShagun Agrawal {
143f2c1e20SShagun Agrawal 	struct adapter *adap = ethdev2adap(dev);
153f2c1e20SShagun Agrawal 	struct fw_clip_cmd c;
163f2c1e20SShagun Agrawal 	u64 hi = ((u64)lip[1]) << 32 | lip[0];
173f2c1e20SShagun Agrawal 	u64 lo = ((u64)lip[3]) << 32 | lip[2];
183f2c1e20SShagun Agrawal 
193f2c1e20SShagun Agrawal 	memset(&c, 0, sizeof(c));
203f2c1e20SShagun Agrawal 	c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
213f2c1e20SShagun Agrawal 				    F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
223f2c1e20SShagun Agrawal 	c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
233f2c1e20SShagun Agrawal 	c.ip_hi = hi;
243f2c1e20SShagun Agrawal 	c.ip_lo = lo;
253f2c1e20SShagun Agrawal 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
263f2c1e20SShagun Agrawal }
273f2c1e20SShagun Agrawal 
283f2c1e20SShagun Agrawal /**
293f2c1e20SShagun Agrawal  * Delete clip entry in HW having the associated IPV4/IPV6 address
303f2c1e20SShagun Agrawal  */
clip6_release_mbox(const struct rte_eth_dev * dev,const u32 * lip)313f2c1e20SShagun Agrawal static int clip6_release_mbox(const struct rte_eth_dev *dev, const u32 *lip)
323f2c1e20SShagun Agrawal {
333f2c1e20SShagun Agrawal 	struct adapter *adap = ethdev2adap(dev);
343f2c1e20SShagun Agrawal 	struct fw_clip_cmd c;
353f2c1e20SShagun Agrawal 	u64 hi = ((u64)lip[1]) << 32 | lip[0];
363f2c1e20SShagun Agrawal 	u64 lo = ((u64)lip[3]) << 32 | lip[2];
373f2c1e20SShagun Agrawal 
383f2c1e20SShagun Agrawal 	memset(&c, 0, sizeof(c));
393f2c1e20SShagun Agrawal 	c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
403f2c1e20SShagun Agrawal 				    F_FW_CMD_REQUEST | F_FW_CMD_READ);
413f2c1e20SShagun Agrawal 	c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
423f2c1e20SShagun Agrawal 	c.ip_hi = hi;
433f2c1e20SShagun Agrawal 	c.ip_lo = lo;
443f2c1e20SShagun Agrawal 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
453f2c1e20SShagun Agrawal }
463f2c1e20SShagun Agrawal 
473f2c1e20SShagun Agrawal /**
483f2c1e20SShagun Agrawal  * cxgbe_clip_release - Release associated CLIP entry
493f2c1e20SShagun Agrawal  * @ce: clip entry to release
503f2c1e20SShagun Agrawal  *
513f2c1e20SShagun Agrawal  * Releases ref count and frees up a clip entry from CLIP table
523f2c1e20SShagun Agrawal  */
cxgbe_clip_release(struct rte_eth_dev * dev,struct clip_entry * ce)533f2c1e20SShagun Agrawal void cxgbe_clip_release(struct rte_eth_dev *dev, struct clip_entry *ce)
543f2c1e20SShagun Agrawal {
553f2c1e20SShagun Agrawal 	int ret;
563f2c1e20SShagun Agrawal 
573f2c1e20SShagun Agrawal 	t4_os_lock(&ce->lock);
58*e12a0166STyler Retzlaff 	if (rte_atomic_fetch_sub_explicit(&ce->refcnt, 1, rte_memory_order_relaxed) - 1 == 0) {
593f2c1e20SShagun Agrawal 		ret = clip6_release_mbox(dev, ce->addr);
603f2c1e20SShagun Agrawal 		if (ret)
613f2c1e20SShagun Agrawal 			dev_debug(adap, "CLIP FW DEL CMD failed: %d", ret);
623f2c1e20SShagun Agrawal 	}
633f2c1e20SShagun Agrawal 	t4_os_unlock(&ce->lock);
643f2c1e20SShagun Agrawal }
653f2c1e20SShagun Agrawal 
663f2c1e20SShagun Agrawal /**
673f2c1e20SShagun Agrawal  * find_or_alloc_clipe - Find/Allocate a free CLIP entry
683f2c1e20SShagun Agrawal  * @c: CLIP table
693f2c1e20SShagun Agrawal  * @lip: IPV4/IPV6 address to compare/add
703f2c1e20SShagun Agrawal  * Returns pointer to the IPV4/IPV6 entry found/created
713f2c1e20SShagun Agrawal  *
723f2c1e20SShagun Agrawal  * Finds/Allocates an CLIP entry to be used for a filter rule.
733f2c1e20SShagun Agrawal  */
find_or_alloc_clipe(struct clip_tbl * c,const u32 * lip)743f2c1e20SShagun Agrawal static struct clip_entry *find_or_alloc_clipe(struct clip_tbl *c,
753f2c1e20SShagun Agrawal 					      const u32 *lip)
763f2c1e20SShagun Agrawal {
773f2c1e20SShagun Agrawal 	struct clip_entry *end, *e;
783f2c1e20SShagun Agrawal 	struct clip_entry *first_free = NULL;
793f2c1e20SShagun Agrawal 	unsigned int clipt_size = c->clipt_size;
803f2c1e20SShagun Agrawal 
813f2c1e20SShagun Agrawal 	for (e = &c->cl_list[0], end = &c->cl_list[clipt_size]; e != end; ++e) {
82*e12a0166STyler Retzlaff 		if (rte_atomic_load_explicit(&e->refcnt, rte_memory_order_relaxed) == 0) {
833f2c1e20SShagun Agrawal 			if (!first_free)
843f2c1e20SShagun Agrawal 				first_free = e;
853f2c1e20SShagun Agrawal 		} else {
863f2c1e20SShagun Agrawal 			if (memcmp(lip, e->addr, sizeof(e->addr)) == 0)
873f2c1e20SShagun Agrawal 				goto exists;
883f2c1e20SShagun Agrawal 		}
893f2c1e20SShagun Agrawal 	}
903f2c1e20SShagun Agrawal 
913f2c1e20SShagun Agrawal 	if (first_free) {
923f2c1e20SShagun Agrawal 		e = first_free;
933f2c1e20SShagun Agrawal 		goto exists;
943f2c1e20SShagun Agrawal 	}
953f2c1e20SShagun Agrawal 
963f2c1e20SShagun Agrawal 	return NULL;
973f2c1e20SShagun Agrawal 
983f2c1e20SShagun Agrawal exists:
993f2c1e20SShagun Agrawal 	return e;
1003f2c1e20SShagun Agrawal }
1013f2c1e20SShagun Agrawal 
t4_clip_alloc(struct rte_eth_dev * dev,u32 * lip,u8 v6)1023f2c1e20SShagun Agrawal static struct clip_entry *t4_clip_alloc(struct rte_eth_dev *dev,
1033f2c1e20SShagun Agrawal 					u32 *lip, u8 v6)
1043f2c1e20SShagun Agrawal {
1053f2c1e20SShagun Agrawal 	struct adapter *adap = ethdev2adap(dev);
1063f2c1e20SShagun Agrawal 	struct clip_tbl *ctbl = adap->clipt;
1073f2c1e20SShagun Agrawal 	struct clip_entry *ce;
108217d1816SShagun Agrawal 	int ret = 0;
1093f2c1e20SShagun Agrawal 
1103f2c1e20SShagun Agrawal 	if (!ctbl)
1113f2c1e20SShagun Agrawal 		return NULL;
1123f2c1e20SShagun Agrawal 
1133f2c1e20SShagun Agrawal 	t4_os_write_lock(&ctbl->lock);
1143f2c1e20SShagun Agrawal 	ce = find_or_alloc_clipe(ctbl, lip);
1153f2c1e20SShagun Agrawal 	if (ce) {
1163f2c1e20SShagun Agrawal 		t4_os_lock(&ce->lock);
117*e12a0166STyler Retzlaff 		if (rte_atomic_load_explicit(&ce->refcnt, rte_memory_order_relaxed) == 0) {
1183f2c1e20SShagun Agrawal 			rte_memcpy(ce->addr, lip, sizeof(ce->addr));
1193f2c1e20SShagun Agrawal 			if (v6) {
1203f2c1e20SShagun Agrawal 				ce->type = FILTER_TYPE_IPV6;
121*e12a0166STyler Retzlaff 				rte_atomic_store_explicit(&ce->refcnt, 1,
122*e12a0166STyler Retzlaff 						 rte_memory_order_relaxed);
1233f2c1e20SShagun Agrawal 				ret = clip6_get_mbox(dev, lip);
124217d1816SShagun Agrawal 				if (ret)
1253f2c1e20SShagun Agrawal 					dev_debug(adap,
1263f2c1e20SShagun Agrawal 						  "CLIP FW ADD CMD failed: %d",
1273f2c1e20SShagun Agrawal 						  ret);
1283f2c1e20SShagun Agrawal 			} else {
1293f2c1e20SShagun Agrawal 				ce->type = FILTER_TYPE_IPV4;
1303f2c1e20SShagun Agrawal 			}
1313f2c1e20SShagun Agrawal 		} else {
132*e12a0166STyler Retzlaff 			rte_atomic_fetch_add_explicit(&ce->refcnt, 1, rte_memory_order_relaxed);
1333f2c1e20SShagun Agrawal 		}
1343f2c1e20SShagun Agrawal 		t4_os_unlock(&ce->lock);
1353f2c1e20SShagun Agrawal 	}
1363f2c1e20SShagun Agrawal 	t4_os_write_unlock(&ctbl->lock);
1373f2c1e20SShagun Agrawal 
138217d1816SShagun Agrawal 	return ret ? NULL : ce;
1393f2c1e20SShagun Agrawal }
1403f2c1e20SShagun Agrawal 
1413f2c1e20SShagun Agrawal /**
1423f2c1e20SShagun Agrawal  * cxgbe_clip_alloc - Allocate a IPV6 CLIP entry
1433f2c1e20SShagun Agrawal  * @dev: rte_eth_dev pointer
1443f2c1e20SShagun Agrawal  * @lip: IPV6 address to add
1453f2c1e20SShagun Agrawal  * Returns pointer to the CLIP entry created
1463f2c1e20SShagun Agrawal  *
1473f2c1e20SShagun Agrawal  * Allocates a IPV6 CLIP entry to be used for a filter rule.
1483f2c1e20SShagun Agrawal  */
cxgbe_clip_alloc(struct rte_eth_dev * dev,u32 * lip)1493f2c1e20SShagun Agrawal struct clip_entry *cxgbe_clip_alloc(struct rte_eth_dev *dev, u32 *lip)
1503f2c1e20SShagun Agrawal {
1513f2c1e20SShagun Agrawal 	return t4_clip_alloc(dev, lip, FILTER_TYPE_IPV6);
1523f2c1e20SShagun Agrawal }
1533f2c1e20SShagun Agrawal 
1543f2c1e20SShagun Agrawal /**
1553f2c1e20SShagun Agrawal  * Initialize CLIP Table
1563f2c1e20SShagun Agrawal  */
t4_init_clip_tbl(unsigned int clipt_start,unsigned int clipt_end)1573f2c1e20SShagun Agrawal struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
1583f2c1e20SShagun Agrawal 				  unsigned int clipt_end)
1593f2c1e20SShagun Agrawal {
1603f2c1e20SShagun Agrawal 	unsigned int clipt_size;
1613f2c1e20SShagun Agrawal 	struct clip_tbl *ctbl;
1623f2c1e20SShagun Agrawal 	unsigned int i;
1633f2c1e20SShagun Agrawal 
1643f2c1e20SShagun Agrawal 	if (clipt_start >= clipt_end)
1653f2c1e20SShagun Agrawal 		return NULL;
1663f2c1e20SShagun Agrawal 
1673f2c1e20SShagun Agrawal 	clipt_size = clipt_end - clipt_start + 1;
1683f2c1e20SShagun Agrawal 
1693f2c1e20SShagun Agrawal 	ctbl = t4_os_alloc(sizeof(*ctbl) +
1703f2c1e20SShagun Agrawal 			   clipt_size * sizeof(struct clip_entry));
1713f2c1e20SShagun Agrawal 	if (!ctbl)
1723f2c1e20SShagun Agrawal 		return NULL;
1733f2c1e20SShagun Agrawal 
1743f2c1e20SShagun Agrawal 	ctbl->clipt_start = clipt_start;
1753f2c1e20SShagun Agrawal 	ctbl->clipt_size = clipt_size;
1763f2c1e20SShagun Agrawal 
1773f2c1e20SShagun Agrawal 	t4_os_rwlock_init(&ctbl->lock);
1783f2c1e20SShagun Agrawal 
1793f2c1e20SShagun Agrawal 	for (i = 0; i < ctbl->clipt_size; i++) {
1803f2c1e20SShagun Agrawal 		t4_os_lock_init(&ctbl->cl_list[i].lock);
181a12f14bcSRahul Lakkireddy 		ctbl->cl_list[i].refcnt = 0;
1823f2c1e20SShagun Agrawal 	}
1833f2c1e20SShagun Agrawal 
1843f2c1e20SShagun Agrawal 	return ctbl;
1853f2c1e20SShagun Agrawal }
1863f2c1e20SShagun Agrawal 
1873f2c1e20SShagun Agrawal /**
1883f2c1e20SShagun Agrawal  * Cleanup CLIP Table
1893f2c1e20SShagun Agrawal  */
t4_cleanup_clip_tbl(struct adapter * adap)1903f2c1e20SShagun Agrawal void t4_cleanup_clip_tbl(struct adapter *adap)
1913f2c1e20SShagun Agrawal {
1923f2c1e20SShagun Agrawal 	if (adap->clipt)
1933f2c1e20SShagun Agrawal 		t4_os_free(adap->clipt);
1943f2c1e20SShagun Agrawal }
195