1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Chelsio Communications.
6 #include "base/common.h"
10 * Allocate clip entry in HW with associated IPV4/IPv6 address
12 static int clip6_get_mbox(const struct rte_eth_dev *dev, const u32 *lip)
14 struct adapter *adap = ethdev2adap(dev);
16 u64 hi = ((u64)lip[1]) << 32 | lip[0];
17 u64 lo = ((u64)lip[3]) << 32 | lip[2];
19 memset(&c, 0, sizeof(c));
20 c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
21 F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
22 c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
25 return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
29 * Delete clip entry in HW having the associated IPV4/IPV6 address
31 static int clip6_release_mbox(const struct rte_eth_dev *dev, const u32 *lip)
33 struct adapter *adap = ethdev2adap(dev);
35 u64 hi = ((u64)lip[1]) << 32 | lip[0];
36 u64 lo = ((u64)lip[3]) << 32 | lip[2];
38 memset(&c, 0, sizeof(c));
39 c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
40 F_FW_CMD_REQUEST | F_FW_CMD_READ);
41 c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
44 return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
48 * cxgbe_clip_release - Release associated CLIP entry
49 * @ce: clip entry to release
51 * Releases ref count and frees up a clip entry from CLIP table
53 void cxgbe_clip_release(struct rte_eth_dev *dev, struct clip_entry *ce)
57 t4_os_lock(&ce->lock);
58 if (__atomic_sub_fetch(&ce->refcnt, 1, __ATOMIC_RELAXED) == 0) {
59 ret = clip6_release_mbox(dev, ce->addr);
61 dev_debug(adap, "CLIP FW DEL CMD failed: %d", ret);
63 t4_os_unlock(&ce->lock);
67 * find_or_alloc_clipe - Find/Allocate a free CLIP entry
69 * @lip: IPV4/IPV6 address to compare/add
70 * Returns pointer to the IPV4/IPV6 entry found/created
72 * Finds/Allocates an CLIP entry to be used for a filter rule.
74 static struct clip_entry *find_or_alloc_clipe(struct clip_tbl *c,
77 struct clip_entry *end, *e;
78 struct clip_entry *first_free = NULL;
79 unsigned int clipt_size = c->clipt_size;
81 for (e = &c->cl_list[0], end = &c->cl_list[clipt_size]; e != end; ++e) {
82 if (__atomic_load_n(&e->refcnt, __ATOMIC_RELAXED) == 0) {
86 if (memcmp(lip, e->addr, sizeof(e->addr)) == 0)
102 static struct clip_entry *t4_clip_alloc(struct rte_eth_dev *dev,
105 struct adapter *adap = ethdev2adap(dev);
106 struct clip_tbl *ctbl = adap->clipt;
107 struct clip_entry *ce;
113 t4_os_write_lock(&ctbl->lock);
114 ce = find_or_alloc_clipe(ctbl, lip);
116 t4_os_lock(&ce->lock);
117 if (__atomic_load_n(&ce->refcnt, __ATOMIC_RELAXED) == 0) {
118 rte_memcpy(ce->addr, lip, sizeof(ce->addr));
120 ce->type = FILTER_TYPE_IPV6;
121 __atomic_store_n(&ce->refcnt, 1,
123 ret = clip6_get_mbox(dev, lip);
126 "CLIP FW ADD CMD failed: %d",
129 ce->type = FILTER_TYPE_IPV4;
132 __atomic_add_fetch(&ce->refcnt, 1, __ATOMIC_RELAXED);
134 t4_os_unlock(&ce->lock);
136 t4_os_write_unlock(&ctbl->lock);
138 return ret ? NULL : ce;
142 * cxgbe_clip_alloc - Allocate a IPV6 CLIP entry
143 * @dev: rte_eth_dev pointer
144 * @lip: IPV6 address to add
145 * Returns pointer to the CLIP entry created
147 * Allocates a IPV6 CLIP entry to be used for a filter rule.
149 struct clip_entry *cxgbe_clip_alloc(struct rte_eth_dev *dev, u32 *lip)
151 return t4_clip_alloc(dev, lip, FILTER_TYPE_IPV6);
155 * Initialize CLIP Table
157 struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
158 unsigned int clipt_end)
160 unsigned int clipt_size;
161 struct clip_tbl *ctbl;
164 if (clipt_start >= clipt_end)
167 clipt_size = clipt_end - clipt_start + 1;
169 ctbl = t4_os_alloc(sizeof(*ctbl) +
170 clipt_size * sizeof(struct clip_entry));
174 ctbl->clipt_start = clipt_start;
175 ctbl->clipt_size = clipt_size;
177 t4_os_rwlock_init(&ctbl->lock);
179 for (i = 0; i < ctbl->clipt_size; i++) {
180 t4_os_lock_init(&ctbl->cl_list[i].lock);
181 ctbl->cl_list[i].refcnt = 0;
190 void t4_cleanup_clip_tbl(struct adapter *adap)
193 t4_os_free(adap->clipt);