Skip to content

Commit 322d95f

Browse files
committed
Merge branch 'cxgb4-more-flower-offloads'
Rahul Lakkireddy says: ==================== cxgb4: enable more tc flower offload matches and actions This patch series enable more matches and actions for TC Flower Offload support on Chelsio adapters. Patch 1 enables matching on IP TOS. Patch 2 enables matching on VLAN TCI. Patch 3 adds support for action PASS. Patch 4 adds support for ETH-DMAC rewrite via TC-PEDIT action. Also, adds a check to assert that vlan/eth-dmac rewrite actions are valid only in combination with action egress redirect. Patch 5 introduces SMT ops for adding/removing entries from SMAC Table in HW in preparation for patch 6. Patch 6 adds support for ETH-SMAC rewrite via TC-PEDIT action. Patch 7 introduces fw_filter2_wr to support L3/L4 header rewrites in preparation for patch 8. Patch 8 adds support for rewrite on L3/L4 header fields via TC-PEDIT action. Supported fields for rewrite are: IPv4 src/dst address, IPv6 src/dst address, TCP/UDP sport/dport. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8900567 + 557ccbf commit 322d95f

File tree

11 files changed

+1068
-27
lines changed

11 files changed

+1068
-27
lines changed

drivers/net/ethernet/chelsio/cxgb4/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
66

7-
cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o \
7+
cxgb4-objs := cxgb4_main.o l2t.o smt.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o \
88
cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o \
99
cxgb4_ptp.o cxgb4_tc_flower.o cxgb4_cudbg.o \
1010
cudbg_common.o cudbg_lib.o

drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ struct adapter_params {
367367
unsigned int max_ird_adapter; /* Max read depth per adapter */
368368
bool fr_nsmr_tpte_wr_support; /* FW support for FR_NSMR_TPTE_WR */
369369
u8 fw_caps_support; /* 32-bit Port Capabilities */
370+
bool filter2_wr_support; /* FW support for FILTER2_WR */
370371

371372
/* MPS Buffer Group Map[per Port]. Bit i is set if buffer group i is
372373
* used by the Port
@@ -858,6 +859,7 @@ struct adapter {
858859
unsigned int clipt_start;
859860
unsigned int clipt_end;
860861
struct clip_tbl *clipt;
862+
struct smt_data *smt;
861863
struct cxgb4_uld_info *uld;
862864
void *uld_handle[CXGB4_ULD_MAX];
863865
unsigned int num_uld;
@@ -1063,10 +1065,19 @@ struct ch_filter_specification {
10631065
uint32_t newdmac:1; /* rewrite destination MAC address */
10641066
uint32_t newsmac:1; /* rewrite source MAC address */
10651067
uint32_t newvlan:2; /* rewrite VLAN Tag */
1068+
uint32_t nat_mode:3; /* specify NAT operation mode */
10661069
uint8_t dmac[ETH_ALEN]; /* new destination MAC address */
10671070
uint8_t smac[ETH_ALEN]; /* new source MAC address */
10681071
uint16_t vlan; /* VLAN Tag to insert */
10691072

1073+
u8 nat_lip[16]; /* local IP to use after NAT'ing */
1074+
u8 nat_fip[16]; /* foreign IP to use after NAT'ing */
1075+
u16 nat_lport; /* local port to use after NAT'ing */
1076+
u16 nat_fport; /* foreign port to use after NAT'ing */
1077+
1078+
/* reservation for future additions */
1079+
u8 rsvd[24];
1080+
10701081
/* Filter rule value/mask pairs.
10711082
*/
10721083
struct ch_filter_tuple val;
@@ -1086,6 +1097,10 @@ enum {
10861097
VLAN_REWRITE
10871098
};
10881099

1100+
enum {
1101+
NAT_MODE_ALL = 7, /* NAT on entire 4-tuple */
1102+
};
1103+
10891104
/* Host shadow copy of ingress filter entry. This is in host native format
10901105
* and doesn't match the ordering or bit order, etc. of the hardware of the
10911106
* firmware command. The use of bit-field structure elements is purely to
@@ -1098,9 +1113,9 @@ struct filter_entry {
10981113
u32 locked:1; /* filter is administratively locked */
10991114

11001115
u32 pending:1; /* filter action is pending firmware reply */
1101-
u32 smtidx:8; /* Source MAC Table index for smac */
11021116
struct filter_ctx *ctx; /* Caller's completion hook */
11031117
struct l2t_entry *l2t; /* Layer Two Table entry for dmac */
1118+
struct smt_entry *smt; /* Source Mac Table entry for smac */
11041119
struct net_device *dev; /* Associated net device */
11051120
u32 tid; /* This will store the actual tid */
11061121

drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c

Lines changed: 109 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434

3535
#include "cxgb4.h"
3636
#include "t4_regs.h"
37+
#include "t4_tcb.h"
3738
#include "l2t.h"
39+
#include "smt.h"
3840
#include "t4fw_api.h"
3941
#include "cxgb4_filter.h"
4042

@@ -311,7 +313,7 @@ static int del_filter_wr(struct adapter *adapter, int fidx)
311313
int set_filter_wr(struct adapter *adapter, int fidx)
312314
{
313315
struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
314-
struct fw_filter_wr *fwr;
316+
struct fw_filter2_wr *fwr;
315317
struct sk_buff *skb;
316318

317319
skb = alloc_skb(sizeof(*fwr), GFP_KERNEL);
@@ -332,6 +334,21 @@ int set_filter_wr(struct adapter *adapter, int fidx)
332334
}
333335
}
334336

337+
/* If the new filter requires loopback Source MAC rewriting then
338+
* we need to allocate a SMT entry for the filter.
339+
*/
340+
if (f->fs.newsmac) {
341+
f->smt = cxgb4_smt_alloc_switching(f->dev, f->fs.smac);
342+
if (!f->smt) {
343+
if (f->l2t) {
344+
cxgb4_l2t_release(f->l2t);
345+
f->l2t = NULL;
346+
}
347+
kfree_skb(skb);
348+
return -ENOMEM;
349+
}
350+
}
351+
335352
fwr = __skb_put_zero(skb, sizeof(*fwr));
336353

337354
/* It would be nice to put most of the following in t4_hw.c but most
@@ -342,7 +359,10 @@ int set_filter_wr(struct adapter *adapter, int fidx)
342359
* filter specification structure but for now it's easiest to simply
343360
* put this fairly direct code in line ...
344361
*/
345-
fwr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR));
362+
if (adapter->params.filter2_wr_support)
363+
fwr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER2_WR));
364+
else
365+
fwr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR));
346366
fwr->len16_pkd = htonl(FW_WR_LEN16_V(sizeof(*fwr) / 16));
347367
fwr->tid_to_iq =
348368
htonl(FW_FILTER_WR_TID_V(f->tid) |
@@ -357,7 +377,6 @@ int set_filter_wr(struct adapter *adapter, int fidx)
357377
FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) |
358378
FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) |
359379
FW_FILTER_WR_DMAC_V(f->fs.newdmac) |
360-
FW_FILTER_WR_SMAC_V(f->fs.newsmac) |
361380
FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT ||
362381
f->fs.newvlan == VLAN_REWRITE) |
363382
FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE ||
@@ -404,8 +423,18 @@ int set_filter_wr(struct adapter *adapter, int fidx)
404423
fwr->lpm = htons(f->fs.mask.lport);
405424
fwr->fp = htons(f->fs.val.fport);
406425
fwr->fpm = htons(f->fs.mask.fport);
407-
if (f->fs.newsmac)
408-
memcpy(fwr->sma, f->fs.smac, sizeof(fwr->sma));
426+
427+
if (adapter->params.filter2_wr_support) {
428+
fwr->natmode_to_ulp_type =
429+
FW_FILTER2_WR_ULP_TYPE_V(f->fs.nat_mode ?
430+
ULP_MODE_TCPDDP :
431+
ULP_MODE_NONE) |
432+
FW_FILTER2_WR_NATMODE_V(f->fs.nat_mode);
433+
memcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));
434+
memcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));
435+
fwr->newlport = htons(f->fs.nat_lport);
436+
fwr->newfport = htons(f->fs.nat_fport);
437+
}
409438

410439
/* Mark the filter as "pending" and ship off the Filter Work Request.
411440
* When we get the Work Request Reply we'll clear the pending status.
@@ -463,6 +492,9 @@ void clear_filter(struct adapter *adap, struct filter_entry *f)
463492
if (f->l2t)
464493
cxgb4_l2t_release(f->l2t);
465494

495+
if (f->smt)
496+
cxgb4_smt_release(f->smt);
497+
466498
/* The zeroing of the filter rule below clears the filter valid,
467499
* pending, locked flags, l2t pointer, etc. so it's all we need for
468500
* this operation.
@@ -757,6 +789,62 @@ int cxgb4_del_filter(struct net_device *dev, int filter_id)
757789
return ret;
758790
}
759791

792+
static int set_tcb_field(struct adapter *adap, struct filter_entry *f,
793+
unsigned int ftid, u16 word, u64 mask, u64 val,
794+
int no_reply)
795+
{
796+
struct cpl_set_tcb_field *req;
797+
struct sk_buff *skb;
798+
799+
skb = alloc_skb(sizeof(struct cpl_set_tcb_field), GFP_ATOMIC);
800+
if (!skb)
801+
return -ENOMEM;
802+
803+
req = (struct cpl_set_tcb_field *)__skb_put(skb, sizeof(*req));
804+
memset(req, 0, sizeof(*req));
805+
INIT_TP_WR_CPL(req, CPL_SET_TCB_FIELD, ftid);
806+
req->reply_ctrl = htons(REPLY_CHAN_V(0) |
807+
QUEUENO_V(adap->sge.fw_evtq.abs_id) |
808+
NO_REPLY_V(no_reply));
809+
req->word_cookie = htons(TCB_WORD_V(word) | TCB_COOKIE_V(ftid));
810+
req->mask = cpu_to_be64(mask);
811+
req->val = cpu_to_be64(val);
812+
set_wr_txq(skb, CPL_PRIORITY_CONTROL, f->fs.val.iport & 0x3);
813+
t4_ofld_send(adap, skb);
814+
return 0;
815+
}
816+
817+
/* Set one of the t_flags bits in the TCB.
818+
*/
819+
static int set_tcb_tflag(struct adapter *adap, struct filter_entry *f,
820+
unsigned int ftid, unsigned int bit_pos,
821+
unsigned int val, int no_reply)
822+
{
823+
return set_tcb_field(adap, f, ftid, TCB_T_FLAGS_W, 1ULL << bit_pos,
824+
(unsigned long long)val << bit_pos, no_reply);
825+
}
826+
827+
static int configure_filter_smac(struct adapter *adap, struct filter_entry *f)
828+
{
829+
int err;
830+
831+
/* do a set-tcb for smac-sel and CWR bit.. */
832+
err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
833+
if (err)
834+
goto smac_err;
835+
836+
err = set_tcb_field(adap, f, f->tid, TCB_SMAC_SEL_W,
837+
TCB_SMAC_SEL_V(TCB_SMAC_SEL_M),
838+
TCB_SMAC_SEL_V(f->smt->idx), 1);
839+
if (!err)
840+
return 0;
841+
842+
smac_err:
843+
dev_err(adap->pdev_dev, "filter %u smac config failed with error %u\n",
844+
f->tid, err);
845+
return err;
846+
}
847+
760848
/* Handle a filter write/deletion reply. */
761849
void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
762850
{
@@ -795,19 +883,23 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
795883
clear_filter(adap, f);
796884
if (ctx)
797885
ctx->result = 0;
798-
} else if (ret == FW_FILTER_WR_SMT_TBL_FULL) {
799-
dev_err(adap->pdev_dev, "filter %u setup failed due to full SMT\n",
800-
idx);
801-
clear_filter(adap, f);
802-
if (ctx)
803-
ctx->result = -ENOMEM;
804886
} else if (ret == FW_FILTER_WR_FLT_ADDED) {
805-
f->smtidx = (be64_to_cpu(rpl->oldval) >> 24) & 0xff;
806-
f->pending = 0; /* asynchronous setup completed */
807-
f->valid = 1;
808-
if (ctx) {
809-
ctx->result = 0;
810-
ctx->tid = idx;
887+
int err = 0;
888+
889+
if (f->fs.newsmac)
890+
err = configure_filter_smac(adap, f);
891+
892+
if (!err) {
893+
f->pending = 0; /* async setup completed */
894+
f->valid = 1;
895+
if (ctx) {
896+
ctx->result = 0;
897+
ctx->tid = idx;
898+
}
899+
} else {
900+
clear_filter(adap, f);
901+
if (ctx)
902+
ctx->result = err;
811903
}
812904
} else {
813905
/* Something went wrong. Issue a warning about the

drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "cxgb4_debugfs.h"
7878
#include "clip_tbl.h"
7979
#include "l2t.h"
80+
#include "smt.h"
8081
#include "sched.h"
8182
#include "cxgb4_tc_u32.h"
8283
#include "cxgb4_tc_flower.h"
@@ -563,6 +564,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
563564
const struct cpl_l2t_write_rpl *p = (void *)rsp;
564565

565566
do_l2t_write_rpl(q->adap, p);
567+
} else if (opcode == CPL_SMT_WRITE_RPL) {
568+
const struct cpl_smt_write_rpl *p = (void *)rsp;
569+
570+
do_smt_write_rpl(q->adap, p);
566571
} else if (opcode == CPL_SET_TCB_RPL) {
567572
const struct cpl_set_tcb_rpl *p = (void *)rsp;
568573

@@ -3905,6 +3910,16 @@ static int adap_init0(struct adapter *adap)
39053910
1, params, val);
39063911
adap->params.fr_nsmr_tpte_wr_support = (ret == 0 && val[0] != 0);
39073912

3913+
/* See if FW supports FW_FILTER2 work request */
3914+
if (is_t4(adap->params.chip)) {
3915+
adap->params.filter2_wr_support = 0;
3916+
} else {
3917+
params[0] = FW_PARAM_DEV(FILTER2_WR);
3918+
ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
3919+
1, params, val);
3920+
adap->params.filter2_wr_support = (ret == 0 && val[0] != 0);
3921+
}
3922+
39083923
/*
39093924
* Get device capabilities so we can determine what resources we need
39103925
* to manage.
@@ -4641,6 +4656,7 @@ static void free_some_resources(struct adapter *adapter)
46414656
{
46424657
unsigned int i;
46434658

4659+
kvfree(adapter->smt);
46444660
kvfree(adapter->l2t);
46454661
t4_cleanup_sched(adapter);
46464662
kvfree(adapter->tids.tid_tab);
@@ -5067,6 +5083,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
50675083
*/
50685084
cfg_queues(adapter);
50695085

5086+
adapter->smt = t4_init_smt();
5087+
if (!adapter->smt) {
5088+
/* We tolerate a lack of SMT, giving up some functionality */
5089+
dev_warn(&pdev->dev, "could not allocate SMT, continuing\n");
5090+
}
5091+
50705092
adapter->l2t = t4_init_l2t(adapter->l2t_start, adapter->l2t_end);
50715093
if (!adapter->l2t) {
50725094
/* We tolerate a lack of L2T, giving up some functionality */

0 commit comments

Comments
 (0)