1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Chelsio Communications.
8 #include "cxgbe_filter.h"
11 * Initialize Hash Filters
13 int init_hash_filter(struct adapter *adap)
15 unsigned int n_user_filters;
16 unsigned int user_filter_perc;
18 u32 params[7], val[7];
20 #define FW_PARAM_DEV(param) \
21 (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
22 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
24 #define FW_PARAM_PFVF(param) \
25 (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
26 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \
27 V_FW_PARAMS_PARAM_Y(0) | \
28 V_FW_PARAMS_PARAM_Z(0))
30 params[0] = FW_PARAM_DEV(NTID);
31 ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
35 adap->tids.ntids = val[0];
36 adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
38 user_filter_perc = 100;
39 n_user_filters = mult_frac(adap->tids.nftids,
43 adap->tids.nftids = n_user_filters;
44 adap->params.hash_filter = 1;
49 * Validate if the requested filter specification can be set by checking
50 * if the requested features have been enabled
52 int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
57 * Check for unconfigured fields being used.
59 fconf = adapter->params.tp.vlan_pri_map;
62 (fs->val._field || fs->mask._field)
63 #define U(_mask, _field) \
64 (!(fconf & (_mask)) && S(_field))
66 if (U(F_ETHERTYPE, ethtype) || U(F_PROTOCOL, proto))
75 * Get the queue to which the traffic must be steered to.
77 static unsigned int get_filter_steerq(struct rte_eth_dev *dev,
78 struct ch_filter_specification *fs)
80 struct port_info *pi = ethdev2pinfo(dev);
81 struct adapter *adapter = pi->adapter;
85 * If the user has requested steering matching Ingress Packets
86 * to a specific Queue Set, we need to make sure it's in range
87 * for the port and map that into the Absolute Queue ID of the
88 * Queue Set's Response Queue.
94 * If the iq id is greater than the number of qsets,
95 * then assume it is an absolute qid.
97 if (fs->iq < pi->n_rx_qsets)
98 iq = adapter->sge.ethrxq[pi->first_qset +
107 /* Return an error number if the indicated filter isn't writable ... */
108 int writable_filter(struct filter_entry *f)
119 * Check if entry already filled.
121 bool is_filter_set(struct tid_info *t, int fidx, int family)
126 /* IPv6 requires four slots and IPv4 requires only 1 slot.
127 * Ensure, there's enough slots available.
129 max = family == FILTER_TYPE_IPV6 ? fidx + 3 : fidx;
131 t4_os_lock(&t->ftid_lock);
132 for (i = fidx; i <= max; i++) {
133 if (rte_bitmap_get(t->ftid_bmap, i)) {
138 t4_os_unlock(&t->ftid_lock);
143 * Allocate a available free entry
145 int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family)
147 struct tid_info *t = &adap->tids;
149 int size = t->nftids;
151 t4_os_lock(&t->ftid_lock);
152 if (family == FILTER_TYPE_IPV6)
153 pos = cxgbe_bitmap_find_free_region(t->ftid_bmap, size, 4);
155 pos = cxgbe_find_first_zero_bit(t->ftid_bmap, size);
156 t4_os_unlock(&t->ftid_lock);
158 return pos < size ? pos : -1;
162 * Clear a filter and release any of its resources that we own. This also
163 * clears the filter's "pending" status.
165 void clear_filter(struct filter_entry *f)
168 * The zeroing of the filter rule below clears the filter valid,
169 * pending, locked flags etc. so it's all we need for
172 memset(f, 0, sizeof(*f));
176 * t4_mk_filtdelwr - create a delete filter WR
177 * @ftid: the filter ID
178 * @wr: the filter work request to populate
179 * @qid: ingress queue to receive the delete notification
181 * Creates a filter work request to delete the supplied filter. If @qid is
182 * negative the delete notification is suppressed.
184 static void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
186 memset(wr, 0, sizeof(*wr));
187 wr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
188 wr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));
189 wr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |
190 V_FW_FILTER_WR_NOREPLY(qid < 0));
191 wr->del_filter_to_l2tix = cpu_to_be32(F_FW_FILTER_WR_DEL_FILTER);
193 wr->rx_chan_rx_rpl_iq =
194 cpu_to_be16(V_FW_FILTER_WR_RX_RPL_IQ(qid));
198 * Create FW work request to delete the filter at a specified index
200 static int del_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
202 struct adapter *adapter = ethdev2adap(dev);
203 struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
204 struct rte_mbuf *mbuf;
205 struct fw_filter_wr *fwr;
206 struct sge_ctrl_txq *ctrlq;
207 unsigned int port_id = ethdev2pinfo(dev)->port_id;
209 ctrlq = &adapter->sge.ctrlq[port_id];
210 mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
214 mbuf->data_len = sizeof(*fwr);
215 mbuf->pkt_len = mbuf->data_len;
217 fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);
218 t4_mk_filtdelwr(f->tid, fwr, adapter->sge.fw_evtq.abs_id);
221 * Mark the filter as "pending" and ship off the Filter Work Request.
222 * When we get the Work Request Reply we'll clear the pending status.
225 t4_mgmt_tx(ctrlq, mbuf);
229 int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
231 struct adapter *adapter = ethdev2adap(dev);
232 struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
233 struct rte_mbuf *mbuf;
234 struct fw_filter_wr *fwr;
235 struct sge_ctrl_txq *ctrlq;
236 unsigned int port_id = ethdev2pinfo(dev)->port_id;
239 ctrlq = &adapter->sge.ctrlq[port_id];
240 mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
246 mbuf->data_len = sizeof(*fwr);
247 mbuf->pkt_len = mbuf->data_len;
249 fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);
250 memset(fwr, 0, sizeof(*fwr));
253 * Construct the work request to set the filter.
255 fwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
256 fwr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*fwr) / 16));
258 cpu_to_be32(V_FW_FILTER_WR_TID(f->tid) |
259 V_FW_FILTER_WR_RQTYPE(f->fs.type) |
260 V_FW_FILTER_WR_NOREPLY(0) |
261 V_FW_FILTER_WR_IQ(f->fs.iq));
262 fwr->del_filter_to_l2tix =
263 cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
264 V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
265 V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
266 V_FW_FILTER_WR_PRIO(f->fs.prio));
267 fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
268 fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);
270 fwr->rx_chan_rx_rpl_iq =
271 cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |
272 V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id
274 fwr->ptcl = f->fs.val.proto;
275 fwr->ptclm = f->fs.mask.proto;
276 rte_memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
277 rte_memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));
278 rte_memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));
279 rte_memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm));
280 fwr->lp = cpu_to_be16(f->fs.val.lport);
281 fwr->lpm = cpu_to_be16(f->fs.mask.lport);
282 fwr->fp = cpu_to_be16(f->fs.val.fport);
283 fwr->fpm = cpu_to_be16(f->fs.mask.fport);
286 * Mark the filter as "pending" and ship off the Filter Work Request.
287 * When we get the Work Request Reply we'll clear the pending status.
290 t4_mgmt_tx(ctrlq, mbuf);
298 * Set the corresponding entry in the bitmap. 4 slots are
299 * marked for IPv6, whereas only 1 slot is marked for IPv4.
301 static int cxgbe_set_ftid(struct tid_info *t, int fidx, int family)
303 t4_os_lock(&t->ftid_lock);
304 if (rte_bitmap_get(t->ftid_bmap, fidx)) {
305 t4_os_unlock(&t->ftid_lock);
309 if (family == FILTER_TYPE_IPV4) {
310 rte_bitmap_set(t->ftid_bmap, fidx);
312 rte_bitmap_set(t->ftid_bmap, fidx);
313 rte_bitmap_set(t->ftid_bmap, fidx + 1);
314 rte_bitmap_set(t->ftid_bmap, fidx + 2);
315 rte_bitmap_set(t->ftid_bmap, fidx + 3);
317 t4_os_unlock(&t->ftid_lock);
322 * Clear the corresponding entry in the bitmap. 4 slots are
323 * cleared for IPv6, whereas only 1 slot is cleared for IPv4.
325 static void cxgbe_clear_ftid(struct tid_info *t, int fidx, int family)
327 t4_os_lock(&t->ftid_lock);
328 if (family == FILTER_TYPE_IPV4) {
329 rte_bitmap_clear(t->ftid_bmap, fidx);
331 rte_bitmap_clear(t->ftid_bmap, fidx);
332 rte_bitmap_clear(t->ftid_bmap, fidx + 1);
333 rte_bitmap_clear(t->ftid_bmap, fidx + 2);
334 rte_bitmap_clear(t->ftid_bmap, fidx + 3);
336 t4_os_unlock(&t->ftid_lock);
340 * Check a delete filter request for validity and send it to the hardware.
341 * Return 0 on success, an error number otherwise. We attach any provided
342 * filter operation context to the internal filter specification in order to
343 * facilitate signaling completion of the operation.
345 int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,
346 struct ch_filter_specification *fs,
347 struct filter_ctx *ctx)
349 struct port_info *pi = (struct port_info *)(dev->data->dev_private);
350 struct adapter *adapter = pi->adapter;
351 struct filter_entry *f;
354 if (filter_id >= adapter->tids.nftids)
357 ret = is_filter_set(&adapter->tids, filter_id, fs->type);
359 dev_warn(adap, "%s: could not find filter entry: %u\n",
360 __func__, filter_id);
364 f = &adapter->tids.ftid_tab[filter_id];
365 ret = writable_filter(f);
371 cxgbe_clear_ftid(&adapter->tids,
372 f->tid - adapter->tids.ftid_base,
373 f->fs.type ? FILTER_TYPE_IPV6 :
375 return del_filter_wr(dev, filter_id);
379 * If the caller has passed in a Completion Context then we need to
380 * mark it as a successful completion so they don't stall waiting
385 t4_complete(&ctx->completion);
392 * Check a Chelsio Filter Request for validity, convert it into our internal
393 * format and send it to the hardware. Return 0 on success, an error number
394 * otherwise. We attach any provided filter operation context to the internal
395 * filter specification in order to facilitate signaling completion of the
398 int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,
399 struct ch_filter_specification *fs,
400 struct filter_ctx *ctx)
402 struct port_info *pi = ethdev2pinfo(dev);
403 struct adapter *adapter = pi->adapter;
404 unsigned int fidx, iq, fid_bit = 0;
405 struct filter_entry *f;
408 if (filter_id >= adapter->tids.nftids)
411 ret = validate_filter(adapter, fs);
416 * Ensure filter id is aligned on the 4 slot boundary for IPv6
422 ret = is_filter_set(&adapter->tids, filter_id, fs->type);
426 iq = get_filter_steerq(dev, fs);
429 * IPv6 filters occupy four slots and must be aligned on
430 * four-slot boundaries. IPv4 filters only occupy a single
431 * slot and have no alignment requirements but writing a new
432 * IPv4 filter into the middle of an existing IPv6 filter
433 * requires clearing the old IPv6 filter.
435 if (fs->type == FILTER_TYPE_IPV4) { /* IPv4 */
437 * If our IPv4 filter isn't being written to a
438 * multiple of four filter index and there's an IPv6
439 * filter at the multiple of 4 base slot, then we need
440 * to delete that IPv6 filter ...
442 fidx = filter_id & ~0x3;
443 if (fidx != filter_id && adapter->tids.ftid_tab[fidx].fs.type) {
444 f = &adapter->tids.ftid_tab[fidx];
450 * Ensure that the IPv6 filter is aligned on a
451 * multiple of 4 boundary.
457 * Check all except the base overlapping IPv4 filter
460 for (fidx = filter_id + 1; fidx < filter_id + 4; fidx++) {
461 f = &adapter->tids.ftid_tab[fidx];
468 * Check to make sure that provided filter index is not
469 * already in use by someone else
471 f = &adapter->tids.ftid_tab[filter_id];
475 fidx = adapter->tids.ftid_base + filter_id;
477 ret = cxgbe_set_ftid(&adapter->tids, fid_bit,
478 fs->type ? FILTER_TYPE_IPV6 : FILTER_TYPE_IPV4);
483 * Check to make sure the filter requested is writable ...
485 ret = writable_filter(f);
487 /* Clear the bits we have set above */
488 cxgbe_clear_ftid(&adapter->tids, fid_bit,
489 fs->type ? FILTER_TYPE_IPV6 :
495 * Convert the filter specification into our internal format.
496 * We copy the PF/VF specification into the Outer VLAN field
497 * here so the rest of the code -- including the interface to
498 * the firmware -- doesn't have to constantly do these checks.
505 * Attempt to set the filter. If we don't succeed, we clear
506 * it and return the failure.
509 f->tid = fidx; /* Save the actual tid */
510 ret = set_filter_wr(dev, filter_id);
512 fid_bit = f->tid - adapter->tids.ftid_base;
513 cxgbe_clear_ftid(&adapter->tids, fid_bit,
514 fs->type ? FILTER_TYPE_IPV6 :
523 * Handle a LE-TCAM filter write/deletion reply.
525 void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
527 struct filter_entry *f = NULL;
528 unsigned int tid = GET_TID(rpl);
529 int idx, max_fidx = adap->tids.nftids;
531 /* Get the corresponding filter entry for this tid */
532 if (adap->tids.ftid_tab) {
533 /* Check this in normal filter region */
534 idx = tid - adap->tids.ftid_base;
538 f = &adap->tids.ftid_tab[idx];
543 /* We found the filter entry for this tid */
545 unsigned int ret = G_COOKIE(rpl->cookie);
546 struct filter_ctx *ctx;
549 * Pull off any filter operation context attached to the
555 if (ret == FW_FILTER_WR_FLT_ADDED) {
556 f->pending = 0; /* asynchronous setup completed */
562 } else if (ret == FW_FILTER_WR_FLT_DELETED) {
564 * Clear the filter when we get confirmation from the
565 * hardware that the filter has been deleted.
572 * Something went wrong. Issue a warning about the
573 * problem and clear everything out.
575 dev_warn(adap, "filter %u setup failed with error %u\n",
579 ctx->result = -EINVAL;
583 t4_complete(&ctx->completion);
588 * Retrieve the packet count for the specified filter.
590 int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,
591 u64 *c, bool get_byte)
593 struct filter_entry *f;
594 unsigned int tcb_base, tcbaddr;
597 tcb_base = t4_read_reg(adapter, A_TP_CMM_TCB_BASE);
598 if (fidx >= adapter->tids.nftids)
601 f = &adapter->tids.ftid_tab[fidx];
605 tcbaddr = tcb_base + f->tid * TCB_SIZE;
607 if (is_t5(adapter->params.chip) || is_t6(adapter->params.chip)) {
609 * For T5, the Filter Packet Hit Count is maintained as a
610 * 32-bit Big Endian value in the TCB field {timestamp}.
611 * Similar to the craziness above, instead of the filter hit
612 * count showing up at offset 20 ((W_TCB_TIMESTAMP == 5) *
613 * sizeof(u32)), it actually shows up at offset 24. Whacky.
616 unsigned int word_offset = 4;
617 __be64 be64_byte_count;
619 t4_os_lock(&adapter->win0_lock);
620 ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
622 (word_offset * sizeof(__be32)),
623 sizeof(be64_byte_count),
626 t4_os_unlock(&adapter->win0_lock);
629 *c = be64_to_cpu(be64_byte_count);
631 unsigned int word_offset = 6;
634 t4_os_lock(&adapter->win0_lock);
635 ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
637 (word_offset * sizeof(__be32)),
638 sizeof(be32_count), &be32_count,
640 t4_os_unlock(&adapter->win0_lock);
643 *c = (u64)be32_to_cpu(be32_count);