diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 131 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 294 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/l2t.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/l2t.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 279 |
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 | */ | ||
580 | struct 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 | */ | ||
614 | struct 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 | |||
658 | enum { | ||
659 | FILTER_PASS = 0, /* default */ | ||
660 | FILTER_DROP, | ||
661 | FILTER_SWITCH | ||
662 | }; | ||
663 | |||
664 | enum { | ||
665 | VLAN_NOCHANGE = 0, /* default */ | ||
666 | VLAN_REMOVE, | ||
667 | VLAN_INSERT, | ||
668 | VLAN_REWRITE | ||
669 | }; | ||
670 | |||
548 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) | 671 | static 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, | |||
701 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, | 824 | void 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); |
827 | void 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 | |||
831 | struct fw_filter_wr; | ||
832 | |||
704 | void t4_intr_enable(struct adapter *adapter); | 833 | void t4_intr_enable(struct adapter *adapter); |
705 | void t4_intr_disable(struct adapter *adapter); | 834 | void t4_intr_disable(struct adapter *adapter); |
706 | int t4_slow_intr_handler(struct adapter *adapter); | 835 | int 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, | |||
737 | void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, | 866 | void 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 | ||
869 | void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid); | ||
870 | |||
740 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, | 871 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, |
741 | const u8 *addr); | 872 | const u8 *addr); |
742 | int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | 873 | int 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 | */ | ||
184 | struct 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 | ||
326 | static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; | 350 | static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; |
327 | 351 | ||
352 | module_param(tp_vlan_pri_map, uint, 0644); | ||
353 | MODULE_PARM_DESC(tp_vlan_pri_map, "global compressed filter configuration"); | ||
354 | |||
328 | static struct dentry *cxgb4_debugfs_root; | 355 | static struct dentry *cxgb4_debugfs_root; |
329 | 356 | ||
330 | static LIST_HEAD(adapter_list); | 357 | static 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 | */ | ||
539 | static 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 | */ | ||
559 | static 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 | */ |
512 | static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, | 598 | static 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 | */ | ||
1082 | static 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 | */ | ||
1196 | static 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 | |||
986 | static inline int is_offload(const struct adapter *adap) | 1218 | static 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 | */ |
2211 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid) | 2443 | void 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); | |||
2362 | static int tid_init(struct tid_info *t) | 2594 | static 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 | */ | ||
3242 | static 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 | */ | ||
3256 | static 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 | |||
3002 | static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, | 3274 | static 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 | */ | ||
491 | struct 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 | */ | ||
510 | int 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 | |||
487 | struct l2t_data *t4_init_l2t(void) | 519 | struct 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 | ||
102 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); | 102 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); |
103 | struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d); | ||
104 | int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, | ||
105 | u8 port, u8 *eth_addr); | ||
103 | struct l2t_data *t4_init_l2t(void); | 106 | struct l2t_data *t4_init_l2t(void); |
104 | void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); | 107 | void 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 | */ |
112 | static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | 112 | void 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 | */ | ||
2279 | void 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 | ||
38 | enum 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 */ | ||
90 | enum 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 | |||
98 | struct 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 | |||
85 | struct fw_ulptx_wr { | 364 | struct fw_ulptx_wr { |
86 | __be32 op_to_compl; | 365 | __be32 op_to_compl; |
87 | __be32 flowid_len16; | 366 | __be32 flowid_len16; |