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