net/cxgbe: support to match on ingress physical port
[dpdk.git] / drivers / net / cxgbe / cxgbe_filter.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Chelsio Communications.
3  * All rights reserved.
4  */
5 #include <rte_net.h>
6 #include "common.h"
7 #include "t4_tcb.h"
8 #include "t4_regs.h"
9 #include "cxgbe_filter.h"
10 #include "clip_tbl.h"
11
12 /**
13  * Initialize Hash Filters
14  */
15 int init_hash_filter(struct adapter *adap)
16 {
17         unsigned int n_user_filters;
18         unsigned int user_filter_perc;
19         int ret;
20         u32 params[7], val[7];
21
22 #define FW_PARAM_DEV(param) \
23         (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
24         V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
25
26 #define FW_PARAM_PFVF(param) \
27         (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
28         V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) |  \
29         V_FW_PARAMS_PARAM_Y(0) | \
30         V_FW_PARAMS_PARAM_Z(0))
31
32         params[0] = FW_PARAM_DEV(NTID);
33         ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
34                               params, val);
35         if (ret < 0)
36                 return ret;
37         adap->tids.ntids = val[0];
38         adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
39
40         user_filter_perc = 100;
41         n_user_filters = mult_frac(adap->tids.nftids,
42                                    user_filter_perc,
43                                    100);
44
45         adap->tids.nftids = n_user_filters;
46         adap->params.hash_filter = 1;
47         return 0;
48 }
49
50 /**
51  * Validate if the requested filter specification can be set by checking
52  * if the requested features have been enabled
53  */
54 int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
55 {
56         u32 fconf;
57
58         /*
59          * Check for unconfigured fields being used.
60          */
61         fconf = adapter->params.tp.vlan_pri_map;
62
63 #define S(_field) \
64         (fs->val._field || fs->mask._field)
65 #define U(_mask, _field) \
66         (!(fconf & (_mask)) && S(_field))
67
68         if (U(F_PORT, iport) || U(F_ETHERTYPE, ethtype) || U(F_PROTOCOL, proto))
69                 return -EOPNOTSUPP;
70
71 #undef S
72 #undef U
73
74         /*
75          * Don't allow various trivially obvious bogus out-of-range
76          * values ...
77          */
78         if (fs->val.iport >= adapter->params.nports)
79                 return -ERANGE;
80
81         return 0;
82 }
83
84 /**
85  * Get the queue to which the traffic must be steered to.
86  */
87 static unsigned int get_filter_steerq(struct rte_eth_dev *dev,
88                                       struct ch_filter_specification *fs)
89 {
90         struct port_info *pi = ethdev2pinfo(dev);
91         struct adapter *adapter = pi->adapter;
92         unsigned int iq;
93
94         /*
95          * If the user has requested steering matching Ingress Packets
96          * to a specific Queue Set, we need to make sure it's in range
97          * for the port and map that into the Absolute Queue ID of the
98          * Queue Set's Response Queue.
99          */
100         if (!fs->dirsteer) {
101                 iq = 0;
102         } else {
103                 /*
104                  * If the iq id is greater than the number of qsets,
105                  * then assume it is an absolute qid.
106                  */
107                 if (fs->iq < pi->n_rx_qsets)
108                         iq = adapter->sge.ethrxq[pi->first_qset +
109                                                  fs->iq].rspq.abs_id;
110                 else
111                         iq = fs->iq;
112         }
113
114         return iq;
115 }
116
117 /* Return an error number if the indicated filter isn't writable ... */
118 int writable_filter(struct filter_entry *f)
119 {
120         if (f->locked)
121                 return -EPERM;
122         if (f->pending)
123                 return -EBUSY;
124
125         return 0;
126 }
127
128 /**
129  * Send CPL_SET_TCB_FIELD message
130  */
131 static void set_tcb_field(struct adapter *adapter, unsigned int ftid,
132                           u16 word, u64 mask, u64 val, int no_reply)
133 {
134         struct rte_mbuf *mbuf;
135         struct cpl_set_tcb_field *req;
136         struct sge_ctrl_txq *ctrlq;
137
138         ctrlq = &adapter->sge.ctrlq[0];
139         mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
140         WARN_ON(!mbuf);
141
142         mbuf->data_len = sizeof(*req);
143         mbuf->pkt_len = mbuf->data_len;
144
145         req = rte_pktmbuf_mtod(mbuf, struct cpl_set_tcb_field *);
146         memset(req, 0, sizeof(*req));
147         INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, ftid);
148         req->reply_ctrl = cpu_to_be16(V_REPLY_CHAN(0) |
149                                       V_QUEUENO(adapter->sge.fw_evtq.abs_id) |
150                                       V_NO_REPLY(no_reply));
151         req->word_cookie = cpu_to_be16(V_WORD(word) | V_COOKIE(ftid));
152         req->mask = cpu_to_be64(mask);
153         req->val = cpu_to_be64(val);
154
155         t4_mgmt_tx(ctrlq, mbuf);
156 }
157
158 /**
159  * Build a CPL_SET_TCB_FIELD message as payload of a ULP_TX_PKT command.
160  */
161 static inline void mk_set_tcb_field_ulp(struct filter_entry *f,
162                                         struct cpl_set_tcb_field *req,
163                                         unsigned int word,
164                                         u64 mask, u64 val, u8 cookie,
165                                         int no_reply)
166 {
167         struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req;
168         struct ulptx_idata *sc = (struct ulptx_idata *)(txpkt + 1);
169
170         txpkt->cmd_dest = cpu_to_be32(V_ULPTX_CMD(ULP_TX_PKT) |
171                                       V_ULP_TXPKT_DEST(0));
172         txpkt->len = cpu_to_be32(DIV_ROUND_UP(sizeof(*req), 16));
173         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_IMM));
174         sc->len = cpu_to_be32(sizeof(*req) - sizeof(struct work_request_hdr));
175         OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_SET_TCB_FIELD, f->tid));
176         req->reply_ctrl = cpu_to_be16(V_NO_REPLY(no_reply) | V_REPLY_CHAN(0) |
177                                       V_QUEUENO(0));
178         req->word_cookie = cpu_to_be16(V_WORD(word) | V_COOKIE(cookie));
179         req->mask = cpu_to_be64(mask);
180         req->val = cpu_to_be64(val);
181         sc = (struct ulptx_idata *)(req + 1);
182         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
183         sc->len = cpu_to_be32(0);
184 }
185
186 /**
187  * Check if entry already filled.
188  */
189 bool is_filter_set(struct tid_info *t, int fidx, int family)
190 {
191         bool result = FALSE;
192         int i, max;
193
194         /* IPv6 requires four slots and IPv4 requires only 1 slot.
195          * Ensure, there's enough slots available.
196          */
197         max = family == FILTER_TYPE_IPV6 ? fidx + 3 : fidx;
198
199         t4_os_lock(&t->ftid_lock);
200         for (i = fidx; i <= max; i++) {
201                 if (rte_bitmap_get(t->ftid_bmap, i)) {
202                         result = TRUE;
203                         break;
204                 }
205         }
206         t4_os_unlock(&t->ftid_lock);
207         return result;
208 }
209
210 /**
211  * Allocate a available free entry
212  */
213 int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family)
214 {
215         struct tid_info *t = &adap->tids;
216         int pos;
217         int size = t->nftids;
218
219         t4_os_lock(&t->ftid_lock);
220         if (family == FILTER_TYPE_IPV6)
221                 pos = cxgbe_bitmap_find_free_region(t->ftid_bmap, size, 4);
222         else
223                 pos = cxgbe_find_first_zero_bit(t->ftid_bmap, size);
224         t4_os_unlock(&t->ftid_lock);
225
226         return pos < size ? pos : -1;
227 }
228
229 /**
230  * Construct hash filter ntuple.
231  */
232 static u64 hash_filter_ntuple(const struct filter_entry *f)
233 {
234         struct adapter *adap = ethdev2adap(f->dev);
235         struct tp_params *tp = &adap->params.tp;
236         u64 ntuple = 0;
237         u16 tcp_proto = IPPROTO_TCP; /* TCP Protocol Number */
238
239         if (tp->port_shift >= 0)
240                 ntuple |= (u64)f->fs.mask.iport << tp->port_shift;
241
242         if (tp->protocol_shift >= 0) {
243                 if (!f->fs.val.proto)
244                         ntuple |= (u64)tcp_proto << tp->protocol_shift;
245                 else
246                         ntuple |= (u64)f->fs.val.proto << tp->protocol_shift;
247         }
248
249         if (tp->ethertype_shift >= 0 && f->fs.mask.ethtype)
250                 ntuple |= (u64)(f->fs.val.ethtype) << tp->ethertype_shift;
251
252         if (ntuple != tp->hash_filter_mask)
253                 return 0;
254
255         return ntuple;
256 }
257
258 /**
259  * Build a CPL_ABORT_REQ message as payload of a ULP_TX_PKT command.
260  */
261 static void mk_abort_req_ulp(struct cpl_abort_req *abort_req,
262                              unsigned int tid)
263 {
264         struct ulp_txpkt *txpkt = (struct ulp_txpkt *)abort_req;
265         struct ulptx_idata *sc = (struct ulptx_idata *)(txpkt + 1);
266
267         txpkt->cmd_dest = cpu_to_be32(V_ULPTX_CMD(ULP_TX_PKT) |
268                                       V_ULP_TXPKT_DEST(0));
269         txpkt->len = cpu_to_be32(DIV_ROUND_UP(sizeof(*abort_req), 16));
270         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_IMM));
271         sc->len = cpu_to_be32(sizeof(*abort_req) -
272                               sizeof(struct work_request_hdr));
273         OPCODE_TID(abort_req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
274         abort_req->rsvd0 = cpu_to_be32(0);
275         abort_req->rsvd1 = 0;
276         abort_req->cmd = CPL_ABORT_NO_RST;
277         sc = (struct ulptx_idata *)(abort_req + 1);
278         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
279         sc->len = cpu_to_be32(0);
280 }
281
282 /**
283  * Build a CPL_ABORT_RPL message as payload of a ULP_TX_PKT command.
284  */
285 static void mk_abort_rpl_ulp(struct cpl_abort_rpl *abort_rpl,
286                              unsigned int tid)
287 {
288         struct ulp_txpkt *txpkt = (struct ulp_txpkt *)abort_rpl;
289         struct ulptx_idata *sc = (struct ulptx_idata *)(txpkt + 1);
290
291         txpkt->cmd_dest = cpu_to_be32(V_ULPTX_CMD(ULP_TX_PKT) |
292                                       V_ULP_TXPKT_DEST(0));
293         txpkt->len = cpu_to_be32(DIV_ROUND_UP(sizeof(*abort_rpl), 16));
294         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_IMM));
295         sc->len = cpu_to_be32(sizeof(*abort_rpl) -
296                               sizeof(struct work_request_hdr));
297         OPCODE_TID(abort_rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
298         abort_rpl->rsvd0 = cpu_to_be32(0);
299         abort_rpl->rsvd1 = 0;
300         abort_rpl->cmd = CPL_ABORT_NO_RST;
301         sc = (struct ulptx_idata *)(abort_rpl + 1);
302         sc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
303         sc->len = cpu_to_be32(0);
304 }
305
306 /**
307  * Delete the specified hash filter.
308  */
309 static int cxgbe_del_hash_filter(struct rte_eth_dev *dev,
310                                  unsigned int filter_id,
311                                  struct filter_ctx *ctx)
312 {
313         struct adapter *adapter = ethdev2adap(dev);
314         struct tid_info *t = &adapter->tids;
315         struct filter_entry *f;
316         struct sge_ctrl_txq *ctrlq;
317         unsigned int port_id = ethdev2pinfo(dev)->port_id;
318         int ret;
319
320         if (filter_id > adapter->tids.ntids)
321                 return -E2BIG;
322
323         f = lookup_tid(t, filter_id);
324         if (!f) {
325                 dev_err(adapter, "%s: no filter entry for filter_id = %d\n",
326                         __func__, filter_id);
327                 return -EINVAL;
328         }
329
330         ret = writable_filter(f);
331         if (ret)
332                 return ret;
333
334         if (f->valid) {
335                 unsigned int wrlen;
336                 struct rte_mbuf *mbuf;
337                 struct work_request_hdr *wr;
338                 struct ulptx_idata *aligner;
339                 struct cpl_set_tcb_field *req;
340                 struct cpl_abort_req *abort_req;
341                 struct cpl_abort_rpl *abort_rpl;
342
343                 f->ctx = ctx;
344                 f->pending = 1;
345
346                 wrlen = cxgbe_roundup(sizeof(*wr) +
347                                       (sizeof(*req) + sizeof(*aligner)) +
348                                       sizeof(*abort_req) + sizeof(*abort_rpl),
349                                       16);
350
351                 ctrlq = &adapter->sge.ctrlq[port_id];
352                 mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
353                 if (!mbuf) {
354                         dev_err(adapter, "%s: could not allocate skb ..\n",
355                                 __func__);
356                         goto out_err;
357                 }
358
359                 mbuf->data_len = wrlen;
360                 mbuf->pkt_len = mbuf->data_len;
361
362                 req = rte_pktmbuf_mtod(mbuf, struct cpl_set_tcb_field *);
363                 INIT_ULPTX_WR(req, wrlen, 0, 0);
364                 wr = (struct work_request_hdr *)req;
365                 wr++;
366                 req = (struct cpl_set_tcb_field *)wr;
367                 mk_set_tcb_field_ulp(f, req, W_TCB_RSS_INFO,
368                                 V_TCB_RSS_INFO(M_TCB_RSS_INFO),
369                                 V_TCB_RSS_INFO(adapter->sge.fw_evtq.abs_id),
370                                 0, 1);
371                 aligner = (struct ulptx_idata *)(req + 1);
372                 abort_req = (struct cpl_abort_req *)(aligner + 1);
373                 mk_abort_req_ulp(abort_req, f->tid);
374                 abort_rpl = (struct cpl_abort_rpl *)(abort_req + 1);
375                 mk_abort_rpl_ulp(abort_rpl, f->tid);
376                 t4_mgmt_tx(ctrlq, mbuf);
377         }
378         return 0;
379
380 out_err:
381         return -ENOMEM;
382 }
383
384 /**
385  * Build a ACT_OPEN_REQ6 message for setting IPv6 hash filter.
386  */
387 static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,
388                              unsigned int qid_filterid, struct adapter *adap)
389 {
390         struct cpl_t6_act_open_req6 *req = NULL;
391         u64 local_lo, local_hi, peer_lo, peer_hi;
392         u32 *lip = (u32 *)f->fs.val.lip;
393         u32 *fip = (u32 *)f->fs.val.fip;
394
395         switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
396         case CHELSIO_T6:
397                 req = rte_pktmbuf_mtod(mbuf, struct cpl_t6_act_open_req6 *);
398
399                 INIT_TP_WR(req, 0);
400                 break;
401         default:
402                 dev_err(adap, "%s: unsupported chip type!\n", __func__);
403                 return;
404         }
405
406         local_hi = ((u64)lip[1]) << 32 | lip[0];
407         local_lo = ((u64)lip[3]) << 32 | lip[2];
408         peer_hi = ((u64)fip[1]) << 32 | fip[0];
409         peer_lo = ((u64)fip[3]) << 32 | fip[2];
410
411         OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
412                                                     qid_filterid));
413         req->local_port = cpu_to_be16(f->fs.val.lport);
414         req->peer_port = cpu_to_be16(f->fs.val.fport);
415         req->local_ip_hi = local_hi;
416         req->local_ip_lo = local_lo;
417         req->peer_ip_hi = peer_hi;
418         req->peer_ip_lo = peer_lo;
419         req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
420                                 V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
421                                            << 1) |
422                                 V_ULP_MODE(ULP_MODE_NONE) |
423                                 F_TCAM_BYPASS | F_NON_OFFLOAD);
424         req->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));
425         req->opt2 = cpu_to_be32(F_RSS_QUEUE_VALID |
426                             V_RSS_QUEUE(f->fs.iq) |
427                             F_T5_OPT_2_VALID |
428                             F_RX_CHANNEL |
429                             V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
430                                          (f->fs.dirsteer << 1)));
431 }
432
433 /**
434  * Build a ACT_OPEN_REQ message for setting IPv4 hash filter.
435  */
436 static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,
437                             unsigned int qid_filterid, struct adapter *adap)
438 {
439         struct cpl_t6_act_open_req *req = NULL;
440
441         switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
442         case CHELSIO_T6:
443                 req = rte_pktmbuf_mtod(mbuf, struct cpl_t6_act_open_req *);
444
445                 INIT_TP_WR(req, 0);
446                 break;
447         default:
448                 dev_err(adap, "%s: unsupported chip type!\n", __func__);
449                 return;
450         }
451
452         OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
453                                                     qid_filterid));
454         req->local_port = cpu_to_be16(f->fs.val.lport);
455         req->peer_port = cpu_to_be16(f->fs.val.fport);
456         req->local_ip = f->fs.val.lip[0] | f->fs.val.lip[1] << 8 |
457                         f->fs.val.lip[2] << 16 | f->fs.val.lip[3] << 24;
458         req->peer_ip = f->fs.val.fip[0] | f->fs.val.fip[1] << 8 |
459                         f->fs.val.fip[2] << 16 | f->fs.val.fip[3] << 24;
460         req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
461                                 V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
462                                            << 1) |
463                                 V_ULP_MODE(ULP_MODE_NONE) |
464                                 F_TCAM_BYPASS | F_NON_OFFLOAD);
465         req->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));
466         req->opt2 = cpu_to_be32(F_RSS_QUEUE_VALID |
467                             V_RSS_QUEUE(f->fs.iq) |
468                             F_T5_OPT_2_VALID |
469                             F_RX_CHANNEL |
470                             V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
471                                          (f->fs.dirsteer << 1)));
472 }
473
474 /**
475  * Set the specified hash filter.
476  */
477 static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,
478                                  struct ch_filter_specification *fs,
479                                  struct filter_ctx *ctx)
480 {
481         struct port_info *pi = ethdev2pinfo(dev);
482         struct adapter *adapter = pi->adapter;
483         struct tid_info *t = &adapter->tids;
484         struct filter_entry *f;
485         struct rte_mbuf *mbuf;
486         struct sge_ctrl_txq *ctrlq;
487         unsigned int iq;
488         int atid, size;
489         int ret = 0;
490
491         ret = validate_filter(adapter, fs);
492         if (ret)
493                 return ret;
494
495         iq = get_filter_steerq(dev, fs);
496
497         ctrlq = &adapter->sge.ctrlq[pi->port_id];
498
499         f = t4_os_alloc(sizeof(*f));
500         if (!f)
501                 goto out_err;
502
503         f->fs = *fs;
504         f->ctx = ctx;
505         f->dev = dev;
506         f->fs.iq = iq;
507
508         atid = cxgbe_alloc_atid(t, f);
509         if (atid < 0)
510                 goto out_err;
511
512         if (f->fs.type) {
513                 /* IPv6 hash filter */
514                 f->clipt = cxgbe_clip_alloc(f->dev, (u32 *)&f->fs.val.lip);
515                 if (!f->clipt)
516                         goto free_atid;
517
518                 size = sizeof(struct cpl_t6_act_open_req6);
519                 mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
520                 if (!mbuf) {
521                         ret = -ENOMEM;
522                         goto free_clip;
523                 }
524
525                 mbuf->data_len = size;
526                 mbuf->pkt_len = mbuf->data_len;
527
528                 mk_act_open_req6(f, mbuf,
529                                  ((adapter->sge.fw_evtq.abs_id << 14) | atid),
530                                  adapter);
531         } else {
532                 /* IPv4 hash filter */
533                 size = sizeof(struct cpl_t6_act_open_req);
534                 mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
535                 if (!mbuf) {
536                         ret = -ENOMEM;
537                         goto free_atid;
538                 }
539
540                 mbuf->data_len = size;
541                 mbuf->pkt_len = mbuf->data_len;
542
543                 mk_act_open_req(f, mbuf,
544                                 ((adapter->sge.fw_evtq.abs_id << 14) | atid),
545                                 adapter);
546         }
547
548         f->pending = 1;
549         t4_mgmt_tx(ctrlq, mbuf);
550         return 0;
551
552 free_clip:
553         cxgbe_clip_release(f->dev, f->clipt);
554 free_atid:
555         cxgbe_free_atid(t, atid);
556
557 out_err:
558         t4_os_free(f);
559         return ret;
560 }
561
562 /**
563  * Clear a filter and release any of its resources that we own.  This also
564  * clears the filter's "pending" status.
565  */
566 void clear_filter(struct filter_entry *f)
567 {
568         if (f->clipt)
569                 cxgbe_clip_release(f->dev, f->clipt);
570
571         /*
572          * The zeroing of the filter rule below clears the filter valid,
573          * pending, locked flags etc. so it's all we need for
574          * this operation.
575          */
576         memset(f, 0, sizeof(*f));
577 }
578
579 /**
580  * t4_mk_filtdelwr - create a delete filter WR
581  * @ftid: the filter ID
582  * @wr: the filter work request to populate
583  * @qid: ingress queue to receive the delete notification
584  *
585  * Creates a filter work request to delete the supplied filter.  If @qid is
586  * negative the delete notification is suppressed.
587  */
588 static void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
589 {
590         memset(wr, 0, sizeof(*wr));
591         wr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
592         wr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));
593         wr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |
594                                     V_FW_FILTER_WR_NOREPLY(qid < 0));
595         wr->del_filter_to_l2tix = cpu_to_be32(F_FW_FILTER_WR_DEL_FILTER);
596         if (qid >= 0)
597                 wr->rx_chan_rx_rpl_iq =
598                                 cpu_to_be16(V_FW_FILTER_WR_RX_RPL_IQ(qid));
599 }
600
601 /**
602  * Create FW work request to delete the filter at a specified index
603  */
604 static int del_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
605 {
606         struct adapter *adapter = ethdev2adap(dev);
607         struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
608         struct rte_mbuf *mbuf;
609         struct fw_filter_wr *fwr;
610         struct sge_ctrl_txq *ctrlq;
611         unsigned int port_id = ethdev2pinfo(dev)->port_id;
612
613         ctrlq = &adapter->sge.ctrlq[port_id];
614         mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
615         if (!mbuf)
616                 return -ENOMEM;
617
618         mbuf->data_len = sizeof(*fwr);
619         mbuf->pkt_len = mbuf->data_len;
620
621         fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);
622         t4_mk_filtdelwr(f->tid, fwr, adapter->sge.fw_evtq.abs_id);
623
624         /*
625          * Mark the filter as "pending" and ship off the Filter Work Request.
626          * When we get the Work Request Reply we'll clear the pending status.
627          */
628         f->pending = 1;
629         t4_mgmt_tx(ctrlq, mbuf);
630         return 0;
631 }
632
633 int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
634 {
635         struct adapter *adapter = ethdev2adap(dev);
636         struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
637         struct rte_mbuf *mbuf;
638         struct fw_filter_wr *fwr;
639         struct sge_ctrl_txq *ctrlq;
640         unsigned int port_id = ethdev2pinfo(dev)->port_id;
641         int ret;
642
643         ctrlq = &adapter->sge.ctrlq[port_id];
644         mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
645         if (!mbuf) {
646                 ret = -ENOMEM;
647                 goto out;
648         }
649
650         mbuf->data_len = sizeof(*fwr);
651         mbuf->pkt_len = mbuf->data_len;
652
653         fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);
654         memset(fwr, 0, sizeof(*fwr));
655
656         /*
657          * Construct the work request to set the filter.
658          */
659         fwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
660         fwr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*fwr) / 16));
661         fwr->tid_to_iq =
662                 cpu_to_be32(V_FW_FILTER_WR_TID(f->tid) |
663                             V_FW_FILTER_WR_RQTYPE(f->fs.type) |
664                             V_FW_FILTER_WR_NOREPLY(0) |
665                             V_FW_FILTER_WR_IQ(f->fs.iq));
666         fwr->del_filter_to_l2tix =
667                 cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
668                             V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
669                             V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
670                             V_FW_FILTER_WR_PRIO(f->fs.prio));
671         fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
672         fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);
673         fwr->smac_sel = 0;
674         fwr->rx_chan_rx_rpl_iq =
675                 cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |
676                             V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id
677                                                      ));
678         fwr->maci_to_matchtypem =
679                 cpu_to_be32(V_FW_FILTER_WR_PORT(f->fs.val.iport) |
680                             V_FW_FILTER_WR_PORTM(f->fs.mask.iport));
681         fwr->ptcl = f->fs.val.proto;
682         fwr->ptclm = f->fs.mask.proto;
683         rte_memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
684         rte_memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));
685         rte_memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));
686         rte_memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm));
687         fwr->lp = cpu_to_be16(f->fs.val.lport);
688         fwr->lpm = cpu_to_be16(f->fs.mask.lport);
689         fwr->fp = cpu_to_be16(f->fs.val.fport);
690         fwr->fpm = cpu_to_be16(f->fs.mask.fport);
691
692         /*
693          * Mark the filter as "pending" and ship off the Filter Work Request.
694          * When we get the Work Request Reply we'll clear the pending status.
695          */
696         f->pending = 1;
697         t4_mgmt_tx(ctrlq, mbuf);
698         return 0;
699
700 out:
701         return ret;
702 }
703
704 /**
705  * Set the corresponding entry in the bitmap. 4 slots are
706  * marked for IPv6, whereas only 1 slot is marked for IPv4.
707  */
708 static int cxgbe_set_ftid(struct tid_info *t, int fidx, int family)
709 {
710         t4_os_lock(&t->ftid_lock);
711         if (rte_bitmap_get(t->ftid_bmap, fidx)) {
712                 t4_os_unlock(&t->ftid_lock);
713                 return -EBUSY;
714         }
715
716         if (family == FILTER_TYPE_IPV4) {
717                 rte_bitmap_set(t->ftid_bmap, fidx);
718         } else {
719                 rte_bitmap_set(t->ftid_bmap, fidx);
720                 rte_bitmap_set(t->ftid_bmap, fidx + 1);
721                 rte_bitmap_set(t->ftid_bmap, fidx + 2);
722                 rte_bitmap_set(t->ftid_bmap, fidx + 3);
723         }
724         t4_os_unlock(&t->ftid_lock);
725         return 0;
726 }
727
728 /**
729  * Clear the corresponding entry in the bitmap. 4 slots are
730  * cleared for IPv6, whereas only 1 slot is cleared for IPv4.
731  */
732 static void cxgbe_clear_ftid(struct tid_info *t, int fidx, int family)
733 {
734         t4_os_lock(&t->ftid_lock);
735         if (family == FILTER_TYPE_IPV4) {
736                 rte_bitmap_clear(t->ftid_bmap, fidx);
737         } else {
738                 rte_bitmap_clear(t->ftid_bmap, fidx);
739                 rte_bitmap_clear(t->ftid_bmap, fidx + 1);
740                 rte_bitmap_clear(t->ftid_bmap, fidx + 2);
741                 rte_bitmap_clear(t->ftid_bmap, fidx + 3);
742         }
743         t4_os_unlock(&t->ftid_lock);
744 }
745
746 /**
747  * Check a delete filter request for validity and send it to the hardware.
748  * Return 0 on success, an error number otherwise.  We attach any provided
749  * filter operation context to the internal filter specification in order to
750  * facilitate signaling completion of the operation.
751  */
752 int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,
753                      struct ch_filter_specification *fs,
754                      struct filter_ctx *ctx)
755 {
756         struct port_info *pi = (struct port_info *)(dev->data->dev_private);
757         struct adapter *adapter = pi->adapter;
758         struct filter_entry *f;
759         unsigned int chip_ver;
760         int ret;
761
762         if (is_hashfilter(adapter) && fs->cap)
763                 return cxgbe_del_hash_filter(dev, filter_id, ctx);
764
765         if (filter_id >= adapter->tids.nftids)
766                 return -ERANGE;
767
768         chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip);
769
770         ret = is_filter_set(&adapter->tids, filter_id, fs->type);
771         if (!ret) {
772                 dev_warn(adap, "%s: could not find filter entry: %u\n",
773                          __func__, filter_id);
774                 return -EINVAL;
775         }
776
777         /*
778          * Ensure filter id is aligned on the 2 slot boundary for T6,
779          * and 4 slot boundary for cards below T6.
780          */
781         if (fs->type) {
782                 if (chip_ver < CHELSIO_T6)
783                         filter_id &= ~(0x3);
784                 else
785                         filter_id &= ~(0x1);
786         }
787
788         f = &adapter->tids.ftid_tab[filter_id];
789         ret = writable_filter(f);
790         if (ret)
791                 return ret;
792
793         if (f->valid) {
794                 f->ctx = ctx;
795                 cxgbe_clear_ftid(&adapter->tids,
796                                  f->tid - adapter->tids.ftid_base,
797                                  f->fs.type ? FILTER_TYPE_IPV6 :
798                                               FILTER_TYPE_IPV4);
799                 return del_filter_wr(dev, filter_id);
800         }
801
802         /*
803          * If the caller has passed in a Completion Context then we need to
804          * mark it as a successful completion so they don't stall waiting
805          * for it.
806          */
807         if (ctx) {
808                 ctx->result = 0;
809                 t4_complete(&ctx->completion);
810         }
811
812         return 0;
813 }
814
815 /**
816  * Check a Chelsio Filter Request for validity, convert it into our internal
817  * format and send it to the hardware.  Return 0 on success, an error number
818  * otherwise.  We attach any provided filter operation context to the internal
819  * filter specification in order to facilitate signaling completion of the
820  * operation.
821  */
822 int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,
823                      struct ch_filter_specification *fs,
824                      struct filter_ctx *ctx)
825 {
826         struct port_info *pi = ethdev2pinfo(dev);
827         struct adapter *adapter = pi->adapter;
828         unsigned int fidx, iq, fid_bit = 0;
829         struct filter_entry *f;
830         unsigned int chip_ver;
831         uint8_t bitoff[16] = {0};
832         int ret;
833
834         if (is_hashfilter(adapter) && fs->cap)
835                 return cxgbe_set_hash_filter(dev, fs, ctx);
836
837         if (filter_id >= adapter->tids.nftids)
838                 return -ERANGE;
839
840         chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip);
841
842         ret = validate_filter(adapter, fs);
843         if (ret)
844                 return ret;
845
846         /*
847          * Ensure filter id is aligned on the 4 slot boundary for IPv6
848          * maskfull filters.
849          */
850         if (fs->type)
851                 filter_id &= ~(0x3);
852
853         ret = is_filter_set(&adapter->tids, filter_id, fs->type);
854         if (ret)
855                 return -EBUSY;
856
857         iq = get_filter_steerq(dev, fs);
858
859         /*
860          * IPv6 filters occupy four slots and must be aligned on four-slot
861          * boundaries for T5. On T6, IPv6 filters occupy two-slots and
862          * must be aligned on two-slot boundaries.
863          *
864          * IPv4 filters only occupy a single slot and have no alignment
865          * requirements but writing a new IPv4 filter into the middle
866          * of an existing IPv6 filter requires clearing the old IPv6
867          * filter.
868          */
869         if (fs->type == FILTER_TYPE_IPV4) { /* IPv4 */
870                 /*
871                  * For T6, If our IPv4 filter isn't being written to a
872                  * multiple of two filter index and there's an IPv6
873                  * filter at the multiple of 2 base slot, then we need
874                  * to delete that IPv6 filter ...
875                  * For adapters below T6, IPv6 filter occupies 4 entries.
876                  */
877                 if (chip_ver < CHELSIO_T6)
878                         fidx = filter_id & ~0x3;
879                 else
880                         fidx = filter_id & ~0x1;
881
882                 if (fidx != filter_id && adapter->tids.ftid_tab[fidx].fs.type) {
883                         f = &adapter->tids.ftid_tab[fidx];
884                         if (f->valid)
885                                 return -EBUSY;
886                 }
887         } else { /* IPv6 */
888                 unsigned int max_filter_id;
889
890                 if (chip_ver < CHELSIO_T6) {
891                         /*
892                          * Ensure that the IPv6 filter is aligned on a
893                          * multiple of 4 boundary.
894                          */
895                         if (filter_id & 0x3)
896                                 return -EINVAL;
897
898                         max_filter_id = filter_id + 4;
899                 } else {
900                         /*
901                          * For T6, CLIP being enabled, IPv6 filter would occupy
902                          * 2 entries.
903                          */
904                         if (filter_id & 0x1)
905                                 return -EINVAL;
906
907                         max_filter_id = filter_id + 2;
908                 }
909
910                 /*
911                  * Check all except the base overlapping IPv4 filter
912                  * slots.
913                  */
914                 for (fidx = filter_id + 1; fidx < max_filter_id; fidx++) {
915                         f = &adapter->tids.ftid_tab[fidx];
916                         if (f->valid)
917                                 return -EBUSY;
918                 }
919         }
920
921         /*
922          * Check to make sure that provided filter index is not
923          * already in use by someone else
924          */
925         f = &adapter->tids.ftid_tab[filter_id];
926         if (f->valid)
927                 return -EBUSY;
928
929         fidx = adapter->tids.ftid_base + filter_id;
930         fid_bit = filter_id;
931         ret = cxgbe_set_ftid(&adapter->tids, fid_bit,
932                              fs->type ? FILTER_TYPE_IPV6 : FILTER_TYPE_IPV4);
933         if (ret)
934                 return ret;
935
936         /*
937          * Check to make sure the filter requested is writable ...
938          */
939         ret = writable_filter(f);
940         if (ret) {
941                 /* Clear the bits we have set above */
942                 cxgbe_clear_ftid(&adapter->tids, fid_bit,
943                                  fs->type ? FILTER_TYPE_IPV6 :
944                                             FILTER_TYPE_IPV4);
945                 return ret;
946         }
947
948         /*
949          * Allocate a clip table entry only if we have non-zero IPv6 address
950          */
951         if (chip_ver > CHELSIO_T5 && fs->type &&
952             memcmp(fs->val.lip, bitoff, sizeof(bitoff))) {
953                 f->clipt = cxgbe_clip_alloc(f->dev, (u32 *)&f->fs.val.lip);
954                 if (!f->clipt)
955                         goto free_tid;
956         }
957
958         /*
959          * Convert the filter specification into our internal format.
960          * We copy the PF/VF specification into the Outer VLAN field
961          * here so the rest of the code -- including the interface to
962          * the firmware -- doesn't have to constantly do these checks.
963          */
964         f->fs = *fs;
965         f->fs.iq = iq;
966         f->dev = dev;
967
968         /*
969          * Attempt to set the filter.  If we don't succeed, we clear
970          * it and return the failure.
971          */
972         f->ctx = ctx;
973         f->tid = fidx; /* Save the actual tid */
974         ret = set_filter_wr(dev, filter_id);
975         if (ret) {
976                 fid_bit = f->tid - adapter->tids.ftid_base;
977                 goto free_tid;
978         }
979
980         return ret;
981
982 free_tid:
983         cxgbe_clear_ftid(&adapter->tids, fid_bit,
984                          fs->type ? FILTER_TYPE_IPV6 :
985                                     FILTER_TYPE_IPV4);
986         clear_filter(f);
987         return ret;
988 }
989
990 /**
991  * Handle a Hash filter write reply.
992  */
993 void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)
994 {
995         struct tid_info *t = &adap->tids;
996         struct filter_entry *f;
997         struct filter_ctx *ctx = NULL;
998         unsigned int tid = GET_TID(rpl);
999         unsigned int ftid = G_TID_TID(G_AOPEN_ATID
1000                                       (be32_to_cpu(rpl->atid_status)));
1001         unsigned int status  = G_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
1002
1003         f = lookup_atid(t, ftid);
1004         if (!f) {
1005                 dev_warn(adap, "%s: could not find filter entry: %d\n",
1006                          __func__, ftid);
1007                 return;
1008         }
1009
1010         ctx = f->ctx;
1011         f->ctx = NULL;
1012
1013         switch (status) {
1014         case CPL_ERR_NONE: {
1015                 f->tid = tid;
1016                 f->pending = 0;  /* asynchronous setup completed */
1017                 f->valid = 1;
1018
1019                 cxgbe_insert_tid(t, f, f->tid, 0);
1020                 cxgbe_free_atid(t, ftid);
1021                 if (ctx) {
1022                         ctx->tid = f->tid;
1023                         ctx->result = 0;
1024                 }
1025                 if (f->fs.hitcnts)
1026                         set_tcb_field(adap, tid,
1027                                       W_TCB_TIMESTAMP,
1028                                       V_TCB_TIMESTAMP(M_TCB_TIMESTAMP) |
1029                                       V_TCB_T_RTT_TS_RECENT_AGE
1030                                               (M_TCB_T_RTT_TS_RECENT_AGE),
1031                                       V_TCB_TIMESTAMP(0ULL) |
1032                                       V_TCB_T_RTT_TS_RECENT_AGE(0ULL),
1033                                       1);
1034                 break;
1035         }
1036         default:
1037                 dev_warn(adap, "%s: filter creation failed with status = %u\n",
1038                          __func__, status);
1039
1040                 if (ctx) {
1041                         if (status == CPL_ERR_TCAM_FULL)
1042                                 ctx->result = -EAGAIN;
1043                         else
1044                                 ctx->result = -EINVAL;
1045                 }
1046
1047                 cxgbe_free_atid(t, ftid);
1048                 t4_os_free(f);
1049         }
1050
1051         if (ctx)
1052                 t4_complete(&ctx->completion);
1053 }
1054
1055 /**
1056  * Handle a LE-TCAM filter write/deletion reply.
1057  */
1058 void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
1059 {
1060         struct filter_entry *f = NULL;
1061         unsigned int tid = GET_TID(rpl);
1062         int idx, max_fidx = adap->tids.nftids;
1063
1064         /* Get the corresponding filter entry for this tid */
1065         if (adap->tids.ftid_tab) {
1066                 /* Check this in normal filter region */
1067                 idx = tid - adap->tids.ftid_base;
1068                 if (idx >= max_fidx)
1069                         return;
1070
1071                 f = &adap->tids.ftid_tab[idx];
1072                 if (f->tid != tid)
1073                         return;
1074         }
1075
1076         /* We found the filter entry for this tid */
1077         if (f) {
1078                 unsigned int ret = G_COOKIE(rpl->cookie);
1079                 struct filter_ctx *ctx;
1080
1081                 /*
1082                  * Pull off any filter operation context attached to the
1083                  * filter.
1084                  */
1085                 ctx = f->ctx;
1086                 f->ctx = NULL;
1087
1088                 if (ret == FW_FILTER_WR_FLT_ADDED) {
1089                         f->pending = 0;  /* asynchronous setup completed */
1090                         f->valid = 1;
1091                         if (ctx) {
1092                                 ctx->tid = f->tid;
1093                                 ctx->result = 0;
1094                         }
1095                 } else if (ret == FW_FILTER_WR_FLT_DELETED) {
1096                         /*
1097                          * Clear the filter when we get confirmation from the
1098                          * hardware that the filter has been deleted.
1099                          */
1100                         clear_filter(f);
1101                         if (ctx)
1102                                 ctx->result = 0;
1103                 } else {
1104                         /*
1105                          * Something went wrong.  Issue a warning about the
1106                          * problem and clear everything out.
1107                          */
1108                         dev_warn(adap, "filter %u setup failed with error %u\n",
1109                                  idx, ret);
1110                         clear_filter(f);
1111                         if (ctx)
1112                                 ctx->result = -EINVAL;
1113                 }
1114
1115                 if (ctx)
1116                         t4_complete(&ctx->completion);
1117         }
1118 }
1119
1120 /*
1121  * Retrieve the packet count for the specified filter.
1122  */
1123 int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,
1124                            u64 *c, int hash, bool get_byte)
1125 {
1126         struct filter_entry *f;
1127         unsigned int tcb_base, tcbaddr;
1128         int ret;
1129
1130         tcb_base = t4_read_reg(adapter, A_TP_CMM_TCB_BASE);
1131         if (is_hashfilter(adapter) && hash) {
1132                 if (fidx < adapter->tids.ntids) {
1133                         f = adapter->tids.tid_tab[fidx];
1134                         if (!f)
1135                                 return -EINVAL;
1136
1137                         if (is_t5(adapter->params.chip)) {
1138                                 *c = 0;
1139                                 return 0;
1140                         }
1141                         tcbaddr = tcb_base + (fidx * TCB_SIZE);
1142                         goto get_count;
1143                 } else {
1144                         return -ERANGE;
1145                 }
1146         } else {
1147                 if (fidx >= adapter->tids.nftids)
1148                         return -ERANGE;
1149
1150                 f = &adapter->tids.ftid_tab[fidx];
1151                 if (!f->valid)
1152                         return -EINVAL;
1153
1154                 tcbaddr = tcb_base + f->tid * TCB_SIZE;
1155         }
1156
1157         f = &adapter->tids.ftid_tab[fidx];
1158         if (!f->valid)
1159                 return -EINVAL;
1160
1161 get_count:
1162         if (is_t5(adapter->params.chip) || is_t6(adapter->params.chip)) {
1163                 /*
1164                  * For T5, the Filter Packet Hit Count is maintained as a
1165                  * 32-bit Big Endian value in the TCB field {timestamp}.
1166                  * Similar to the craziness above, instead of the filter hit
1167                  * count showing up at offset 20 ((W_TCB_TIMESTAMP == 5) *
1168                  * sizeof(u32)), it actually shows up at offset 24.  Whacky.
1169                  */
1170                 if (get_byte) {
1171                         unsigned int word_offset = 4;
1172                         __be64 be64_byte_count;
1173
1174                         t4_os_lock(&adapter->win0_lock);
1175                         ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
1176                                            tcbaddr +
1177                                            (word_offset * sizeof(__be32)),
1178                                            sizeof(be64_byte_count),
1179                                            &be64_byte_count,
1180                                            T4_MEMORY_READ);
1181                         t4_os_unlock(&adapter->win0_lock);
1182                         if (ret < 0)
1183                                 return ret;
1184                         *c = be64_to_cpu(be64_byte_count);
1185                 } else {
1186                         unsigned int word_offset = 6;
1187                         __be32 be32_count;
1188
1189                         t4_os_lock(&adapter->win0_lock);
1190                         ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
1191                                            tcbaddr +
1192                                            (word_offset * sizeof(__be32)),
1193                                            sizeof(be32_count), &be32_count,
1194                                            T4_MEMORY_READ);
1195                         t4_os_unlock(&adapter->win0_lock);
1196                         if (ret < 0)
1197                                 return ret;
1198                         *c = (u64)be32_to_cpu(be32_count);
1199                 }
1200         }
1201         return 0;
1202 }
1203
1204 /**
1205  * Handle a Hash filter delete reply.
1206  */
1207 void hash_del_filter_rpl(struct adapter *adap,
1208                          const struct cpl_abort_rpl_rss *rpl)
1209 {
1210         struct tid_info *t = &adap->tids;
1211         struct filter_entry *f;
1212         struct filter_ctx *ctx = NULL;
1213         unsigned int tid = GET_TID(rpl);
1214
1215         f = lookup_tid(t, tid);
1216         if (!f) {
1217                 dev_warn(adap, "%s: could not find filter entry: %u\n",
1218                          __func__, tid);
1219                 return;
1220         }
1221
1222         ctx = f->ctx;
1223         f->ctx = NULL;
1224
1225         f->valid = 0;
1226
1227         if (f->clipt)
1228                 cxgbe_clip_release(f->dev, f->clipt);
1229
1230         cxgbe_remove_tid(t, 0, tid, 0);
1231         t4_os_free(f);
1232
1233         if (ctx) {
1234                 ctx->result = 0;
1235                 t4_complete(&ctx->completion);
1236         }
1237 }