crypto/snow3g: add dynamic logging
[dpdk.git] / drivers / net / cxgbe / cxgbe_filter.c
index 7759b8a..7f0d380 100644 (file)
@@ -65,11 +65,28 @@ int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
 #define U(_mask, _field) \
        (!(fconf & (_mask)) && S(_field))
 
-       if (U(F_ETHERTYPE, ethtype) || U(F_PROTOCOL, proto))
+       if (U(F_PORT, iport) || U(F_ETHERTYPE, ethtype) || U(F_PROTOCOL, proto))
                return -EOPNOTSUPP;
 
 #undef S
 #undef U
+
+       /*
+        * If the user is requesting that the filter action loop
+        * matching packets back out one of our ports, make sure that
+        * the egress port is in range.
+        */
+       if (fs->action == FILTER_SWITCH &&
+           fs->eport >= adapter->params.nports)
+               return -ERANGE;
+
+       /*
+        * Don't allow various trivially obvious bogus out-of-range
+        * values ...
+        */
+       if (fs->val.iport >= adapter->params.nports)
+               return -ERANGE;
+
        return 0;
 }
 
@@ -117,6 +134,36 @@ int writable_filter(struct filter_entry *f)
        return 0;
 }
 
+/**
+ * Send CPL_SET_TCB_FIELD message
+ */
+static void set_tcb_field(struct adapter *adapter, unsigned int ftid,
+                         u16 word, u64 mask, u64 val, int no_reply)
+{
+       struct rte_mbuf *mbuf;
+       struct cpl_set_tcb_field *req;
+       struct sge_ctrl_txq *ctrlq;
+
+       ctrlq = &adapter->sge.ctrlq[0];
+       mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
+       WARN_ON(!mbuf);
+
+       mbuf->data_len = sizeof(*req);
+       mbuf->pkt_len = mbuf->data_len;
+
+       req = rte_pktmbuf_mtod(mbuf, struct cpl_set_tcb_field *);
+       memset(req, 0, sizeof(*req));
+       INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, ftid);
+       req->reply_ctrl = cpu_to_be16(V_REPLY_CHAN(0) |
+                                     V_QUEUENO(adapter->sge.fw_evtq.abs_id) |
+                                     V_NO_REPLY(no_reply));
+       req->word_cookie = cpu_to_be16(V_WORD(word) | V_COOKIE(ftid));
+       req->mask = cpu_to_be64(mask);
+       req->val = cpu_to_be64(val);
+
+       t4_mgmt_tx(ctrlq, mbuf);
+}
+
 /**
  * Build a CPL_SET_TCB_FIELD message as payload of a ULP_TX_PKT command.
  */
@@ -198,6 +245,9 @@ static u64 hash_filter_ntuple(const struct filter_entry *f)
        u64 ntuple = 0;
        u16 tcp_proto = IPPROTO_TCP; /* TCP Protocol Number */
 
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)f->fs.mask.iport << tp->port_shift;
+
        if (tp->protocol_shift >= 0) {
                if (!f->fs.val.proto)
                        ntuple |= (u64)tcp_proto << tp->protocol_shift;
@@ -378,6 +428,7 @@ static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,
        req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
                                V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
                                           << 1) |
+                               V_TX_CHAN(f->fs.eport) |
                                V_ULP_MODE(ULP_MODE_NONE) |
                                F_TCAM_BYPASS | F_NON_OFFLOAD);
        req->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));
@@ -386,7 +437,8 @@ static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,
                            F_T5_OPT_2_VALID |
                            F_RX_CHANNEL |
                            V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)));
+                                        (f->fs.dirsteer << 1)) |
+                           V_CCTRL_ECN(f->fs.action == FILTER_SWITCH));
 }
 
 /**
@@ -419,6 +471,7 @@ static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,
        req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
                                V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
                                           << 1) |
+                               V_TX_CHAN(f->fs.eport) |
                                V_ULP_MODE(ULP_MODE_NONE) |
                                F_TCAM_BYPASS | F_NON_OFFLOAD);
        req->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));
@@ -427,7 +480,8 @@ static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,
                            F_T5_OPT_2_VALID |
                            F_RX_CHANNEL |
                            V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)));
+                                        (f->fs.dirsteer << 1)) |
+                           V_CCTRL_ECN(f->fs.action == FILTER_SWITCH));
 }
 
 /**
@@ -625,7 +679,9 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
        fwr->del_filter_to_l2tix =
                cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
                            V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
+                           V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
                            V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
+                           V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
                            V_FW_FILTER_WR_PRIO(f->fs.prio));
        fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
        fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);
@@ -634,6 +690,9 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
                cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |
                            V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id
                                                     ));
+       fwr->maci_to_matchtypem =
+               cpu_to_be32(V_FW_FILTER_WR_PORT(f->fs.val.iport) |
+                           V_FW_FILTER_WR_PORTM(f->fs.mask.iport));
        fwr->ptcl = f->fs.val.proto;
        fwr->ptclm = f->fs.mask.proto;
        rte_memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
@@ -978,6 +1037,15 @@ void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)
                        ctx->tid = f->tid;
                        ctx->result = 0;
                }
+               if (f->fs.hitcnts)
+                       set_tcb_field(adap, tid,
+                                     W_TCB_TIMESTAMP,
+                                     V_TCB_TIMESTAMP(M_TCB_TIMESTAMP) |
+                                     V_TCB_T_RTT_TS_RECENT_AGE
+                                             (M_TCB_T_RTT_TS_RECENT_AGE),
+                                     V_TCB_TIMESTAMP(0ULL) |
+                                     V_TCB_T_RTT_TS_RECENT_AGE(0ULL),
+                                     1);
                break;
        }
        default:
@@ -1068,22 +1136,44 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
  * Retrieve the packet count for the specified filter.
  */
 int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,
-                          u64 *c, bool get_byte)
+                          u64 *c, int hash, bool get_byte)
 {
        struct filter_entry *f;
        unsigned int tcb_base, tcbaddr;
        int ret;
 
        tcb_base = t4_read_reg(adapter, A_TP_CMM_TCB_BASE);
-       if (fidx >= adapter->tids.nftids)
-               return -ERANGE;
+       if (is_hashfilter(adapter) && hash) {
+               if (fidx < adapter->tids.ntids) {
+                       f = adapter->tids.tid_tab[fidx];
+                       if (!f)
+                               return -EINVAL;
+
+                       if (is_t5(adapter->params.chip)) {
+                               *c = 0;
+                               return 0;
+                       }
+                       tcbaddr = tcb_base + (fidx * TCB_SIZE);
+                       goto get_count;
+               } else {
+                       return -ERANGE;
+               }
+       } else {
+               if (fidx >= adapter->tids.nftids)
+                       return -ERANGE;
+
+               f = &adapter->tids.ftid_tab[fidx];
+               if (!f->valid)
+                       return -EINVAL;
+
+               tcbaddr = tcb_base + f->tid * TCB_SIZE;
+       }
 
        f = &adapter->tids.ftid_tab[fidx];
        if (!f->valid)
                return -EINVAL;
 
-       tcbaddr = tcb_base + f->tid * TCB_SIZE;
-
+get_count:
        if (is_t5(adapter->params.chip) || is_t6(adapter->params.chip)) {
                /*
                 * For T5, the Filter Packet Hit Count is maintained as a