aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-12-10 04:30:52 -0500
committerRoland Dreier <roland@purestorage.com>2012-12-19 12:28:19 -0500
commitf2b7e78dbc79e09fc1164b226adc03ed91a326cb (patch)
treef1ec25c2d5e09e89d6ef46e1e55676654cbfe357 /drivers
parent5bd665f28db2b04a8d6fe277342479906fc60b62 (diff)
cxgb4: Add T4 filter support
The T4 architecture is capable of filtering ingress packets at line rate using the rule in TCAM. If packet hits a rule in the TCAM then it can be either dropped or passed to the receive queues based on a rule settings. This patch adds framework for managing filters and to use T4's filter capabilities. It constructs a Firmware Filter Work Request which writes the filter at a specified index to get the work done. It hosts shadow copy of ingress filter entry to check field size limitations and save memory in the case where the filter table is large. Signed-off-by: Vipul Pandya <vipul@chelsio.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h131
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c294
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c32
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.h3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c22
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h279
8 files changed, 757 insertions, 7 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 378988b5709a..24ce797ddbbd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -545,6 +545,129 @@ struct adapter {
545 spinlock_t stats_lock; 545 spinlock_t stats_lock;
546}; 546};
547 547
548/* Defined bit width of user definable filter tuples
549 */
550#define ETHTYPE_BITWIDTH 16
551#define FRAG_BITWIDTH 1
552#define MACIDX_BITWIDTH 9
553#define FCOE_BITWIDTH 1
554#define IPORT_BITWIDTH 3
555#define MATCHTYPE_BITWIDTH 3
556#define PROTO_BITWIDTH 8
557#define TOS_BITWIDTH 8
558#define PF_BITWIDTH 8
559#define VF_BITWIDTH 8
560#define IVLAN_BITWIDTH 16
561#define OVLAN_BITWIDTH 16
562
563/* Filter matching rules. These consist of a set of ingress packet field
564 * (value, mask) tuples. The associated ingress packet field matches the
565 * tuple when ((field & mask) == value). (Thus a wildcard "don't care" field
566 * rule can be constructed by specifying a tuple of (0, 0).) A filter rule
567 * matches an ingress packet when all of the individual individual field
568 * matching rules are true.
569 *
570 * Partial field masks are always valid, however, while it may be easy to
571 * understand their meanings for some fields (e.g. IP address to match a
572 * subnet), for others making sensible partial masks is less intuitive (e.g.
573 * MPS match type) ...
574 *
575 * Most of the following data structures are modeled on T4 capabilities.
576 * Drivers for earlier chips use the subsets which make sense for those chips.
577 * We really need to come up with a hardware-independent mechanism to
578 * represent hardware filter capabilities ...
579 */
580struct ch_filter_tuple {
581 /* Compressed header matching field rules. The TP_VLAN_PRI_MAP
582 * register selects which of these fields will participate in the
583 * filter match rules -- up to a maximum of 36 bits. Because
584 * TP_VLAN_PRI_MAP is a global register, all filters must use the same
585 * set of fields.
586 */
587 uint32_t ethtype:ETHTYPE_BITWIDTH; /* Ethernet type */
588 uint32_t frag:FRAG_BITWIDTH; /* IP fragmentation header */
589 uint32_t ivlan_vld:1; /* inner VLAN valid */
590 uint32_t ovlan_vld:1; /* outer VLAN valid */
591 uint32_t pfvf_vld:1; /* PF/VF valid */
592 uint32_t macidx:MACIDX_BITWIDTH; /* exact match MAC index */
593 uint32_t fcoe:FCOE_BITWIDTH; /* FCoE packet */
594 uint32_t iport:IPORT_BITWIDTH; /* ingress port */
595 uint32_t matchtype:MATCHTYPE_BITWIDTH; /* MPS match type */
596 uint32_t proto:PROTO_BITWIDTH; /* protocol type */
597 uint32_t tos:TOS_BITWIDTH; /* TOS/Traffic Type */
598 uint32_t pf:PF_BITWIDTH; /* PCI-E PF ID */
599 uint32_t vf:VF_BITWIDTH; /* PCI-E VF ID */
600 uint32_t ivlan:IVLAN_BITWIDTH; /* inner VLAN */
601 uint32_t ovlan:OVLAN_BITWIDTH; /* outer VLAN */
602
603 /* Uncompressed header matching field rules. These are always
604 * available for field rules.
605 */
606 uint8_t lip[16]; /* local IP address (IPv4 in [3:0]) */
607 uint8_t fip[16]; /* foreign IP address (IPv4 in [3:0]) */
608 uint16_t lport; /* local port */
609 uint16_t fport; /* foreign port */
610};
611
612/* A filter ioctl command.
613 */
614struct ch_filter_specification {
615 /* Administrative fields for filter.
616 */
617 uint32_t hitcnts:1; /* count filter hits in TCB */
618 uint32_t prio:1; /* filter has priority over active/server */
619
620 /* Fundamental filter typing. This is the one element of filter
621 * matching that doesn't exist as a (value, mask) tuple.
622 */
623 uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */
624
625 /* Packet dispatch information. Ingress packets which match the
626 * filter rules will be dropped, passed to the host or switched back
627 * out as egress packets.
628 */
629 uint32_t action:2; /* drop, pass, switch */
630
631 uint32_t rpttid:1; /* report TID in RSS hash field */
632
633 uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */
634 uint32_t iq:10; /* ingress queue */
635
636 uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */
637 uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */
638 /* 1 => TCB contains IQ ID */
639
640 /* Switch proxy/rewrite fields. An ingress packet which matches a
641 * filter with "switch" set will be looped back out as an egress
642 * packet -- potentially with some Ethernet header rewriting.
643 */
644 uint32_t eport:2; /* egress port to switch packet out */
645 uint32_t newdmac:1; /* rewrite destination MAC address */
646 uint32_t newsmac:1; /* rewrite source MAC address */
647 uint32_t newvlan:2; /* rewrite VLAN Tag */
648 uint8_t dmac[ETH_ALEN]; /* new destination MAC address */
649 uint8_t smac[ETH_ALEN]; /* new source MAC address */
650 uint16_t vlan; /* VLAN Tag to insert */
651
652 /* Filter rule value/mask pairs.
653 */
654 struct ch_filter_tuple val;
655 struct ch_filter_tuple mask;
656};
657
658enum {
659 FILTER_PASS = 0, /* default */
660 FILTER_DROP,
661 FILTER_SWITCH
662};
663
664enum {
665 VLAN_NOCHANGE = 0, /* default */
666 VLAN_REMOVE,
667 VLAN_INSERT,
668 VLAN_REWRITE
669};
670
548static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) 671static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
549{ 672{
550 return readl(adap->regs + reg_addr); 673 return readl(adap->regs + reg_addr);
@@ -701,6 +824,12 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd,
701void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, 824void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
702 unsigned int data_reg, const u32 *vals, 825 unsigned int data_reg, const u32 *vals,
703 unsigned int nregs, unsigned int start_idx); 826 unsigned int nregs, unsigned int start_idx);
827void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
828 unsigned int data_reg, u32 *vals, unsigned int nregs,
829 unsigned int start_idx);
830
831struct fw_filter_wr;
832
704void t4_intr_enable(struct adapter *adapter); 833void t4_intr_enable(struct adapter *adapter);
705void t4_intr_disable(struct adapter *adapter); 834void t4_intr_disable(struct adapter *adapter);
706int t4_slow_intr_handler(struct adapter *adapter); 835int t4_slow_intr_handler(struct adapter *adapter);
@@ -737,6 +866,8 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
737void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, 866void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
738 const unsigned short *alpha, const unsigned short *beta); 867 const unsigned short *alpha, const unsigned short *beta);
739 868
869void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid);
870
740void t4_wol_magic_enable(struct adapter *adap, unsigned int port, 871void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
741 const u8 *addr); 872 const u8 *addr);
742int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, 873int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index a27b4ae20f43..41537a403eef 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -175,6 +175,30 @@ enum {
175 MIN_FL_ENTRIES = 16 175 MIN_FL_ENTRIES = 16
176}; 176};
177 177
178/* Host shadow copy of ingress filter entry. This is in host native format
179 * and doesn't match the ordering or bit order, etc. of the hardware of the
180 * firmware command. The use of bit-field structure elements is purely to
181 * remind ourselves of the field size limitations and save memory in the case
182 * where the filter table is large.
183 */
184struct filter_entry {
185 /* Administrative fields for filter.
186 */
187 u32 valid:1; /* filter allocated and valid */
188 u32 locked:1; /* filter is administratively locked */
189
190 u32 pending:1; /* filter action is pending firmware reply */
191 u32 smtidx:8; /* Source MAC Table index for smac */
192 struct l2t_entry *l2t; /* Layer Two Table entry for dmac */
193
194 /* The filter itself. Most of this is a straight copy of information
195 * provided by the extended ioctl(). Some fields are translated to
196 * internal forms -- for instance the Ingress Queue ID passed in from
197 * the ioctl() is translated into the Absolute Ingress Queue ID.
198 */
199 struct ch_filter_specification fs;
200};
201
178#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ 202#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
179 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ 203 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
180 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) 204 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -325,6 +349,9 @@ enum {
325 349
326static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; 350static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT;
327 351
352module_param(tp_vlan_pri_map, uint, 0644);
353MODULE_PARM_DESC(tp_vlan_pri_map, "global compressed filter configuration");
354
328static struct dentry *cxgb4_debugfs_root; 355static struct dentry *cxgb4_debugfs_root;
329 356
330static LIST_HEAD(adapter_list); 357static LIST_HEAD(adapter_list);
@@ -506,8 +533,67 @@ static int link_start(struct net_device *dev)
506 return ret; 533 return ret;
507} 534}
508 535
509/* 536/* Clear a filter and release any of its resources that we own. This also
510 * Response queue handler for the FW event queue. 537 * clears the filter's "pending" status.
538 */
539static void clear_filter(struct adapter *adap, struct filter_entry *f)
540{
541 /* If the new or old filter have loopback rewriteing rules then we'll
542 * need to free any existing Layer Two Table (L2T) entries of the old
543 * filter rule. The firmware will handle freeing up any Source MAC
544 * Table (SMT) entries used for rewriting Source MAC Addresses in
545 * loopback rules.
546 */
547 if (f->l2t)
548 cxgb4_l2t_release(f->l2t);
549
550 /* The zeroing of the filter rule below clears the filter valid,
551 * pending, locked flags, l2t pointer, etc. so it's all we need for
552 * this operation.
553 */
554 memset(f, 0, sizeof(*f));
555}
556
557/* Handle a filter write/deletion reply.
558 */
559static void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
560{
561 unsigned int idx = GET_TID(rpl);
562 unsigned int nidx = idx - adap->tids.ftid_base;
563 unsigned int ret;
564 struct filter_entry *f;
565
566 if (idx >= adap->tids.ftid_base && nidx <
567 (adap->tids.nftids + adap->tids.nsftids)) {
568 idx = nidx;
569 ret = GET_TCB_COOKIE(rpl->cookie);
570 f = &adap->tids.ftid_tab[idx];
571
572 if (ret == FW_FILTER_WR_FLT_DELETED) {
573 /* Clear the filter when we get confirmation from the
574 * hardware that the filter has been deleted.
575 */
576 clear_filter(adap, f);
577 } else if (ret == FW_FILTER_WR_SMT_TBL_FULL) {
578 dev_err(adap->pdev_dev, "filter %u setup failed due to full SMT\n",
579 idx);
580 clear_filter(adap, f);
581 } else if (ret == FW_FILTER_WR_FLT_ADDED) {
582 f->smtidx = (be64_to_cpu(rpl->oldval) >> 24) & 0xff;
583 f->pending = 0; /* asynchronous setup completed */
584 f->valid = 1;
585 } else {
586 /* Something went wrong. Issue a warning about the
587 * problem and clear everything out.
588 */
589 dev_err(adap->pdev_dev, "filter %u setup failed with error %u\n",
590 idx, ret);
591 clear_filter(adap, f);
592 }
593 }
594}
595
596/* Response queue handler for the FW event queue.
511 */ 597 */
512static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, 598static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
513 const struct pkt_gl *gl) 599 const struct pkt_gl *gl)
@@ -542,6 +628,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
542 const struct cpl_l2t_write_rpl *p = (void *)rsp; 628 const struct cpl_l2t_write_rpl *p = (void *)rsp;
543 629
544 do_l2t_write_rpl(q->adap, p); 630 do_l2t_write_rpl(q->adap, p);
631 } else if (opcode == CPL_SET_TCB_RPL) {
632 const struct cpl_set_tcb_rpl *p = (void *)rsp;
633
634 filter_rpl(q->adap, p);
545 } else 635 } else
546 dev_err(q->adap->pdev_dev, 636 dev_err(q->adap->pdev_dev,
547 "unexpected CPL %#x on FW event queue\n", opcode); 637 "unexpected CPL %#x on FW event queue\n", opcode);
@@ -983,6 +1073,148 @@ static void t4_free_mem(void *addr)
983 kfree(addr); 1073 kfree(addr);
984} 1074}
985 1075
1076/* Send a Work Request to write the filter at a specified index. We construct
1077 * a Firmware Filter Work Request to have the work done and put the indicated
1078 * filter into "pending" mode which will prevent any further actions against
1079 * it till we get a reply from the firmware on the completion status of the
1080 * request.
1081 */
1082static int set_filter_wr(struct adapter *adapter, int fidx)
1083{
1084 struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
1085 struct sk_buff *skb;
1086 struct fw_filter_wr *fwr;
1087 unsigned int ftid;
1088
1089 /* If the new filter requires loopback Destination MAC and/or VLAN
1090 * rewriting then we need to allocate a Layer 2 Table (L2T) entry for
1091 * the filter.
1092 */
1093 if (f->fs.newdmac || f->fs.newvlan) {
1094 /* allocate L2T entry for new filter */
1095 f->l2t = t4_l2t_alloc_switching(adapter->l2t);
1096 if (f->l2t == NULL)
1097 return -EAGAIN;
1098 if (t4_l2t_set_switching(adapter, f->l2t, f->fs.vlan,
1099 f->fs.eport, f->fs.dmac)) {
1100 cxgb4_l2t_release(f->l2t);
1101 f->l2t = NULL;
1102 return -ENOMEM;
1103 }
1104 }
1105
1106 ftid = adapter->tids.ftid_base + fidx;
1107
1108 skb = alloc_skb(sizeof(*fwr), GFP_KERNEL | __GFP_NOFAIL);
1109 fwr = (struct fw_filter_wr *)__skb_put(skb, sizeof(*fwr));
1110 memset(fwr, 0, sizeof(*fwr));
1111
1112 /* It would be nice to put most of the following in t4_hw.c but most
1113 * of the work is translating the cxgbtool ch_filter_specification
1114 * into the Work Request and the definition of that structure is
1115 * currently in cxgbtool.h which isn't appropriate to pull into the
1116 * common code. We may eventually try to come up with a more neutral
1117 * filter specification structure but for now it's easiest to simply
1118 * put this fairly direct code in line ...
1119 */
1120 fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
1121 fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16));
1122 fwr->tid_to_iq =
1123 htonl(V_FW_FILTER_WR_TID(ftid) |
1124 V_FW_FILTER_WR_RQTYPE(f->fs.type) |
1125 V_FW_FILTER_WR_NOREPLY(0) |
1126 V_FW_FILTER_WR_IQ(f->fs.iq));
1127 fwr->del_filter_to_l2tix =
1128 htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) |
1129 V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
1130 V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
1131 V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) |
1132 V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) |
1133 V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
1134 V_FW_FILTER_WR_DMAC(f->fs.newdmac) |
1135 V_FW_FILTER_WR_SMAC(f->fs.newsmac) |
1136 V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT ||
1137 f->fs.newvlan == VLAN_REWRITE) |
1138 V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE ||
1139 f->fs.newvlan == VLAN_REWRITE) |
1140 V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
1141 V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
1142 V_FW_FILTER_WR_PRIO(f->fs.prio) |
1143 V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
1144 fwr->ethtype = htons(f->fs.val.ethtype);
1145 fwr->ethtypem = htons(f->fs.mask.ethtype);
1146 fwr->frag_to_ovlan_vldm =
1147 (V_FW_FILTER_WR_FRAG(f->fs.val.frag) |
1148 V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) |
1149 V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) |
1150 V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) |
1151 V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) |
1152 V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));
1153 fwr->smac_sel = 0;
1154 fwr->rx_chan_rx_rpl_iq =
1155 htons(V_FW_FILTER_WR_RX_CHAN(0) |
1156 V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id));
1157 fwr->maci_to_matchtypem =
1158 htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |
1159 V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |
1160 V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) |
1161 V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) |
1162 V_FW_FILTER_WR_PORT(f->fs.val.iport) |
1163 V_FW_FILTER_WR_PORTM(f->fs.mask.iport) |
1164 V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) |
1165 V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype));
1166 fwr->ptcl = f->fs.val.proto;
1167 fwr->ptclm = f->fs.mask.proto;
1168 fwr->ttyp = f->fs.val.tos;
1169 fwr->ttypm = f->fs.mask.tos;
1170 fwr->ivlan = htons(f->fs.val.ivlan);
1171 fwr->ivlanm = htons(f->fs.mask.ivlan);
1172 fwr->ovlan = htons(f->fs.val.ovlan);
1173 fwr->ovlanm = htons(f->fs.mask.ovlan);
1174 memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
1175 memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));
1176 memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));
1177 memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm));
1178 fwr->lp = htons(f->fs.val.lport);
1179 fwr->lpm = htons(f->fs.mask.lport);
1180 fwr->fp = htons(f->fs.val.fport);
1181 fwr->fpm = htons(f->fs.mask.fport);
1182 if (f->fs.newsmac)
1183 memcpy(fwr->sma, f->fs.smac, sizeof(fwr->sma));
1184
1185 /* Mark the filter as "pending" and ship off the Filter Work Request.
1186 * When we get the Work Request Reply we'll clear the pending status.
1187 */
1188 f->pending = 1;
1189 set_wr_txq(skb, CPL_PRIORITY_CONTROL, f->fs.val.iport & 0x3);
1190 t4_ofld_send(adapter, skb);
1191 return 0;
1192}
1193
1194/* Delete the filter at a specified index.
1195 */
1196static int del_filter_wr(struct adapter *adapter, int fidx)
1197{
1198 struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
1199 struct sk_buff *skb;
1200 struct fw_filter_wr *fwr;
1201 unsigned int len, ftid;
1202
1203 len = sizeof(*fwr);
1204 ftid = adapter->tids.ftid_base + fidx;
1205
1206 skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL);
1207 fwr = (struct fw_filter_wr *)__skb_put(skb, len);
1208 t4_mk_filtdelwr(ftid, fwr, adapter->sge.fw_evtq.abs_id);
1209
1210 /* Mark the filter as "pending" and ship off the Filter Work Request.
1211 * When we get the Work Request Reply we'll clear the pending status.
1212 */
1213 f->pending = 1;
1214 t4_mgmt_tx(adapter, skb);
1215 return 0;
1216}
1217
986static inline int is_offload(const struct adapter *adap) 1218static inline int is_offload(const struct adapter *adap)
987{ 1219{
988 return adap->params.offload; 1220 return adap->params.offload;
@@ -2195,7 +2427,7 @@ int cxgb4_alloc_atid(struct tid_info *t, void *data)
2195 if (t->afree) { 2427 if (t->afree) {
2196 union aopen_entry *p = t->afree; 2428 union aopen_entry *p = t->afree;
2197 2429
2198 atid = p - t->atid_tab; 2430 atid = (p - t->atid_tab) + t->atid_base;
2199 t->afree = p->next; 2431 t->afree = p->next;
2200 p->data = data; 2432 p->data = data;
2201 t->atids_in_use++; 2433 t->atids_in_use++;
@@ -2210,7 +2442,7 @@ EXPORT_SYMBOL(cxgb4_alloc_atid);
2210 */ 2442 */
2211void cxgb4_free_atid(struct tid_info *t, unsigned int atid) 2443void cxgb4_free_atid(struct tid_info *t, unsigned int atid)
2212{ 2444{
2213 union aopen_entry *p = &t->atid_tab[atid]; 2445 union aopen_entry *p = &t->atid_tab[atid - t->atid_base];
2214 2446
2215 spin_lock_bh(&t->atid_lock); 2447 spin_lock_bh(&t->atid_lock);
2216 p->next = t->afree; 2448 p->next = t->afree;
@@ -2362,11 +2594,16 @@ EXPORT_SYMBOL(cxgb4_remove_tid);
2362static int tid_init(struct tid_info *t) 2594static int tid_init(struct tid_info *t)
2363{ 2595{
2364 size_t size; 2596 size_t size;
2597 unsigned int stid_bmap_size;
2365 unsigned int natids = t->natids; 2598 unsigned int natids = t->natids;
2366 2599
2367 size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) + 2600 stid_bmap_size = BITS_TO_LONGS(t->nstids);
2601 size = t->ntids * sizeof(*t->tid_tab) +
2602 natids * sizeof(*t->atid_tab) +
2368 t->nstids * sizeof(*t->stid_tab) + 2603 t->nstids * sizeof(*t->stid_tab) +
2369 BITS_TO_LONGS(t->nstids) * sizeof(long); 2604 stid_bmap_size * sizeof(long) +
2605 t->nftids * sizeof(*t->ftid_tab);
2606
2370 t->tid_tab = t4_alloc_mem(size); 2607 t->tid_tab = t4_alloc_mem(size);
2371 if (!t->tid_tab) 2608 if (!t->tid_tab)
2372 return -ENOMEM; 2609 return -ENOMEM;
@@ -2374,6 +2611,7 @@ static int tid_init(struct tid_info *t)
2374 t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; 2611 t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
2375 t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; 2612 t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
2376 t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids]; 2613 t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids];
2614 t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size];
2377 spin_lock_init(&t->stid_lock); 2615 spin_lock_init(&t->stid_lock);
2378 spin_lock_init(&t->atid_lock); 2616 spin_lock_init(&t->atid_lock);
2379 2617
@@ -2999,6 +3237,40 @@ static int cxgb_close(struct net_device *dev)
2999 return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); 3237 return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false);
3000} 3238}
3001 3239
3240/* Return an error number if the indicated filter isn't writable ...
3241 */
3242static int writable_filter(struct filter_entry *f)
3243{
3244 if (f->locked)
3245 return -EPERM;
3246 if (f->pending)
3247 return -EBUSY;
3248
3249 return 0;
3250}
3251
3252/* Delete the filter at the specified index (if valid). The checks for all
3253 * the common problems with doing this like the filter being locked, currently
3254 * pending in another operation, etc.
3255 */
3256static int delete_filter(struct adapter *adapter, unsigned int fidx)
3257{
3258 struct filter_entry *f;
3259 int ret;
3260
3261 if (fidx >= adapter->tids.nftids)
3262 return -EINVAL;
3263
3264 f = &adapter->tids.ftid_tab[fidx];
3265 ret = writable_filter(f);
3266 if (ret)
3267 return ret;
3268 if (f->valid)
3269 return del_filter_wr(adapter, fidx);
3270
3271 return 0;
3272}
3273
3002static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, 3274static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
3003 struct rtnl_link_stats64 *ns) 3275 struct rtnl_link_stats64 *ns)
3004{ 3276{
@@ -4661,6 +4933,16 @@ static void remove_one(struct pci_dev *pdev)
4661 if (adapter->debugfs_root) 4933 if (adapter->debugfs_root)
4662 debugfs_remove_recursive(adapter->debugfs_root); 4934 debugfs_remove_recursive(adapter->debugfs_root);
4663 4935
4936 /* If we allocated filters, free up state associated with any
4937 * valid filters ...
4938 */
4939 if (adapter->tids.ftid_tab) {
4940 struct filter_entry *f = &adapter->tids.ftid_tab[0];
4941 for (i = 0; i < adapter->tids.nftids; i++, f++)
4942 if (f->valid)
4943 clear_filter(adapter, f);
4944 }
4945
4664 if (adapter->flags & FULL_INIT_DONE) 4946 if (adapter->flags & FULL_INIT_DONE)
4665 cxgb_down(adapter); 4947 cxgb_down(adapter);
4666 4948
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 39bec73ff87c..59a61332b78c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -97,7 +97,9 @@ struct tid_info {
97 97
98 union aopen_entry *atid_tab; 98 union aopen_entry *atid_tab;
99 unsigned int natids; 99 unsigned int natids;
100 unsigned int atid_base;
100 101
102 struct filter_entry *ftid_tab;
101 unsigned int nftids; 103 unsigned int nftids;
102 unsigned int ftid_base; 104 unsigned int ftid_base;
103 unsigned int aftid_base; 105 unsigned int aftid_base;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 6ac77a62f361..29878098101e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -484,6 +484,38 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
484 handle_failed_resolution(adap, arpq); 484 handle_failed_resolution(adap, arpq);
485} 485}
486 486
487/* Allocate an L2T entry for use by a switching rule. Such need to be
488 * explicitly freed and while busy they are not on any hash chain, so normal
489 * address resolution updates do not see them.
490 */
491struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d)
492{
493 struct l2t_entry *e;
494
495 write_lock_bh(&d->lock);
496 e = alloc_l2e(d);
497 if (e) {
498 spin_lock(&e->lock); /* avoid race with t4_l2t_free */
499 e->state = L2T_STATE_SWITCHING;
500 atomic_set(&e->refcnt, 1);
501 spin_unlock(&e->lock);
502 }
503 write_unlock_bh(&d->lock);
504 return e;
505}
506
507/* Sets/updates the contents of a switching L2T entry that has been allocated
508 * with an earlier call to @t4_l2t_alloc_switching.
509 */
510int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
511 u8 port, u8 *eth_addr)
512{
513 e->vlan = vlan;
514 e->lport = port;
515 memcpy(e->dmac, eth_addr, ETH_ALEN);
516 return write_l2e(adap, e, 0);
517}
518
487struct l2t_data *t4_init_l2t(void) 519struct l2t_data *t4_init_l2t(void)
488{ 520{
489 int i; 521 int i;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
index 02b31d0c6410..108c0f1fce1c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
@@ -100,6 +100,9 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
100 unsigned int priority); 100 unsigned int priority);
101 101
102void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); 102void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
103struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
104int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
105 u8 port, u8 *eth_addr);
103struct l2t_data *t4_init_l2t(void); 106struct l2t_data *t4_init_l2t(void);
104void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); 107void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
105 108
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 8d9c7547b070..22f3af5166bf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -109,7 +109,7 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
109 * Reads registers that are accessed indirectly through an address/data 109 * Reads registers that are accessed indirectly through an address/data
110 * register pair. 110 * register pair.
111 */ 111 */
112static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, 112void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
113 unsigned int data_reg, u32 *vals, 113 unsigned int data_reg, u32 *vals,
114 unsigned int nregs, unsigned int start_idx) 114 unsigned int nregs, unsigned int start_idx)
115{ 115{
@@ -2268,6 +2268,26 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
2268 return 0; 2268 return 0;
2269} 2269}
2270 2270
2271/* t4_mk_filtdelwr - create a delete filter WR
2272 * @ftid: the filter ID
2273 * @wr: the filter work request to populate
2274 * @qid: ingress queue to receive the delete notification
2275 *
2276 * Creates a filter work request to delete the supplied filter. If @qid is
2277 * negative the delete notification is suppressed.
2278 */
2279void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
2280{
2281 memset(wr, 0, sizeof(*wr));
2282 wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
2283 wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16));
2284 wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) |
2285 V_FW_FILTER_WR_NOREPLY(qid < 0));
2286 wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER);
2287 if (qid >= 0)
2288 wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid));
2289}
2290
2271#define INIT_CMD(var, cmd, rd_wr) do { \ 2291#define INIT_CMD(var, cmd, rd_wr) do { \
2272 (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \ 2292 (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \
2273 FW_CMD_REQUEST | FW_CMD_##rd_wr); \ 2293 FW_CMD_REQUEST | FW_CMD_##rd_wr); \
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index b760808fd6d9..99ff71764499 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -332,6 +332,7 @@ struct cpl_set_tcb_field {
332 __be16 word_cookie; 332 __be16 word_cookie;
333#define TCB_WORD(x) ((x) << 0) 333#define TCB_WORD(x) ((x) << 0)
334#define TCB_COOKIE(x) ((x) << 5) 334#define TCB_COOKIE(x) ((x) << 5)
335#define GET_TCB_COOKIE(x) (((x) >> 5) & 7)
335 __be64 mask; 336 __be64 mask;
336 __be64 val; 337 __be64 val;
337}; 338};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 0abc864cdd3a..e98b6fff2c96 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -35,6 +35,10 @@
35#ifndef _T4FW_INTERFACE_H_ 35#ifndef _T4FW_INTERFACE_H_
36#define _T4FW_INTERFACE_H_ 36#define _T4FW_INTERFACE_H_
37 37
38enum fw_ret_val {
39 FW_ENOEXEC = 8, /* Exec format error; inv microcode */
40};
41
38#define FW_T4VF_SGE_BASE_ADDR 0x0000 42#define FW_T4VF_SGE_BASE_ADDR 0x0000
39#define FW_T4VF_MPS_BASE_ADDR 0x0100 43#define FW_T4VF_MPS_BASE_ADDR 0x0100
40#define FW_T4VF_PL_BASE_ADDR 0x0200 44#define FW_T4VF_PL_BASE_ADDR 0x0200
@@ -82,6 +86,281 @@ struct fw_wr_hdr {
82 86
83#define HW_TPL_FR_MT_PR_IV_P_FC 0X32B 87#define HW_TPL_FR_MT_PR_IV_P_FC 0X32B
84 88
89/* filter wr reply code in cookie in CPL_SET_TCB_RPL */
90enum fw_filter_wr_cookie {
91 FW_FILTER_WR_SUCCESS,
92 FW_FILTER_WR_FLT_ADDED,
93 FW_FILTER_WR_FLT_DELETED,
94 FW_FILTER_WR_SMT_TBL_FULL,
95 FW_FILTER_WR_EINVAL,
96};
97
98struct fw_filter_wr {
99 __be32 op_pkd;
100 __be32 len16_pkd;
101 __be64 r3;
102 __be32 tid_to_iq;
103 __be32 del_filter_to_l2tix;
104 __be16 ethtype;
105 __be16 ethtypem;
106 __u8 frag_to_ovlan_vldm;
107 __u8 smac_sel;
108 __be16 rx_chan_rx_rpl_iq;
109 __be32 maci_to_matchtypem;
110 __u8 ptcl;
111 __u8 ptclm;
112 __u8 ttyp;
113 __u8 ttypm;
114 __be16 ivlan;
115 __be16 ivlanm;
116 __be16 ovlan;
117 __be16 ovlanm;
118 __u8 lip[16];
119 __u8 lipm[16];
120 __u8 fip[16];
121 __u8 fipm[16];
122 __be16 lp;
123 __be16 lpm;
124 __be16 fp;
125 __be16 fpm;
126 __be16 r7;
127 __u8 sma[6];
128};
129
130#define S_FW_FILTER_WR_TID 12
131#define M_FW_FILTER_WR_TID 0xfffff
132#define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID)
133#define G_FW_FILTER_WR_TID(x) \
134 (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID)
135
136#define S_FW_FILTER_WR_RQTYPE 11
137#define M_FW_FILTER_WR_RQTYPE 0x1
138#define V_FW_FILTER_WR_RQTYPE(x) ((x) << S_FW_FILTER_WR_RQTYPE)
139#define G_FW_FILTER_WR_RQTYPE(x) \
140 (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE)
141#define F_FW_FILTER_WR_RQTYPE V_FW_FILTER_WR_RQTYPE(1U)
142
143#define S_FW_FILTER_WR_NOREPLY 10
144#define M_FW_FILTER_WR_NOREPLY 0x1
145#define V_FW_FILTER_WR_NOREPLY(x) ((x) << S_FW_FILTER_WR_NOREPLY)
146#define G_FW_FILTER_WR_NOREPLY(x) \
147 (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY)
148#define F_FW_FILTER_WR_NOREPLY V_FW_FILTER_WR_NOREPLY(1U)
149
150#define S_FW_FILTER_WR_IQ 0
151#define M_FW_FILTER_WR_IQ 0x3ff
152#define V_FW_FILTER_WR_IQ(x) ((x) << S_FW_FILTER_WR_IQ)
153#define G_FW_FILTER_WR_IQ(x) \
154 (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ)
155
156#define S_FW_FILTER_WR_DEL_FILTER 31
157#define M_FW_FILTER_WR_DEL_FILTER 0x1
158#define V_FW_FILTER_WR_DEL_FILTER(x) ((x) << S_FW_FILTER_WR_DEL_FILTER)
159#define G_FW_FILTER_WR_DEL_FILTER(x) \
160 (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER)
161#define F_FW_FILTER_WR_DEL_FILTER V_FW_FILTER_WR_DEL_FILTER(1U)
162
163#define S_FW_FILTER_WR_RPTTID 25
164#define M_FW_FILTER_WR_RPTTID 0x1
165#define V_FW_FILTER_WR_RPTTID(x) ((x) << S_FW_FILTER_WR_RPTTID)
166#define G_FW_FILTER_WR_RPTTID(x) \
167 (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID)
168#define F_FW_FILTER_WR_RPTTID V_FW_FILTER_WR_RPTTID(1U)
169
170#define S_FW_FILTER_WR_DROP 24
171#define M_FW_FILTER_WR_DROP 0x1
172#define V_FW_FILTER_WR_DROP(x) ((x) << S_FW_FILTER_WR_DROP)
173#define G_FW_FILTER_WR_DROP(x) \
174 (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP)
175#define F_FW_FILTER_WR_DROP V_FW_FILTER_WR_DROP(1U)
176
177#define S_FW_FILTER_WR_DIRSTEER 23
178#define M_FW_FILTER_WR_DIRSTEER 0x1
179#define V_FW_FILTER_WR_DIRSTEER(x) ((x) << S_FW_FILTER_WR_DIRSTEER)
180#define G_FW_FILTER_WR_DIRSTEER(x) \
181 (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER)
182#define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U)
183
184#define S_FW_FILTER_WR_MASKHASH 22
185#define M_FW_FILTER_WR_MASKHASH 0x1
186#define V_FW_FILTER_WR_MASKHASH(x) ((x) << S_FW_FILTER_WR_MASKHASH)
187#define G_FW_FILTER_WR_MASKHASH(x) \
188 (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH)
189#define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U)
190
191#define S_FW_FILTER_WR_DIRSTEERHASH 21
192#define M_FW_FILTER_WR_DIRSTEERHASH 0x1
193#define V_FW_FILTER_WR_DIRSTEERHASH(x) ((x) << S_FW_FILTER_WR_DIRSTEERHASH)
194#define G_FW_FILTER_WR_DIRSTEERHASH(x) \
195 (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH)
196#define F_FW_FILTER_WR_DIRSTEERHASH V_FW_FILTER_WR_DIRSTEERHASH(1U)
197
198#define S_FW_FILTER_WR_LPBK 20
199#define M_FW_FILTER_WR_LPBK 0x1
200#define V_FW_FILTER_WR_LPBK(x) ((x) << S_FW_FILTER_WR_LPBK)
201#define G_FW_FILTER_WR_LPBK(x) \
202 (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK)
203#define F_FW_FILTER_WR_LPBK V_FW_FILTER_WR_LPBK(1U)
204
205#define S_FW_FILTER_WR_DMAC 19
206#define M_FW_FILTER_WR_DMAC 0x1
207#define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC)
208#define G_FW_FILTER_WR_DMAC(x) \
209 (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC)
210#define F_FW_FILTER_WR_DMAC V_FW_FILTER_WR_DMAC(1U)
211
212#define S_FW_FILTER_WR_SMAC 18
213#define M_FW_FILTER_WR_SMAC 0x1
214#define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC)
215#define G_FW_FILTER_WR_SMAC(x) \
216 (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC)
217#define F_FW_FILTER_WR_SMAC V_FW_FILTER_WR_SMAC(1U)
218
219#define S_FW_FILTER_WR_INSVLAN 17
220#define M_FW_FILTER_WR_INSVLAN 0x1
221#define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN)
222#define G_FW_FILTER_WR_INSVLAN(x) \
223 (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN)
224#define F_FW_FILTER_WR_INSVLAN V_FW_FILTER_WR_INSVLAN(1U)
225
226#define S_FW_FILTER_WR_RMVLAN 16
227#define M_FW_FILTER_WR_RMVLAN 0x1
228#define V_FW_FILTER_WR_RMVLAN(x) ((x) << S_FW_FILTER_WR_RMVLAN)
229#define G_FW_FILTER_WR_RMVLAN(x) \
230 (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN)
231#define F_FW_FILTER_WR_RMVLAN V_FW_FILTER_WR_RMVLAN(1U)
232
233#define S_FW_FILTER_WR_HITCNTS 15
234#define M_FW_FILTER_WR_HITCNTS 0x1
235#define V_FW_FILTER_WR_HITCNTS(x) ((x) << S_FW_FILTER_WR_HITCNTS)
236#define G_FW_FILTER_WR_HITCNTS(x) \
237 (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS)
238#define F_FW_FILTER_WR_HITCNTS V_FW_FILTER_WR_HITCNTS(1U)
239
240#define S_FW_FILTER_WR_TXCHAN 13
241#define M_FW_FILTER_WR_TXCHAN 0x3
242#define V_FW_FILTER_WR_TXCHAN(x) ((x) << S_FW_FILTER_WR_TXCHAN)
243#define G_FW_FILTER_WR_TXCHAN(x) \
244 (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN)
245
246#define S_FW_FILTER_WR_PRIO 12
247#define M_FW_FILTER_WR_PRIO 0x1
248#define V_FW_FILTER_WR_PRIO(x) ((x) << S_FW_FILTER_WR_PRIO)
249#define G_FW_FILTER_WR_PRIO(x) \
250 (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO)
251#define F_FW_FILTER_WR_PRIO V_FW_FILTER_WR_PRIO(1U)
252
253#define S_FW_FILTER_WR_L2TIX 0
254#define M_FW_FILTER_WR_L2TIX 0xfff
255#define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX)
256#define G_FW_FILTER_WR_L2TIX(x) \
257 (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX)
258
259#define S_FW_FILTER_WR_FRAG 7
260#define M_FW_FILTER_WR_FRAG 0x1
261#define V_FW_FILTER_WR_FRAG(x) ((x) << S_FW_FILTER_WR_FRAG)
262#define G_FW_FILTER_WR_FRAG(x) \
263 (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG)
264#define F_FW_FILTER_WR_FRAG V_FW_FILTER_WR_FRAG(1U)
265
266#define S_FW_FILTER_WR_FRAGM 6
267#define M_FW_FILTER_WR_FRAGM 0x1
268#define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM)
269#define G_FW_FILTER_WR_FRAGM(x) \
270 (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM)
271#define F_FW_FILTER_WR_FRAGM V_FW_FILTER_WR_FRAGM(1U)
272
273#define S_FW_FILTER_WR_IVLAN_VLD 5
274#define M_FW_FILTER_WR_IVLAN_VLD 0x1
275#define V_FW_FILTER_WR_IVLAN_VLD(x) ((x) << S_FW_FILTER_WR_IVLAN_VLD)
276#define G_FW_FILTER_WR_IVLAN_VLD(x) \
277 (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD)
278#define F_FW_FILTER_WR_IVLAN_VLD V_FW_FILTER_WR_IVLAN_VLD(1U)
279
280#define S_FW_FILTER_WR_OVLAN_VLD 4
281#define M_FW_FILTER_WR_OVLAN_VLD 0x1
282#define V_FW_FILTER_WR_OVLAN_VLD(x) ((x) << S_FW_FILTER_WR_OVLAN_VLD)
283#define G_FW_FILTER_WR_OVLAN_VLD(x) \
284 (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD)
285#define F_FW_FILTER_WR_OVLAN_VLD V_FW_FILTER_WR_OVLAN_VLD(1U)
286
287#define S_FW_FILTER_WR_IVLAN_VLDM 3
288#define M_FW_FILTER_WR_IVLAN_VLDM 0x1
289#define V_FW_FILTER_WR_IVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_IVLAN_VLDM)
290#define G_FW_FILTER_WR_IVLAN_VLDM(x) \
291 (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM)
292#define F_FW_FILTER_WR_IVLAN_VLDM V_FW_FILTER_WR_IVLAN_VLDM(1U)
293
294#define S_FW_FILTER_WR_OVLAN_VLDM 2
295#define M_FW_FILTER_WR_OVLAN_VLDM 0x1
296#define V_FW_FILTER_WR_OVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_OVLAN_VLDM)
297#define G_FW_FILTER_WR_OVLAN_VLDM(x) \
298 (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM)
299#define F_FW_FILTER_WR_OVLAN_VLDM V_FW_FILTER_WR_OVLAN_VLDM(1U)
300
301#define S_FW_FILTER_WR_RX_CHAN 15
302#define M_FW_FILTER_WR_RX_CHAN 0x1
303#define V_FW_FILTER_WR_RX_CHAN(x) ((x) << S_FW_FILTER_WR_RX_CHAN)
304#define G_FW_FILTER_WR_RX_CHAN(x) \
305 (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN)
306#define F_FW_FILTER_WR_RX_CHAN V_FW_FILTER_WR_RX_CHAN(1U)
307
308#define S_FW_FILTER_WR_RX_RPL_IQ 0
309#define M_FW_FILTER_WR_RX_RPL_IQ 0x3ff
310#define V_FW_FILTER_WR_RX_RPL_IQ(x) ((x) << S_FW_FILTER_WR_RX_RPL_IQ)
311#define G_FW_FILTER_WR_RX_RPL_IQ(x) \
312 (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ)
313
314#define S_FW_FILTER_WR_MACI 23
315#define M_FW_FILTER_WR_MACI 0x1ff
316#define V_FW_FILTER_WR_MACI(x) ((x) << S_FW_FILTER_WR_MACI)
317#define G_FW_FILTER_WR_MACI(x) \
318 (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI)
319
320#define S_FW_FILTER_WR_MACIM 14
321#define M_FW_FILTER_WR_MACIM 0x1ff
322#define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM)
323#define G_FW_FILTER_WR_MACIM(x) \
324 (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM)
325
326#define S_FW_FILTER_WR_FCOE 13
327#define M_FW_FILTER_WR_FCOE 0x1
328#define V_FW_FILTER_WR_FCOE(x) ((x) << S_FW_FILTER_WR_FCOE)
329#define G_FW_FILTER_WR_FCOE(x) \
330 (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE)
331#define F_FW_FILTER_WR_FCOE V_FW_FILTER_WR_FCOE(1U)
332
333#define S_FW_FILTER_WR_FCOEM 12
334#define M_FW_FILTER_WR_FCOEM 0x1
335#define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM)
336#define G_FW_FILTER_WR_FCOEM(x) \
337 (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM)
338#define F_FW_FILTER_WR_FCOEM V_FW_FILTER_WR_FCOEM(1U)
339
340#define S_FW_FILTER_WR_PORT 9
341#define M_FW_FILTER_WR_PORT 0x7
342#define V_FW_FILTER_WR_PORT(x) ((x) << S_FW_FILTER_WR_PORT)
343#define G_FW_FILTER_WR_PORT(x) \
344 (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT)
345
346#define S_FW_FILTER_WR_PORTM 6
347#define M_FW_FILTER_WR_PORTM 0x7
348#define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM)
349#define G_FW_FILTER_WR_PORTM(x) \
350 (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM)
351
352#define S_FW_FILTER_WR_MATCHTYPE 3
353#define M_FW_FILTER_WR_MATCHTYPE 0x7
354#define V_FW_FILTER_WR_MATCHTYPE(x) ((x) << S_FW_FILTER_WR_MATCHTYPE)
355#define G_FW_FILTER_WR_MATCHTYPE(x) \
356 (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE)
357
358#define S_FW_FILTER_WR_MATCHTYPEM 0
359#define M_FW_FILTER_WR_MATCHTYPEM 0x7
360#define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM)
361#define G_FW_FILTER_WR_MATCHTYPEM(x) \
362 (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM)
363
85struct fw_ulptx_wr { 364struct fw_ulptx_wr {
86 __be32 op_to_compl; 365 __be32 op_to_compl;
87 __be32 flowid_len16; 366 __be32 flowid_len16;