diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-21 19:40:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-21 19:40:26 -0500 |
commit | 184e2516614f7055d4c3a2e63fd8a3eb95fff6d6 (patch) | |
tree | 9822dd3cc97f8cfed3cbda6167818b60355cc7ec /drivers/net | |
parent | 0264405b84505f60ae00625f261e75a32c7ddf56 (diff) | |
parent | d72623b665d84b1e07fe43854e83387fce8dd134 (diff) |
Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
Pull more infiniband changes from Roland Dreier:
"Second batch of InfiniBand/RDMA changes for 3.8:
- cxgb4 changes to fix lookup engine hash collisions
- mlx4 changes to make flow steering usable
- fix to IPoIB to avoid pinning dst reference for too long"
* tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
RDMA/cxgb4: Fix bug for active and passive LE hash collision path
RDMA/cxgb4: Fix LE hash collision bug for passive open connection
RDMA/cxgb4: Fix LE hash collision bug for active open connection
mlx4_core: Allow choosing flow steering mode
mlx4_core: Adjustments to Flow Steering activation logic for SR-IOV
mlx4_core: Fix error flow in the flow steering wrapper
mlx4_core: Add QPN enforcement for flow steering rules set by VFs
cxgb4: Add LE hash collision bug fix path in LLD driver
cxgb4: Add T4 filter support
IPoIB: Call skb_dst_drop() once skb is enqueued for sending
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 136 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 459 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 23 | ||||
-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 | 66 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 37 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 418 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 115 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mcg.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 28 |
15 files changed, 1309 insertions, 59 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 378988b5709a..6db997c78a5f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #ifndef __CXGB4_H__ | 35 | #ifndef __CXGB4_H__ |
36 | #define __CXGB4_H__ | 36 | #define __CXGB4_H__ |
37 | 37 | ||
38 | #include "t4_hw.h" | ||
39 | |||
38 | #include <linux/bitops.h> | 40 | #include <linux/bitops.h> |
39 | #include <linux/cache.h> | 41 | #include <linux/cache.h> |
40 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
@@ -212,6 +214,8 @@ struct tp_err_stats { | |||
212 | struct tp_params { | 214 | struct tp_params { |
213 | unsigned int ntxchan; /* # of Tx channels */ | 215 | unsigned int ntxchan; /* # of Tx channels */ |
214 | unsigned int tre; /* log2 of core clocks per TP tick */ | 216 | unsigned int tre; /* log2 of core clocks per TP tick */ |
217 | unsigned short tx_modq_map; /* TX modulation scheduler queue to */ | ||
218 | /* channel map */ | ||
215 | 219 | ||
216 | uint32_t dack_re; /* DACK timer resolution */ | 220 | uint32_t dack_re; /* DACK timer resolution */ |
217 | unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ | 221 | unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ |
@@ -526,6 +530,7 @@ struct adapter { | |||
526 | struct net_device *port[MAX_NPORTS]; | 530 | struct net_device *port[MAX_NPORTS]; |
527 | u8 chan_map[NCHAN]; /* channel -> port map */ | 531 | u8 chan_map[NCHAN]; /* channel -> port map */ |
528 | 532 | ||
533 | u32 filter_mode; | ||
529 | unsigned int l2t_start; | 534 | unsigned int l2t_start; |
530 | unsigned int l2t_end; | 535 | unsigned int l2t_end; |
531 | struct l2t_data *l2t; | 536 | struct l2t_data *l2t; |
@@ -545,6 +550,129 @@ struct adapter { | |||
545 | spinlock_t stats_lock; | 550 | spinlock_t stats_lock; |
546 | }; | 551 | }; |
547 | 552 | ||
553 | /* Defined bit width of user definable filter tuples | ||
554 | */ | ||
555 | #define ETHTYPE_BITWIDTH 16 | ||
556 | #define FRAG_BITWIDTH 1 | ||
557 | #define MACIDX_BITWIDTH 9 | ||
558 | #define FCOE_BITWIDTH 1 | ||
559 | #define IPORT_BITWIDTH 3 | ||
560 | #define MATCHTYPE_BITWIDTH 3 | ||
561 | #define PROTO_BITWIDTH 8 | ||
562 | #define TOS_BITWIDTH 8 | ||
563 | #define PF_BITWIDTH 8 | ||
564 | #define VF_BITWIDTH 8 | ||
565 | #define IVLAN_BITWIDTH 16 | ||
566 | #define OVLAN_BITWIDTH 16 | ||
567 | |||
568 | /* Filter matching rules. These consist of a set of ingress packet field | ||
569 | * (value, mask) tuples. The associated ingress packet field matches the | ||
570 | * tuple when ((field & mask) == value). (Thus a wildcard "don't care" field | ||
571 | * rule can be constructed by specifying a tuple of (0, 0).) A filter rule | ||
572 | * matches an ingress packet when all of the individual individual field | ||
573 | * matching rules are true. | ||
574 | * | ||
575 | * Partial field masks are always valid, however, while it may be easy to | ||
576 | * understand their meanings for some fields (e.g. IP address to match a | ||
577 | * subnet), for others making sensible partial masks is less intuitive (e.g. | ||
578 | * MPS match type) ... | ||
579 | * | ||
580 | * Most of the following data structures are modeled on T4 capabilities. | ||
581 | * Drivers for earlier chips use the subsets which make sense for those chips. | ||
582 | * We really need to come up with a hardware-independent mechanism to | ||
583 | * represent hardware filter capabilities ... | ||
584 | */ | ||
585 | struct ch_filter_tuple { | ||
586 | /* Compressed header matching field rules. The TP_VLAN_PRI_MAP | ||
587 | * register selects which of these fields will participate in the | ||
588 | * filter match rules -- up to a maximum of 36 bits. Because | ||
589 | * TP_VLAN_PRI_MAP is a global register, all filters must use the same | ||
590 | * set of fields. | ||
591 | */ | ||
592 | uint32_t ethtype:ETHTYPE_BITWIDTH; /* Ethernet type */ | ||
593 | uint32_t frag:FRAG_BITWIDTH; /* IP fragmentation header */ | ||
594 | uint32_t ivlan_vld:1; /* inner VLAN valid */ | ||
595 | uint32_t ovlan_vld:1; /* outer VLAN valid */ | ||
596 | uint32_t pfvf_vld:1; /* PF/VF valid */ | ||
597 | uint32_t macidx:MACIDX_BITWIDTH; /* exact match MAC index */ | ||
598 | uint32_t fcoe:FCOE_BITWIDTH; /* FCoE packet */ | ||
599 | uint32_t iport:IPORT_BITWIDTH; /* ingress port */ | ||
600 | uint32_t matchtype:MATCHTYPE_BITWIDTH; /* MPS match type */ | ||
601 | uint32_t proto:PROTO_BITWIDTH; /* protocol type */ | ||
602 | uint32_t tos:TOS_BITWIDTH; /* TOS/Traffic Type */ | ||
603 | uint32_t pf:PF_BITWIDTH; /* PCI-E PF ID */ | ||
604 | uint32_t vf:VF_BITWIDTH; /* PCI-E VF ID */ | ||
605 | uint32_t ivlan:IVLAN_BITWIDTH; /* inner VLAN */ | ||
606 | uint32_t ovlan:OVLAN_BITWIDTH; /* outer VLAN */ | ||
607 | |||
608 | /* Uncompressed header matching field rules. These are always | ||
609 | * available for field rules. | ||
610 | */ | ||
611 | uint8_t lip[16]; /* local IP address (IPv4 in [3:0]) */ | ||
612 | uint8_t fip[16]; /* foreign IP address (IPv4 in [3:0]) */ | ||
613 | uint16_t lport; /* local port */ | ||
614 | uint16_t fport; /* foreign port */ | ||
615 | }; | ||
616 | |||
617 | /* A filter ioctl command. | ||
618 | */ | ||
619 | struct ch_filter_specification { | ||
620 | /* Administrative fields for filter. | ||
621 | */ | ||
622 | uint32_t hitcnts:1; /* count filter hits in TCB */ | ||
623 | uint32_t prio:1; /* filter has priority over active/server */ | ||
624 | |||
625 | /* Fundamental filter typing. This is the one element of filter | ||
626 | * matching that doesn't exist as a (value, mask) tuple. | ||
627 | */ | ||
628 | uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */ | ||
629 | |||
630 | /* Packet dispatch information. Ingress packets which match the | ||
631 | * filter rules will be dropped, passed to the host or switched back | ||
632 | * out as egress packets. | ||
633 | */ | ||
634 | uint32_t action:2; /* drop, pass, switch */ | ||
635 | |||
636 | uint32_t rpttid:1; /* report TID in RSS hash field */ | ||
637 | |||
638 | uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */ | ||
639 | uint32_t iq:10; /* ingress queue */ | ||
640 | |||
641 | uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */ | ||
642 | uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */ | ||
643 | /* 1 => TCB contains IQ ID */ | ||
644 | |||
645 | /* Switch proxy/rewrite fields. An ingress packet which matches a | ||
646 | * filter with "switch" set will be looped back out as an egress | ||
647 | * packet -- potentially with some Ethernet header rewriting. | ||
648 | */ | ||
649 | uint32_t eport:2; /* egress port to switch packet out */ | ||
650 | uint32_t newdmac:1; /* rewrite destination MAC address */ | ||
651 | uint32_t newsmac:1; /* rewrite source MAC address */ | ||
652 | uint32_t newvlan:2; /* rewrite VLAN Tag */ | ||
653 | uint8_t dmac[ETH_ALEN]; /* new destination MAC address */ | ||
654 | uint8_t smac[ETH_ALEN]; /* new source MAC address */ | ||
655 | uint16_t vlan; /* VLAN Tag to insert */ | ||
656 | |||
657 | /* Filter rule value/mask pairs. | ||
658 | */ | ||
659 | struct ch_filter_tuple val; | ||
660 | struct ch_filter_tuple mask; | ||
661 | }; | ||
662 | |||
663 | enum { | ||
664 | FILTER_PASS = 0, /* default */ | ||
665 | FILTER_DROP, | ||
666 | FILTER_SWITCH | ||
667 | }; | ||
668 | |||
669 | enum { | ||
670 | VLAN_NOCHANGE = 0, /* default */ | ||
671 | VLAN_REMOVE, | ||
672 | VLAN_INSERT, | ||
673 | VLAN_REWRITE | ||
674 | }; | ||
675 | |||
548 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) | 676 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) |
549 | { | 677 | { |
550 | return readl(adap->regs + reg_addr); | 678 | return readl(adap->regs + reg_addr); |
@@ -701,6 +829,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, | 829 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, |
702 | unsigned int data_reg, const u32 *vals, | 830 | unsigned int data_reg, const u32 *vals, |
703 | unsigned int nregs, unsigned int start_idx); | 831 | unsigned int nregs, unsigned int start_idx); |
832 | void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | ||
833 | unsigned int data_reg, u32 *vals, unsigned int nregs, | ||
834 | unsigned int start_idx); | ||
835 | |||
836 | struct fw_filter_wr; | ||
837 | |||
704 | void t4_intr_enable(struct adapter *adapter); | 838 | void t4_intr_enable(struct adapter *adapter); |
705 | void t4_intr_disable(struct adapter *adapter); | 839 | void t4_intr_disable(struct adapter *adapter); |
706 | int t4_slow_intr_handler(struct adapter *adapter); | 840 | int t4_slow_intr_handler(struct adapter *adapter); |
@@ -737,6 +871,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, | 871 | void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, |
738 | const unsigned short *alpha, const unsigned short *beta); | 872 | const unsigned short *alpha, const unsigned short *beta); |
739 | 873 | ||
874 | void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid); | ||
875 | |||
740 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, | 876 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, |
741 | const u8 *addr); | 877 | const u8 *addr); |
742 | int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | 878 | 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..f0718e1a8369 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; |
@@ -2249,8 +2481,34 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data) | |||
2249 | } | 2481 | } |
2250 | EXPORT_SYMBOL(cxgb4_alloc_stid); | 2482 | EXPORT_SYMBOL(cxgb4_alloc_stid); |
2251 | 2483 | ||
2252 | /* | 2484 | /* Allocate a server filter TID and set it to the supplied value. |
2253 | * Release a server TID. | 2485 | */ |
2486 | int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data) | ||
2487 | { | ||
2488 | int stid; | ||
2489 | |||
2490 | spin_lock_bh(&t->stid_lock); | ||
2491 | if (family == PF_INET) { | ||
2492 | stid = find_next_zero_bit(t->stid_bmap, | ||
2493 | t->nstids + t->nsftids, t->nstids); | ||
2494 | if (stid < (t->nstids + t->nsftids)) | ||
2495 | __set_bit(stid, t->stid_bmap); | ||
2496 | else | ||
2497 | stid = -1; | ||
2498 | } else { | ||
2499 | stid = -1; | ||
2500 | } | ||
2501 | if (stid >= 0) { | ||
2502 | t->stid_tab[stid].data = data; | ||
2503 | stid += t->stid_base; | ||
2504 | t->stids_in_use++; | ||
2505 | } | ||
2506 | spin_unlock_bh(&t->stid_lock); | ||
2507 | return stid; | ||
2508 | } | ||
2509 | EXPORT_SYMBOL(cxgb4_alloc_sftid); | ||
2510 | |||
2511 | /* Release a server TID. | ||
2254 | */ | 2512 | */ |
2255 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) | 2513 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) |
2256 | { | 2514 | { |
@@ -2362,18 +2620,26 @@ EXPORT_SYMBOL(cxgb4_remove_tid); | |||
2362 | static int tid_init(struct tid_info *t) | 2620 | static int tid_init(struct tid_info *t) |
2363 | { | 2621 | { |
2364 | size_t size; | 2622 | size_t size; |
2623 | unsigned int stid_bmap_size; | ||
2365 | unsigned int natids = t->natids; | 2624 | unsigned int natids = t->natids; |
2366 | 2625 | ||
2367 | size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) + | 2626 | stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids); |
2627 | size = t->ntids * sizeof(*t->tid_tab) + | ||
2628 | natids * sizeof(*t->atid_tab) + | ||
2368 | t->nstids * sizeof(*t->stid_tab) + | 2629 | t->nstids * sizeof(*t->stid_tab) + |
2369 | BITS_TO_LONGS(t->nstids) * sizeof(long); | 2630 | t->nsftids * sizeof(*t->stid_tab) + |
2631 | stid_bmap_size * sizeof(long) + | ||
2632 | t->nftids * sizeof(*t->ftid_tab) + | ||
2633 | t->nsftids * sizeof(*t->ftid_tab); | ||
2634 | |||
2370 | t->tid_tab = t4_alloc_mem(size); | 2635 | t->tid_tab = t4_alloc_mem(size); |
2371 | if (!t->tid_tab) | 2636 | if (!t->tid_tab) |
2372 | return -ENOMEM; | 2637 | return -ENOMEM; |
2373 | 2638 | ||
2374 | t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; | 2639 | t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; |
2375 | t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; | 2640 | t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; |
2376 | t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids]; | 2641 | t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids]; |
2642 | t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; | ||
2377 | spin_lock_init(&t->stid_lock); | 2643 | spin_lock_init(&t->stid_lock); |
2378 | spin_lock_init(&t->atid_lock); | 2644 | spin_lock_init(&t->atid_lock); |
2379 | 2645 | ||
@@ -2388,7 +2654,7 @@ static int tid_init(struct tid_info *t) | |||
2388 | t->atid_tab[natids - 1].next = &t->atid_tab[natids]; | 2654 | t->atid_tab[natids - 1].next = &t->atid_tab[natids]; |
2389 | t->afree = t->atid_tab; | 2655 | t->afree = t->atid_tab; |
2390 | } | 2656 | } |
2391 | bitmap_zero(t->stid_bmap, t->nstids); | 2657 | bitmap_zero(t->stid_bmap, t->nstids + t->nsftids); |
2392 | return 0; | 2658 | return 0; |
2393 | } | 2659 | } |
2394 | 2660 | ||
@@ -2404,7 +2670,8 @@ static int tid_init(struct tid_info *t) | |||
2404 | * Returns <0 on error and one of the %NET_XMIT_* values on success. | 2670 | * Returns <0 on error and one of the %NET_XMIT_* values on success. |
2405 | */ | 2671 | */ |
2406 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, | 2672 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, |
2407 | __be32 sip, __be16 sport, unsigned int queue) | 2673 | __be32 sip, __be16 sport, __be16 vlan, |
2674 | unsigned int queue) | ||
2408 | { | 2675 | { |
2409 | unsigned int chan; | 2676 | unsigned int chan; |
2410 | struct sk_buff *skb; | 2677 | struct sk_buff *skb; |
@@ -2750,6 +3017,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) | |||
2750 | { | 3017 | { |
2751 | void *handle; | 3018 | void *handle; |
2752 | struct cxgb4_lld_info lli; | 3019 | struct cxgb4_lld_info lli; |
3020 | unsigned short i; | ||
2753 | 3021 | ||
2754 | lli.pdev = adap->pdev; | 3022 | lli.pdev = adap->pdev; |
2755 | lli.l2t = adap->l2t; | 3023 | lli.l2t = adap->l2t; |
@@ -2776,10 +3044,16 @@ static void uld_attach(struct adapter *adap, unsigned int uld) | |||
2776 | lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( | 3044 | lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( |
2777 | t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> | 3045 | t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> |
2778 | (adap->fn * 4)); | 3046 | (adap->fn * 4)); |
3047 | lli.filt_mode = adap->filter_mode; | ||
3048 | /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */ | ||
3049 | for (i = 0; i < NCHAN; i++) | ||
3050 | lli.tx_modq[i] = i; | ||
2779 | lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); | 3051 | lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); |
2780 | lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); | 3052 | lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); |
2781 | lli.fw_vers = adap->params.fw_vers; | 3053 | lli.fw_vers = adap->params.fw_vers; |
2782 | lli.dbfifo_int_thresh = dbfifo_int_thresh; | 3054 | lli.dbfifo_int_thresh = dbfifo_int_thresh; |
3055 | lli.sge_pktshift = adap->sge.pktshift; | ||
3056 | lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; | ||
2783 | 3057 | ||
2784 | handle = ulds[uld].add(&lli); | 3058 | handle = ulds[uld].add(&lli); |
2785 | if (IS_ERR(handle)) { | 3059 | if (IS_ERR(handle)) { |
@@ -2999,6 +3273,126 @@ static int cxgb_close(struct net_device *dev) | |||
2999 | return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); | 3273 | return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); |
3000 | } | 3274 | } |
3001 | 3275 | ||
3276 | /* Return an error number if the indicated filter isn't writable ... | ||
3277 | */ | ||
3278 | static int writable_filter(struct filter_entry *f) | ||
3279 | { | ||
3280 | if (f->locked) | ||
3281 | return -EPERM; | ||
3282 | if (f->pending) | ||
3283 | return -EBUSY; | ||
3284 | |||
3285 | return 0; | ||
3286 | } | ||
3287 | |||
3288 | /* Delete the filter at the specified index (if valid). The checks for all | ||
3289 | * the common problems with doing this like the filter being locked, currently | ||
3290 | * pending in another operation, etc. | ||
3291 | */ | ||
3292 | static int delete_filter(struct adapter *adapter, unsigned int fidx) | ||
3293 | { | ||
3294 | struct filter_entry *f; | ||
3295 | int ret; | ||
3296 | |||
3297 | if (fidx >= adapter->tids.nftids + adapter->tids.nsftids) | ||
3298 | return -EINVAL; | ||
3299 | |||
3300 | f = &adapter->tids.ftid_tab[fidx]; | ||
3301 | ret = writable_filter(f); | ||
3302 | if (ret) | ||
3303 | return ret; | ||
3304 | if (f->valid) | ||
3305 | return del_filter_wr(adapter, fidx); | ||
3306 | |||
3307 | return 0; | ||
3308 | } | ||
3309 | |||
3310 | int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, | ||
3311 | __be32 sip, __be16 sport, __be16 vlan, | ||
3312 | unsigned int queue, unsigned char port, unsigned char mask) | ||
3313 | { | ||
3314 | int ret; | ||
3315 | struct filter_entry *f; | ||
3316 | struct adapter *adap; | ||
3317 | int i; | ||
3318 | u8 *val; | ||
3319 | |||
3320 | adap = netdev2adap(dev); | ||
3321 | |||
3322 | /* Adjust stid to correct filter index */ | ||
3323 | stid -= adap->tids.nstids; | ||
3324 | stid += adap->tids.nftids; | ||
3325 | |||
3326 | /* Check to make sure the filter requested is writable ... | ||
3327 | */ | ||
3328 | f = &adap->tids.ftid_tab[stid]; | ||
3329 | ret = writable_filter(f); | ||
3330 | if (ret) | ||
3331 | return ret; | ||
3332 | |||
3333 | /* Clear out any old resources being used by the filter before | ||
3334 | * we start constructing the new filter. | ||
3335 | */ | ||
3336 | if (f->valid) | ||
3337 | clear_filter(adap, f); | ||
3338 | |||
3339 | /* Clear out filter specifications */ | ||
3340 | memset(&f->fs, 0, sizeof(struct ch_filter_specification)); | ||
3341 | f->fs.val.lport = cpu_to_be16(sport); | ||
3342 | f->fs.mask.lport = ~0; | ||
3343 | val = (u8 *)&sip; | ||
3344 | if ((val[0] | val[1] | val[2] | val[3]) != 0) { | ||
3345 | for (i = 0; i < 4; i++) { | ||
3346 | f->fs.val.lip[i] = val[i]; | ||
3347 | f->fs.mask.lip[i] = ~0; | ||
3348 | } | ||
3349 | if (adap->filter_mode & F_PORT) { | ||
3350 | f->fs.val.iport = port; | ||
3351 | f->fs.mask.iport = mask; | ||
3352 | } | ||
3353 | } | ||
3354 | |||
3355 | f->fs.dirsteer = 1; | ||
3356 | f->fs.iq = queue; | ||
3357 | /* Mark filter as locked */ | ||
3358 | f->locked = 1; | ||
3359 | f->fs.rpttid = 1; | ||
3360 | |||
3361 | ret = set_filter_wr(adap, stid); | ||
3362 | if (ret) { | ||
3363 | clear_filter(adap, f); | ||
3364 | return ret; | ||
3365 | } | ||
3366 | |||
3367 | return 0; | ||
3368 | } | ||
3369 | EXPORT_SYMBOL(cxgb4_create_server_filter); | ||
3370 | |||
3371 | int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, | ||
3372 | unsigned int queue, bool ipv6) | ||
3373 | { | ||
3374 | int ret; | ||
3375 | struct filter_entry *f; | ||
3376 | struct adapter *adap; | ||
3377 | |||
3378 | adap = netdev2adap(dev); | ||
3379 | |||
3380 | /* Adjust stid to correct filter index */ | ||
3381 | stid -= adap->tids.nstids; | ||
3382 | stid += adap->tids.nftids; | ||
3383 | |||
3384 | f = &adap->tids.ftid_tab[stid]; | ||
3385 | /* Unlock the filter */ | ||
3386 | f->locked = 0; | ||
3387 | |||
3388 | ret = delete_filter(adap, stid); | ||
3389 | if (ret) | ||
3390 | return ret; | ||
3391 | |||
3392 | return 0; | ||
3393 | } | ||
3394 | EXPORT_SYMBOL(cxgb4_remove_server_filter); | ||
3395 | |||
3002 | static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, | 3396 | static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, |
3003 | struct rtnl_link_stats64 *ns) | 3397 | struct rtnl_link_stats64 *ns) |
3004 | { | 3398 | { |
@@ -3245,6 +3639,34 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) | |||
3245 | v = t4_read_reg(adap, TP_PIO_DATA); | 3639 | v = t4_read_reg(adap, TP_PIO_DATA); |
3246 | t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); | 3640 | t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); |
3247 | 3641 | ||
3642 | /* first 4 Tx modulation queues point to consecutive Tx channels */ | ||
3643 | adap->params.tp.tx_modq_map = 0xE4; | ||
3644 | t4_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, | ||
3645 | V_TX_MOD_QUEUE_REQ_MAP(adap->params.tp.tx_modq_map)); | ||
3646 | |||
3647 | /* associate each Tx modulation queue with consecutive Tx channels */ | ||
3648 | v = 0x84218421; | ||
3649 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
3650 | &v, 1, A_TP_TX_SCHED_HDR); | ||
3651 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
3652 | &v, 1, A_TP_TX_SCHED_FIFO); | ||
3653 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
3654 | &v, 1, A_TP_TX_SCHED_PCMD); | ||
3655 | |||
3656 | #define T4_TX_MODQ_10G_WEIGHT_DEFAULT 16 /* in KB units */ | ||
3657 | if (is_offload(adap)) { | ||
3658 | t4_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, | ||
3659 | V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3660 | V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3661 | V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3662 | V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); | ||
3663 | t4_write_reg(adap, A_TP_TX_MOD_CHANNEL_WEIGHT, | ||
3664 | V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3665 | V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3666 | V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
3667 | V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); | ||
3668 | } | ||
3669 | |||
3248 | /* get basic stuff going */ | 3670 | /* get basic stuff going */ |
3249 | return t4_early_init(adap, adap->fn); | 3671 | return t4_early_init(adap, adap->fn); |
3250 | } | 3672 | } |
@@ -4035,6 +4457,10 @@ static int adap_init0(struct adapter *adap) | |||
4035 | for (j = 0; j < NCHAN; j++) | 4457 | for (j = 0; j < NCHAN; j++) |
4036 | adap->params.tp.tx_modq[j] = j; | 4458 | adap->params.tp.tx_modq[j] = j; |
4037 | 4459 | ||
4460 | t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
4461 | &adap->filter_mode, 1, | ||
4462 | TP_VLAN_PRI_MAP); | ||
4463 | |||
4038 | adap->flags |= FW_OK; | 4464 | adap->flags |= FW_OK; |
4039 | return 0; | 4465 | return 0; |
4040 | 4466 | ||
@@ -4661,6 +5087,17 @@ static void remove_one(struct pci_dev *pdev) | |||
4661 | if (adapter->debugfs_root) | 5087 | if (adapter->debugfs_root) |
4662 | debugfs_remove_recursive(adapter->debugfs_root); | 5088 | debugfs_remove_recursive(adapter->debugfs_root); |
4663 | 5089 | ||
5090 | /* If we allocated filters, free up state associated with any | ||
5091 | * valid filters ... | ||
5092 | */ | ||
5093 | if (adapter->tids.ftid_tab) { | ||
5094 | struct filter_entry *f = &adapter->tids.ftid_tab[0]; | ||
5095 | for (i = 0; i < (adapter->tids.nftids + | ||
5096 | adapter->tids.nsftids); i++, f++) | ||
5097 | if (f->valid) | ||
5098 | clear_filter(adapter, f); | ||
5099 | } | ||
5100 | |||
4664 | if (adapter->flags & FULL_INIT_DONE) | 5101 | if (adapter->flags & FULL_INIT_DONE) |
4665 | cxgb_down(adapter); | 5102 | cxgb_down(adapter); |
4666 | 5103 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 39bec73ff87c..e2bbc7f3e2de 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/cache.h> | 38 | #include <linux/cache.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
41 | #include <linux/inetdevice.h> | ||
41 | #include <linux/atomic.h> | 42 | #include <linux/atomic.h> |
42 | 43 | ||
43 | /* CPL message priority levels */ | 44 | /* CPL message priority levels */ |
@@ -97,7 +98,9 @@ struct tid_info { | |||
97 | 98 | ||
98 | union aopen_entry *atid_tab; | 99 | union aopen_entry *atid_tab; |
99 | unsigned int natids; | 100 | unsigned int natids; |
101 | unsigned int atid_base; | ||
100 | 102 | ||
103 | struct filter_entry *ftid_tab; | ||
101 | unsigned int nftids; | 104 | unsigned int nftids; |
102 | unsigned int ftid_base; | 105 | unsigned int ftid_base; |
103 | unsigned int aftid_base; | 106 | unsigned int aftid_base; |
@@ -129,7 +132,7 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid) | |||
129 | static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) | 132 | static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) |
130 | { | 133 | { |
131 | stid -= t->stid_base; | 134 | stid -= t->stid_base; |
132 | return stid < t->nstids ? t->stid_tab[stid].data : NULL; | 135 | return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL; |
133 | } | 136 | } |
134 | 137 | ||
135 | static inline void cxgb4_insert_tid(struct tid_info *t, void *data, | 138 | static inline void cxgb4_insert_tid(struct tid_info *t, void *data, |
@@ -141,6 +144,7 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data, | |||
141 | 144 | ||
142 | int cxgb4_alloc_atid(struct tid_info *t, void *data); | 145 | int cxgb4_alloc_atid(struct tid_info *t, void *data); |
143 | int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); | 146 | int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); |
147 | int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data); | ||
144 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid); | 148 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid); |
145 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); | 149 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); |
146 | void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); | 150 | void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); |
@@ -148,8 +152,14 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); | |||
148 | struct in6_addr; | 152 | struct in6_addr; |
149 | 153 | ||
150 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, | 154 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, |
151 | __be32 sip, __be16 sport, unsigned int queue); | 155 | __be32 sip, __be16 sport, __be16 vlan, |
152 | 156 | unsigned int queue); | |
157 | int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, | ||
158 | __be32 sip, __be16 sport, __be16 vlan, | ||
159 | unsigned int queue, | ||
160 | unsigned char port, unsigned char mask); | ||
161 | int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, | ||
162 | unsigned int queue, bool ipv6); | ||
153 | static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) | 163 | static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) |
154 | { | 164 | { |
155 | skb_set_queue_mapping(skb, (queue << 1) | prio); | 165 | skb_set_queue_mapping(skb, (queue << 1) | prio); |
@@ -221,9 +231,16 @@ struct cxgb4_lld_info { | |||
221 | unsigned int iscsi_iolen; /* iSCSI max I/O length */ | 231 | unsigned int iscsi_iolen; /* iSCSI max I/O length */ |
222 | unsigned short udb_density; /* # of user DB/page */ | 232 | unsigned short udb_density; /* # of user DB/page */ |
223 | unsigned short ucq_density; /* # of user CQs/page */ | 233 | unsigned short ucq_density; /* # of user CQs/page */ |
234 | unsigned short filt_mode; /* filter optional components */ | ||
235 | unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */ | ||
236 | /* scheduler queue */ | ||
224 | void __iomem *gts_reg; /* address of GTS register */ | 237 | void __iomem *gts_reg; /* address of GTS register */ |
225 | void __iomem *db_reg; /* address of kernel doorbell */ | 238 | void __iomem *db_reg; /* address of kernel doorbell */ |
226 | int dbfifo_int_thresh; /* doorbell fifo int threshold */ | 239 | int dbfifo_int_thresh; /* doorbell fifo int threshold */ |
240 | unsigned int sge_pktshift; /* Padding between CPL and */ | ||
241 | /* packet data */ | ||
242 | bool enable_fw_ofld_conn; /* Enable connection through fw */ | ||
243 | /* WR */ | ||
227 | }; | 244 | }; |
228 | 245 | ||
229 | struct cxgb4_uld_info { | 246 | struct cxgb4_uld_info { |
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..261d17703adc 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | |||
@@ -193,8 +193,24 @@ struct work_request_hdr { | |||
193 | __be64 wr_lo; | 193 | __be64 wr_lo; |
194 | }; | 194 | }; |
195 | 195 | ||
196 | /* wr_hi fields */ | ||
197 | #define S_WR_OP 24 | ||
198 | #define V_WR_OP(x) ((__u64)(x) << S_WR_OP) | ||
199 | |||
196 | #define WR_HDR struct work_request_hdr wr | 200 | #define WR_HDR struct work_request_hdr wr |
197 | 201 | ||
202 | /* option 0 fields */ | ||
203 | #define S_MSS_IDX 60 | ||
204 | #define M_MSS_IDX 0xF | ||
205 | #define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX) | ||
206 | #define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX) | ||
207 | |||
208 | /* option 2 fields */ | ||
209 | #define S_RSS_QUEUE 0 | ||
210 | #define M_RSS_QUEUE 0x3FF | ||
211 | #define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE) | ||
212 | #define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE) | ||
213 | |||
198 | struct cpl_pass_open_req { | 214 | struct cpl_pass_open_req { |
199 | WR_HDR; | 215 | WR_HDR; |
200 | union opcode_tid ot; | 216 | union opcode_tid ot; |
@@ -204,12 +220,14 @@ struct cpl_pass_open_req { | |||
204 | __be32 peer_ip; | 220 | __be32 peer_ip; |
205 | __be64 opt0; | 221 | __be64 opt0; |
206 | #define TX_CHAN(x) ((x) << 2) | 222 | #define TX_CHAN(x) ((x) << 2) |
223 | #define NO_CONG(x) ((x) << 4) | ||
207 | #define DELACK(x) ((x) << 5) | 224 | #define DELACK(x) ((x) << 5) |
208 | #define ULP_MODE(x) ((x) << 8) | 225 | #define ULP_MODE(x) ((x) << 8) |
209 | #define RCV_BUFSIZ(x) ((x) << 12) | 226 | #define RCV_BUFSIZ(x) ((x) << 12) |
210 | #define DSCP(x) ((x) << 22) | 227 | #define DSCP(x) ((x) << 22) |
211 | #define SMAC_SEL(x) ((u64)(x) << 28) | 228 | #define SMAC_SEL(x) ((u64)(x) << 28) |
212 | #define L2T_IDX(x) ((u64)(x) << 36) | 229 | #define L2T_IDX(x) ((u64)(x) << 36) |
230 | #define TCAM_BYPASS(x) ((u64)(x) << 48) | ||
213 | #define NAGLE(x) ((u64)(x) << 49) | 231 | #define NAGLE(x) ((u64)(x) << 49) |
214 | #define WND_SCALE(x) ((u64)(x) << 50) | 232 | #define WND_SCALE(x) ((u64)(x) << 50) |
215 | #define KEEP_ALIVE(x) ((u64)(x) << 54) | 233 | #define KEEP_ALIVE(x) ((u64)(x) << 54) |
@@ -247,8 +265,10 @@ struct cpl_pass_accept_rpl { | |||
247 | #define RSS_QUEUE_VALID (1 << 10) | 265 | #define RSS_QUEUE_VALID (1 << 10) |
248 | #define RX_COALESCE_VALID(x) ((x) << 11) | 266 | #define RX_COALESCE_VALID(x) ((x) << 11) |
249 | #define RX_COALESCE(x) ((x) << 12) | 267 | #define RX_COALESCE(x) ((x) << 12) |
268 | #define PACE(x) ((x) << 16) | ||
250 | #define TX_QUEUE(x) ((x) << 23) | 269 | #define TX_QUEUE(x) ((x) << 23) |
251 | #define RX_CHANNEL(x) ((x) << 26) | 270 | #define RX_CHANNEL(x) ((x) << 26) |
271 | #define CCTRL_ECN(x) ((x) << 27) | ||
252 | #define WND_SCALE_EN(x) ((x) << 28) | 272 | #define WND_SCALE_EN(x) ((x) << 28) |
253 | #define TSTAMPS_EN(x) ((x) << 29) | 273 | #define TSTAMPS_EN(x) ((x) << 29) |
254 | #define SACK_EN(x) ((x) << 30) | 274 | #define SACK_EN(x) ((x) << 30) |
@@ -292,6 +312,9 @@ struct cpl_pass_establish { | |||
292 | union opcode_tid ot; | 312 | union opcode_tid ot; |
293 | __be32 rsvd; | 313 | __be32 rsvd; |
294 | __be32 tos_stid; | 314 | __be32 tos_stid; |
315 | #define PASS_OPEN_TID(x) ((x) << 0) | ||
316 | #define PASS_OPEN_TOS(x) ((x) << 24) | ||
317 | #define GET_PASS_OPEN_TID(x) (((x) >> 0) & 0xFFFFFF) | ||
295 | #define GET_POPEN_TID(x) ((x) & 0xffffff) | 318 | #define GET_POPEN_TID(x) ((x) & 0xffffff) |
296 | #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff) | 319 | #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff) |
297 | __be16 mac_idx; | 320 | __be16 mac_idx; |
@@ -332,6 +355,7 @@ struct cpl_set_tcb_field { | |||
332 | __be16 word_cookie; | 355 | __be16 word_cookie; |
333 | #define TCB_WORD(x) ((x) << 0) | 356 | #define TCB_WORD(x) ((x) << 0) |
334 | #define TCB_COOKIE(x) ((x) << 5) | 357 | #define TCB_COOKIE(x) ((x) << 5) |
358 | #define GET_TCB_COOKIE(x) (((x) >> 5) & 7) | ||
335 | __be64 mask; | 359 | __be64 mask; |
336 | __be64 val; | 360 | __be64 val; |
337 | }; | 361 | }; |
@@ -536,6 +560,37 @@ struct cpl_rx_pkt { | |||
536 | __be16 err_vec; | 560 | __be16 err_vec; |
537 | }; | 561 | }; |
538 | 562 | ||
563 | /* rx_pkt.l2info fields */ | ||
564 | #define S_RX_ETHHDR_LEN 0 | ||
565 | #define M_RX_ETHHDR_LEN 0x1F | ||
566 | #define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN) | ||
567 | #define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN) | ||
568 | |||
569 | #define S_RX_MACIDX 8 | ||
570 | #define M_RX_MACIDX 0x1FF | ||
571 | #define V_RX_MACIDX(x) ((x) << S_RX_MACIDX) | ||
572 | #define G_RX_MACIDX(x) (((x) >> S_RX_MACIDX) & M_RX_MACIDX) | ||
573 | |||
574 | #define S_RXF_SYN 21 | ||
575 | #define V_RXF_SYN(x) ((x) << S_RXF_SYN) | ||
576 | #define F_RXF_SYN V_RXF_SYN(1U) | ||
577 | |||
578 | #define S_RX_CHAN 28 | ||
579 | #define M_RX_CHAN 0xF | ||
580 | #define V_RX_CHAN(x) ((x) << S_RX_CHAN) | ||
581 | #define G_RX_CHAN(x) (((x) >> S_RX_CHAN) & M_RX_CHAN) | ||
582 | |||
583 | /* rx_pkt.hdr_len fields */ | ||
584 | #define S_RX_TCPHDR_LEN 0 | ||
585 | #define M_RX_TCPHDR_LEN 0x3F | ||
586 | #define V_RX_TCPHDR_LEN(x) ((x) << S_RX_TCPHDR_LEN) | ||
587 | #define G_RX_TCPHDR_LEN(x) (((x) >> S_RX_TCPHDR_LEN) & M_RX_TCPHDR_LEN) | ||
588 | |||
589 | #define S_RX_IPHDR_LEN 6 | ||
590 | #define M_RX_IPHDR_LEN 0x3FF | ||
591 | #define V_RX_IPHDR_LEN(x) ((x) << S_RX_IPHDR_LEN) | ||
592 | #define G_RX_IPHDR_LEN(x) (((x) >> S_RX_IPHDR_LEN) & M_RX_IPHDR_LEN) | ||
593 | |||
539 | struct cpl_trace_pkt { | 594 | struct cpl_trace_pkt { |
540 | u8 opcode; | 595 | u8 opcode; |
541 | u8 intf; | 596 | u8 intf; |
@@ -634,6 +689,17 @@ struct cpl_fw6_msg { | |||
634 | /* cpl_fw6_msg.type values */ | 689 | /* cpl_fw6_msg.type values */ |
635 | enum { | 690 | enum { |
636 | FW6_TYPE_CMD_RPL = 0, | 691 | FW6_TYPE_CMD_RPL = 0, |
692 | FW6_TYPE_WR_RPL = 1, | ||
693 | FW6_TYPE_CQE = 2, | ||
694 | FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3, | ||
695 | }; | ||
696 | |||
697 | struct cpl_fw6_msg_ofld_connection_wr_rpl { | ||
698 | __u64 cookie; | ||
699 | __be32 tid; /* or atid in case of active failure */ | ||
700 | __u8 t_state; | ||
701 | __u8 retval; | ||
702 | __u8 rsvd[2]; | ||
637 | }; | 703 | }; |
638 | 704 | ||
639 | enum { | 705 | enum { |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 75393f5cff41..83ec5f7844ac 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | |||
@@ -1064,4 +1064,41 @@ | |||
1064 | #define ADDRESS(x) ((x) << ADDRESS_SHIFT) | 1064 | #define ADDRESS(x) ((x) << ADDRESS_SHIFT) |
1065 | 1065 | ||
1066 | #define XGMAC_PORT_INT_CAUSE 0x10dc | 1066 | #define XGMAC_PORT_INT_CAUSE 0x10dc |
1067 | |||
1068 | #define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28 | ||
1069 | |||
1070 | #define A_TP_TX_MOD_CHANNEL_WEIGHT 0x7e34 | ||
1071 | |||
1072 | #define S_TX_MOD_QUEUE_REQ_MAP 0 | ||
1073 | #define M_TX_MOD_QUEUE_REQ_MAP 0xffffU | ||
1074 | #define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP) | ||
1075 | |||
1076 | #define A_TP_TX_MOD_QUEUE_WEIGHT0 0x7e30 | ||
1077 | |||
1078 | #define S_TX_MODQ_WEIGHT3 24 | ||
1079 | #define M_TX_MODQ_WEIGHT3 0xffU | ||
1080 | #define V_TX_MODQ_WEIGHT3(x) ((x) << S_TX_MODQ_WEIGHT3) | ||
1081 | |||
1082 | #define S_TX_MODQ_WEIGHT2 16 | ||
1083 | #define M_TX_MODQ_WEIGHT2 0xffU | ||
1084 | #define V_TX_MODQ_WEIGHT2(x) ((x) << S_TX_MODQ_WEIGHT2) | ||
1085 | |||
1086 | #define S_TX_MODQ_WEIGHT1 8 | ||
1087 | #define M_TX_MODQ_WEIGHT1 0xffU | ||
1088 | #define V_TX_MODQ_WEIGHT1(x) ((x) << S_TX_MODQ_WEIGHT1) | ||
1089 | |||
1090 | #define S_TX_MODQ_WEIGHT0 0 | ||
1091 | #define M_TX_MODQ_WEIGHT0 0xffU | ||
1092 | #define V_TX_MODQ_WEIGHT0(x) ((x) << S_TX_MODQ_WEIGHT0) | ||
1093 | |||
1094 | #define A_TP_TX_SCHED_HDR 0x23 | ||
1095 | |||
1096 | #define A_TP_TX_SCHED_FIFO 0x24 | ||
1097 | |||
1098 | #define A_TP_TX_SCHED_PCMD 0x25 | ||
1099 | |||
1100 | #define S_PORT 1 | ||
1101 | #define V_PORT(x) ((x) << S_PORT) | ||
1102 | #define F_PORT V_PORT(1U) | ||
1103 | |||
1067 | #endif /* __T4_REGS_H */ | 1104 | #endif /* __T4_REGS_H */ |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 0abc864cdd3a..a0dcccd846c9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | |||
@@ -35,6 +35,45 @@ | |||
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_retval { | ||
39 | FW_SUCCESS = 0, /* completed sucessfully */ | ||
40 | FW_EPERM = 1, /* operation not permitted */ | ||
41 | FW_ENOENT = 2, /* no such file or directory */ | ||
42 | FW_EIO = 5, /* input/output error; hw bad */ | ||
43 | FW_ENOEXEC = 8, /* exec format error; inv microcode */ | ||
44 | FW_EAGAIN = 11, /* try again */ | ||
45 | FW_ENOMEM = 12, /* out of memory */ | ||
46 | FW_EFAULT = 14, /* bad address; fw bad */ | ||
47 | FW_EBUSY = 16, /* resource busy */ | ||
48 | FW_EEXIST = 17, /* file exists */ | ||
49 | FW_EINVAL = 22, /* invalid argument */ | ||
50 | FW_ENOSPC = 28, /* no space left on device */ | ||
51 | FW_ENOSYS = 38, /* functionality not implemented */ | ||
52 | FW_EPROTO = 71, /* protocol error */ | ||
53 | FW_EADDRINUSE = 98, /* address already in use */ | ||
54 | FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ | ||
55 | FW_ENETDOWN = 100, /* network is down */ | ||
56 | FW_ENETUNREACH = 101, /* network is unreachable */ | ||
57 | FW_ENOBUFS = 105, /* no buffer space available */ | ||
58 | FW_ETIMEDOUT = 110, /* timeout */ | ||
59 | FW_EINPROGRESS = 115, /* fw internal */ | ||
60 | FW_SCSI_ABORT_REQUESTED = 128, /* */ | ||
61 | FW_SCSI_ABORT_TIMEDOUT = 129, /* */ | ||
62 | FW_SCSI_ABORTED = 130, /* */ | ||
63 | FW_SCSI_CLOSE_REQUESTED = 131, /* */ | ||
64 | FW_ERR_LINK_DOWN = 132, /* */ | ||
65 | FW_RDEV_NOT_READY = 133, /* */ | ||
66 | FW_ERR_RDEV_LOST = 134, /* */ | ||
67 | FW_ERR_RDEV_LOGO = 135, /* */ | ||
68 | FW_FCOE_NO_XCHG = 136, /* */ | ||
69 | FW_SCSI_RSP_ERR = 137, /* */ | ||
70 | FW_ERR_RDEV_IMPL_LOGO = 138, /* */ | ||
71 | FW_SCSI_UNDER_FLOW_ERR = 139, /* */ | ||
72 | FW_SCSI_OVER_FLOW_ERR = 140, /* */ | ||
73 | FW_SCSI_DDP_ERR = 141, /* DDP error*/ | ||
74 | FW_SCSI_TASK_ERR = 142, /* No SCSI tasks available */ | ||
75 | }; | ||
76 | |||
38 | #define FW_T4VF_SGE_BASE_ADDR 0x0000 | 77 | #define FW_T4VF_SGE_BASE_ADDR 0x0000 |
39 | #define FW_T4VF_MPS_BASE_ADDR 0x0100 | 78 | #define FW_T4VF_MPS_BASE_ADDR 0x0100 |
40 | #define FW_T4VF_PL_BASE_ADDR 0x0200 | 79 | #define FW_T4VF_PL_BASE_ADDR 0x0200 |
@@ -46,6 +85,7 @@ enum fw_wr_opcodes { | |||
46 | FW_ULPTX_WR = 0x04, | 85 | FW_ULPTX_WR = 0x04, |
47 | FW_TP_WR = 0x05, | 86 | FW_TP_WR = 0x05, |
48 | FW_ETH_TX_PKT_WR = 0x08, | 87 | FW_ETH_TX_PKT_WR = 0x08, |
88 | FW_OFLD_CONNECTION_WR = 0x2f, | ||
49 | FW_FLOWC_WR = 0x0a, | 89 | FW_FLOWC_WR = 0x0a, |
50 | FW_OFLD_TX_DATA_WR = 0x0b, | 90 | FW_OFLD_TX_DATA_WR = 0x0b, |
51 | FW_CMD_WR = 0x10, | 91 | FW_CMD_WR = 0x10, |
@@ -81,6 +121,282 @@ struct fw_wr_hdr { | |||
81 | #define FW_WR_LEN16(x) ((x) << 0) | 121 | #define FW_WR_LEN16(x) ((x) << 0) |
82 | 122 | ||
83 | #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B | 123 | #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B |
124 | #define HW_TPL_FR_MT_PR_OV_P_FC 0X327 | ||
125 | |||
126 | /* filter wr reply code in cookie in CPL_SET_TCB_RPL */ | ||
127 | enum fw_filter_wr_cookie { | ||
128 | FW_FILTER_WR_SUCCESS, | ||
129 | FW_FILTER_WR_FLT_ADDED, | ||
130 | FW_FILTER_WR_FLT_DELETED, | ||
131 | FW_FILTER_WR_SMT_TBL_FULL, | ||
132 | FW_FILTER_WR_EINVAL, | ||
133 | }; | ||
134 | |||
135 | struct fw_filter_wr { | ||
136 | __be32 op_pkd; | ||
137 | __be32 len16_pkd; | ||
138 | __be64 r3; | ||
139 | __be32 tid_to_iq; | ||
140 | __be32 del_filter_to_l2tix; | ||
141 | __be16 ethtype; | ||
142 | __be16 ethtypem; | ||
143 | __u8 frag_to_ovlan_vldm; | ||
144 | __u8 smac_sel; | ||
145 | __be16 rx_chan_rx_rpl_iq; | ||
146 | __be32 maci_to_matchtypem; | ||
147 | __u8 ptcl; | ||
148 | __u8 ptclm; | ||
149 | __u8 ttyp; | ||
150 | __u8 ttypm; | ||
151 | __be16 ivlan; | ||
152 | __be16 ivlanm; | ||
153 | __be16 ovlan; | ||
154 | __be16 ovlanm; | ||
155 | __u8 lip[16]; | ||
156 | __u8 lipm[16]; | ||
157 | __u8 fip[16]; | ||
158 | __u8 fipm[16]; | ||
159 | __be16 lp; | ||
160 | __be16 lpm; | ||
161 | __be16 fp; | ||
162 | __be16 fpm; | ||
163 | __be16 r7; | ||
164 | __u8 sma[6]; | ||
165 | }; | ||
166 | |||
167 | #define S_FW_FILTER_WR_TID 12 | ||
168 | #define M_FW_FILTER_WR_TID 0xfffff | ||
169 | #define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID) | ||
170 | #define G_FW_FILTER_WR_TID(x) \ | ||
171 | (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID) | ||
172 | |||
173 | #define S_FW_FILTER_WR_RQTYPE 11 | ||
174 | #define M_FW_FILTER_WR_RQTYPE 0x1 | ||
175 | #define V_FW_FILTER_WR_RQTYPE(x) ((x) << S_FW_FILTER_WR_RQTYPE) | ||
176 | #define G_FW_FILTER_WR_RQTYPE(x) \ | ||
177 | (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE) | ||
178 | #define F_FW_FILTER_WR_RQTYPE V_FW_FILTER_WR_RQTYPE(1U) | ||
179 | |||
180 | #define S_FW_FILTER_WR_NOREPLY 10 | ||
181 | #define M_FW_FILTER_WR_NOREPLY 0x1 | ||
182 | #define V_FW_FILTER_WR_NOREPLY(x) ((x) << S_FW_FILTER_WR_NOREPLY) | ||
183 | #define G_FW_FILTER_WR_NOREPLY(x) \ | ||
184 | (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY) | ||
185 | #define F_FW_FILTER_WR_NOREPLY V_FW_FILTER_WR_NOREPLY(1U) | ||
186 | |||
187 | #define S_FW_FILTER_WR_IQ 0 | ||
188 | #define M_FW_FILTER_WR_IQ 0x3ff | ||
189 | #define V_FW_FILTER_WR_IQ(x) ((x) << S_FW_FILTER_WR_IQ) | ||
190 | #define G_FW_FILTER_WR_IQ(x) \ | ||
191 | (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ) | ||
192 | |||
193 | #define S_FW_FILTER_WR_DEL_FILTER 31 | ||
194 | #define M_FW_FILTER_WR_DEL_FILTER 0x1 | ||
195 | #define V_FW_FILTER_WR_DEL_FILTER(x) ((x) << S_FW_FILTER_WR_DEL_FILTER) | ||
196 | #define G_FW_FILTER_WR_DEL_FILTER(x) \ | ||
197 | (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER) | ||
198 | #define F_FW_FILTER_WR_DEL_FILTER V_FW_FILTER_WR_DEL_FILTER(1U) | ||
199 | |||
200 | #define S_FW_FILTER_WR_RPTTID 25 | ||
201 | #define M_FW_FILTER_WR_RPTTID 0x1 | ||
202 | #define V_FW_FILTER_WR_RPTTID(x) ((x) << S_FW_FILTER_WR_RPTTID) | ||
203 | #define G_FW_FILTER_WR_RPTTID(x) \ | ||
204 | (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID) | ||
205 | #define F_FW_FILTER_WR_RPTTID V_FW_FILTER_WR_RPTTID(1U) | ||
206 | |||
207 | #define S_FW_FILTER_WR_DROP 24 | ||
208 | #define M_FW_FILTER_WR_DROP 0x1 | ||
209 | #define V_FW_FILTER_WR_DROP(x) ((x) << S_FW_FILTER_WR_DROP) | ||
210 | #define G_FW_FILTER_WR_DROP(x) \ | ||
211 | (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP) | ||
212 | #define F_FW_FILTER_WR_DROP V_FW_FILTER_WR_DROP(1U) | ||
213 | |||
214 | #define S_FW_FILTER_WR_DIRSTEER 23 | ||
215 | #define M_FW_FILTER_WR_DIRSTEER 0x1 | ||
216 | #define V_FW_FILTER_WR_DIRSTEER(x) ((x) << S_FW_FILTER_WR_DIRSTEER) | ||
217 | #define G_FW_FILTER_WR_DIRSTEER(x) \ | ||
218 | (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER) | ||
219 | #define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U) | ||
220 | |||
221 | #define S_FW_FILTER_WR_MASKHASH 22 | ||
222 | #define M_FW_FILTER_WR_MASKHASH 0x1 | ||
223 | #define V_FW_FILTER_WR_MASKHASH(x) ((x) << S_FW_FILTER_WR_MASKHASH) | ||
224 | #define G_FW_FILTER_WR_MASKHASH(x) \ | ||
225 | (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH) | ||
226 | #define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U) | ||
227 | |||
228 | #define S_FW_FILTER_WR_DIRSTEERHASH 21 | ||
229 | #define M_FW_FILTER_WR_DIRSTEERHASH 0x1 | ||
230 | #define V_FW_FILTER_WR_DIRSTEERHASH(x) ((x) << S_FW_FILTER_WR_DIRSTEERHASH) | ||
231 | #define G_FW_FILTER_WR_DIRSTEERHASH(x) \ | ||
232 | (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH) | ||
233 | #define F_FW_FILTER_WR_DIRSTEERHASH V_FW_FILTER_WR_DIRSTEERHASH(1U) | ||
234 | |||
235 | #define S_FW_FILTER_WR_LPBK 20 | ||
236 | #define M_FW_FILTER_WR_LPBK 0x1 | ||
237 | #define V_FW_FILTER_WR_LPBK(x) ((x) << S_FW_FILTER_WR_LPBK) | ||
238 | #define G_FW_FILTER_WR_LPBK(x) \ | ||
239 | (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK) | ||
240 | #define F_FW_FILTER_WR_LPBK V_FW_FILTER_WR_LPBK(1U) | ||
241 | |||
242 | #define S_FW_FILTER_WR_DMAC 19 | ||
243 | #define M_FW_FILTER_WR_DMAC 0x1 | ||
244 | #define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC) | ||
245 | #define G_FW_FILTER_WR_DMAC(x) \ | ||
246 | (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC) | ||
247 | #define F_FW_FILTER_WR_DMAC V_FW_FILTER_WR_DMAC(1U) | ||
248 | |||
249 | #define S_FW_FILTER_WR_SMAC 18 | ||
250 | #define M_FW_FILTER_WR_SMAC 0x1 | ||
251 | #define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC) | ||
252 | #define G_FW_FILTER_WR_SMAC(x) \ | ||
253 | (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC) | ||
254 | #define F_FW_FILTER_WR_SMAC V_FW_FILTER_WR_SMAC(1U) | ||
255 | |||
256 | #define S_FW_FILTER_WR_INSVLAN 17 | ||
257 | #define M_FW_FILTER_WR_INSVLAN 0x1 | ||
258 | #define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN) | ||
259 | #define G_FW_FILTER_WR_INSVLAN(x) \ | ||
260 | (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN) | ||
261 | #define F_FW_FILTER_WR_INSVLAN V_FW_FILTER_WR_INSVLAN(1U) | ||
262 | |||
263 | #define S_FW_FILTER_WR_RMVLAN 16 | ||
264 | #define M_FW_FILTER_WR_RMVLAN 0x1 | ||
265 | #define V_FW_FILTER_WR_RMVLAN(x) ((x) << S_FW_FILTER_WR_RMVLAN) | ||
266 | #define G_FW_FILTER_WR_RMVLAN(x) \ | ||
267 | (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN) | ||
268 | #define F_FW_FILTER_WR_RMVLAN V_FW_FILTER_WR_RMVLAN(1U) | ||
269 | |||
270 | #define S_FW_FILTER_WR_HITCNTS 15 | ||
271 | #define M_FW_FILTER_WR_HITCNTS 0x1 | ||
272 | #define V_FW_FILTER_WR_HITCNTS(x) ((x) << S_FW_FILTER_WR_HITCNTS) | ||
273 | #define G_FW_FILTER_WR_HITCNTS(x) \ | ||
274 | (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS) | ||
275 | #define F_FW_FILTER_WR_HITCNTS V_FW_FILTER_WR_HITCNTS(1U) | ||
276 | |||
277 | #define S_FW_FILTER_WR_TXCHAN 13 | ||
278 | #define M_FW_FILTER_WR_TXCHAN 0x3 | ||
279 | #define V_FW_FILTER_WR_TXCHAN(x) ((x) << S_FW_FILTER_WR_TXCHAN) | ||
280 | #define G_FW_FILTER_WR_TXCHAN(x) \ | ||
281 | (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN) | ||
282 | |||
283 | #define S_FW_FILTER_WR_PRIO 12 | ||
284 | #define M_FW_FILTER_WR_PRIO 0x1 | ||
285 | #define V_FW_FILTER_WR_PRIO(x) ((x) << S_FW_FILTER_WR_PRIO) | ||
286 | #define G_FW_FILTER_WR_PRIO(x) \ | ||
287 | (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO) | ||
288 | #define F_FW_FILTER_WR_PRIO V_FW_FILTER_WR_PRIO(1U) | ||
289 | |||
290 | #define S_FW_FILTER_WR_L2TIX 0 | ||
291 | #define M_FW_FILTER_WR_L2TIX 0xfff | ||
292 | #define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX) | ||
293 | #define G_FW_FILTER_WR_L2TIX(x) \ | ||
294 | (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX) | ||
295 | |||
296 | #define S_FW_FILTER_WR_FRAG 7 | ||
297 | #define M_FW_FILTER_WR_FRAG 0x1 | ||
298 | #define V_FW_FILTER_WR_FRAG(x) ((x) << S_FW_FILTER_WR_FRAG) | ||
299 | #define G_FW_FILTER_WR_FRAG(x) \ | ||
300 | (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG) | ||
301 | #define F_FW_FILTER_WR_FRAG V_FW_FILTER_WR_FRAG(1U) | ||
302 | |||
303 | #define S_FW_FILTER_WR_FRAGM 6 | ||
304 | #define M_FW_FILTER_WR_FRAGM 0x1 | ||
305 | #define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM) | ||
306 | #define G_FW_FILTER_WR_FRAGM(x) \ | ||
307 | (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM) | ||
308 | #define F_FW_FILTER_WR_FRAGM V_FW_FILTER_WR_FRAGM(1U) | ||
309 | |||
310 | #define S_FW_FILTER_WR_IVLAN_VLD 5 | ||
311 | #define M_FW_FILTER_WR_IVLAN_VLD 0x1 | ||
312 | #define V_FW_FILTER_WR_IVLAN_VLD(x) ((x) << S_FW_FILTER_WR_IVLAN_VLD) | ||
313 | #define G_FW_FILTER_WR_IVLAN_VLD(x) \ | ||
314 | (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD) | ||
315 | #define F_FW_FILTER_WR_IVLAN_VLD V_FW_FILTER_WR_IVLAN_VLD(1U) | ||
316 | |||
317 | #define S_FW_FILTER_WR_OVLAN_VLD 4 | ||
318 | #define M_FW_FILTER_WR_OVLAN_VLD 0x1 | ||
319 | #define V_FW_FILTER_WR_OVLAN_VLD(x) ((x) << S_FW_FILTER_WR_OVLAN_VLD) | ||
320 | #define G_FW_FILTER_WR_OVLAN_VLD(x) \ | ||
321 | (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD) | ||
322 | #define F_FW_FILTER_WR_OVLAN_VLD V_FW_FILTER_WR_OVLAN_VLD(1U) | ||
323 | |||
324 | #define S_FW_FILTER_WR_IVLAN_VLDM 3 | ||
325 | #define M_FW_FILTER_WR_IVLAN_VLDM 0x1 | ||
326 | #define V_FW_FILTER_WR_IVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_IVLAN_VLDM) | ||
327 | #define G_FW_FILTER_WR_IVLAN_VLDM(x) \ | ||
328 | (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM) | ||
329 | #define F_FW_FILTER_WR_IVLAN_VLDM V_FW_FILTER_WR_IVLAN_VLDM(1U) | ||
330 | |||
331 | #define S_FW_FILTER_WR_OVLAN_VLDM 2 | ||
332 | #define M_FW_FILTER_WR_OVLAN_VLDM 0x1 | ||
333 | #define V_FW_FILTER_WR_OVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_OVLAN_VLDM) | ||
334 | #define G_FW_FILTER_WR_OVLAN_VLDM(x) \ | ||
335 | (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM) | ||
336 | #define F_FW_FILTER_WR_OVLAN_VLDM V_FW_FILTER_WR_OVLAN_VLDM(1U) | ||
337 | |||
338 | #define S_FW_FILTER_WR_RX_CHAN 15 | ||
339 | #define M_FW_FILTER_WR_RX_CHAN 0x1 | ||
340 | #define V_FW_FILTER_WR_RX_CHAN(x) ((x) << S_FW_FILTER_WR_RX_CHAN) | ||
341 | #define G_FW_FILTER_WR_RX_CHAN(x) \ | ||
342 | (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN) | ||
343 | #define F_FW_FILTER_WR_RX_CHAN V_FW_FILTER_WR_RX_CHAN(1U) | ||
344 | |||
345 | #define S_FW_FILTER_WR_RX_RPL_IQ 0 | ||
346 | #define M_FW_FILTER_WR_RX_RPL_IQ 0x3ff | ||
347 | #define V_FW_FILTER_WR_RX_RPL_IQ(x) ((x) << S_FW_FILTER_WR_RX_RPL_IQ) | ||
348 | #define G_FW_FILTER_WR_RX_RPL_IQ(x) \ | ||
349 | (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ) | ||
350 | |||
351 | #define S_FW_FILTER_WR_MACI 23 | ||
352 | #define M_FW_FILTER_WR_MACI 0x1ff | ||
353 | #define V_FW_FILTER_WR_MACI(x) ((x) << S_FW_FILTER_WR_MACI) | ||
354 | #define G_FW_FILTER_WR_MACI(x) \ | ||
355 | (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI) | ||
356 | |||
357 | #define S_FW_FILTER_WR_MACIM 14 | ||
358 | #define M_FW_FILTER_WR_MACIM 0x1ff | ||
359 | #define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM) | ||
360 | #define G_FW_FILTER_WR_MACIM(x) \ | ||
361 | (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM) | ||
362 | |||
363 | #define S_FW_FILTER_WR_FCOE 13 | ||
364 | #define M_FW_FILTER_WR_FCOE 0x1 | ||
365 | #define V_FW_FILTER_WR_FCOE(x) ((x) << S_FW_FILTER_WR_FCOE) | ||
366 | #define G_FW_FILTER_WR_FCOE(x) \ | ||
367 | (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE) | ||
368 | #define F_FW_FILTER_WR_FCOE V_FW_FILTER_WR_FCOE(1U) | ||
369 | |||
370 | #define S_FW_FILTER_WR_FCOEM 12 | ||
371 | #define M_FW_FILTER_WR_FCOEM 0x1 | ||
372 | #define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM) | ||
373 | #define G_FW_FILTER_WR_FCOEM(x) \ | ||
374 | (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM) | ||
375 | #define F_FW_FILTER_WR_FCOEM V_FW_FILTER_WR_FCOEM(1U) | ||
376 | |||
377 | #define S_FW_FILTER_WR_PORT 9 | ||
378 | #define M_FW_FILTER_WR_PORT 0x7 | ||
379 | #define V_FW_FILTER_WR_PORT(x) ((x) << S_FW_FILTER_WR_PORT) | ||
380 | #define G_FW_FILTER_WR_PORT(x) \ | ||
381 | (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT) | ||
382 | |||
383 | #define S_FW_FILTER_WR_PORTM 6 | ||
384 | #define M_FW_FILTER_WR_PORTM 0x7 | ||
385 | #define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM) | ||
386 | #define G_FW_FILTER_WR_PORTM(x) \ | ||
387 | (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM) | ||
388 | |||
389 | #define S_FW_FILTER_WR_MATCHTYPE 3 | ||
390 | #define M_FW_FILTER_WR_MATCHTYPE 0x7 | ||
391 | #define V_FW_FILTER_WR_MATCHTYPE(x) ((x) << S_FW_FILTER_WR_MATCHTYPE) | ||
392 | #define G_FW_FILTER_WR_MATCHTYPE(x) \ | ||
393 | (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE) | ||
394 | |||
395 | #define S_FW_FILTER_WR_MATCHTYPEM 0 | ||
396 | #define M_FW_FILTER_WR_MATCHTYPEM 0x7 | ||
397 | #define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM) | ||
398 | #define G_FW_FILTER_WR_MATCHTYPEM(x) \ | ||
399 | (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM) | ||
84 | 400 | ||
85 | struct fw_ulptx_wr { | 401 | struct fw_ulptx_wr { |
86 | __be32 op_to_compl; | 402 | __be32 op_to_compl; |
@@ -100,6 +416,108 @@ struct fw_eth_tx_pkt_wr { | |||
100 | __be64 r3; | 416 | __be64 r3; |
101 | }; | 417 | }; |
102 | 418 | ||
419 | struct fw_ofld_connection_wr { | ||
420 | __be32 op_compl; | ||
421 | __be32 len16_pkd; | ||
422 | __u64 cookie; | ||
423 | __be64 r2; | ||
424 | __be64 r3; | ||
425 | struct fw_ofld_connection_le { | ||
426 | __be32 version_cpl; | ||
427 | __be32 filter; | ||
428 | __be32 r1; | ||
429 | __be16 lport; | ||
430 | __be16 pport; | ||
431 | union fw_ofld_connection_leip { | ||
432 | struct fw_ofld_connection_le_ipv4 { | ||
433 | __be32 pip; | ||
434 | __be32 lip; | ||
435 | __be64 r0; | ||
436 | __be64 r1; | ||
437 | __be64 r2; | ||
438 | } ipv4; | ||
439 | struct fw_ofld_connection_le_ipv6 { | ||
440 | __be64 pip_hi; | ||
441 | __be64 pip_lo; | ||
442 | __be64 lip_hi; | ||
443 | __be64 lip_lo; | ||
444 | } ipv6; | ||
445 | } u; | ||
446 | } le; | ||
447 | struct fw_ofld_connection_tcb { | ||
448 | __be32 t_state_to_astid; | ||
449 | __be16 cplrxdataack_cplpassacceptrpl; | ||
450 | __be16 rcv_adv; | ||
451 | __be32 rcv_nxt; | ||
452 | __be32 tx_max; | ||
453 | __be64 opt0; | ||
454 | __be32 opt2; | ||
455 | __be32 r1; | ||
456 | __be64 r2; | ||
457 | __be64 r3; | ||
458 | } tcb; | ||
459 | }; | ||
460 | |||
461 | #define S_FW_OFLD_CONNECTION_WR_VERSION 31 | ||
462 | #define M_FW_OFLD_CONNECTION_WR_VERSION 0x1 | ||
463 | #define V_FW_OFLD_CONNECTION_WR_VERSION(x) \ | ||
464 | ((x) << S_FW_OFLD_CONNECTION_WR_VERSION) | ||
465 | #define G_FW_OFLD_CONNECTION_WR_VERSION(x) \ | ||
466 | (((x) >> S_FW_OFLD_CONNECTION_WR_VERSION) & \ | ||
467 | M_FW_OFLD_CONNECTION_WR_VERSION) | ||
468 | #define F_FW_OFLD_CONNECTION_WR_VERSION \ | ||
469 | V_FW_OFLD_CONNECTION_WR_VERSION(1U) | ||
470 | |||
471 | #define S_FW_OFLD_CONNECTION_WR_CPL 30 | ||
472 | #define M_FW_OFLD_CONNECTION_WR_CPL 0x1 | ||
473 | #define V_FW_OFLD_CONNECTION_WR_CPL(x) ((x) << S_FW_OFLD_CONNECTION_WR_CPL) | ||
474 | #define G_FW_OFLD_CONNECTION_WR_CPL(x) \ | ||
475 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPL) & M_FW_OFLD_CONNECTION_WR_CPL) | ||
476 | #define F_FW_OFLD_CONNECTION_WR_CPL V_FW_OFLD_CONNECTION_WR_CPL(1U) | ||
477 | |||
478 | #define S_FW_OFLD_CONNECTION_WR_T_STATE 28 | ||
479 | #define M_FW_OFLD_CONNECTION_WR_T_STATE 0xf | ||
480 | #define V_FW_OFLD_CONNECTION_WR_T_STATE(x) \ | ||
481 | ((x) << S_FW_OFLD_CONNECTION_WR_T_STATE) | ||
482 | #define G_FW_OFLD_CONNECTION_WR_T_STATE(x) \ | ||
483 | (((x) >> S_FW_OFLD_CONNECTION_WR_T_STATE) & \ | ||
484 | M_FW_OFLD_CONNECTION_WR_T_STATE) | ||
485 | |||
486 | #define S_FW_OFLD_CONNECTION_WR_RCV_SCALE 24 | ||
487 | #define M_FW_OFLD_CONNECTION_WR_RCV_SCALE 0xf | ||
488 | #define V_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ | ||
489 | ((x) << S_FW_OFLD_CONNECTION_WR_RCV_SCALE) | ||
490 | #define G_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ | ||
491 | (((x) >> S_FW_OFLD_CONNECTION_WR_RCV_SCALE) & \ | ||
492 | M_FW_OFLD_CONNECTION_WR_RCV_SCALE) | ||
493 | |||
494 | #define S_FW_OFLD_CONNECTION_WR_ASTID 0 | ||
495 | #define M_FW_OFLD_CONNECTION_WR_ASTID 0xffffff | ||
496 | #define V_FW_OFLD_CONNECTION_WR_ASTID(x) \ | ||
497 | ((x) << S_FW_OFLD_CONNECTION_WR_ASTID) | ||
498 | #define G_FW_OFLD_CONNECTION_WR_ASTID(x) \ | ||
499 | (((x) >> S_FW_OFLD_CONNECTION_WR_ASTID) & M_FW_OFLD_CONNECTION_WR_ASTID) | ||
500 | |||
501 | #define S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 15 | ||
502 | #define M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 0x1 | ||
503 | #define V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ | ||
504 | ((x) << S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) | ||
505 | #define G_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ | ||
506 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) & \ | ||
507 | M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) | ||
508 | #define F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK \ | ||
509 | V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(1U) | ||
510 | |||
511 | #define S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 14 | ||
512 | #define M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 0x1 | ||
513 | #define V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ | ||
514 | ((x) << S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) | ||
515 | #define G_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ | ||
516 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) & \ | ||
517 | M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) | ||
518 | #define F_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL \ | ||
519 | V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(1U) | ||
520 | |||
103 | enum fw_flowc_mnem { | 521 | enum fw_flowc_mnem { |
104 | FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ | 522 | FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ |
105 | FW_FLOWC_MNEM_CH, | 523 | FW_FLOWC_MNEM_CH, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 9a9de51ecc91..8b3d0512a46b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -1338,6 +1338,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1338 | { | 1338 | { |
1339 | struct mlx4_cmd_mailbox *mailbox; | 1339 | struct mlx4_cmd_mailbox *mailbox; |
1340 | __be32 *outbox; | 1340 | __be32 *outbox; |
1341 | u32 dword_field; | ||
1341 | int err; | 1342 | int err; |
1342 | u8 byte_field; | 1343 | u8 byte_field; |
1343 | 1344 | ||
@@ -1372,10 +1373,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1372 | MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); | 1373 | MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); |
1373 | MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); | 1374 | MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); |
1374 | 1375 | ||
1376 | MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); | ||
1377 | if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { | ||
1378 | param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
1379 | } else { | ||
1380 | MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET); | ||
1381 | if (byte_field & 0x8) | ||
1382 | param->steering_mode = MLX4_STEERING_MODE_B0; | ||
1383 | else | ||
1384 | param->steering_mode = MLX4_STEERING_MODE_A0; | ||
1385 | } | ||
1375 | /* steering attributes */ | 1386 | /* steering attributes */ |
1376 | if (dev->caps.steering_mode == | 1387 | if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { |
1377 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
1378 | |||
1379 | MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); | 1388 | MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); |
1380 | MLX4_GET(param->log_mc_entry_sz, outbox, | 1389 | MLX4_GET(param->log_mc_entry_sz, outbox, |
1381 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); | 1390 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 2c2e7ade2a34..dbf2f69cc59f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
@@ -172,6 +172,7 @@ struct mlx4_init_hca_param { | |||
172 | u8 log_uar_sz; | 172 | u8 log_uar_sz; |
173 | u8 uar_page_sz; /* log pg sz in 4k chunks */ | 173 | u8 uar_page_sz; /* log pg sz in 4k chunks */ |
174 | u8 fs_hash_enable_bits; | 174 | u8 fs_hash_enable_bits; |
175 | u8 steering_mode; /* for QUERY_HCA */ | ||
175 | u64 dev_cap_enabled; | 176 | u64 dev_cap_enabled; |
176 | }; | 177 | }; |
177 | 178 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index b2acbe7706a3..e1bafffbc3b1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -85,15 +85,15 @@ static int probe_vf; | |||
85 | module_param(probe_vf, int, 0644); | 85 | module_param(probe_vf, int, 0644); |
86 | MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); | 86 | MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); |
87 | 87 | ||
88 | int mlx4_log_num_mgm_entry_size = 10; | 88 | int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; |
89 | module_param_named(log_num_mgm_entry_size, | 89 | module_param_named(log_num_mgm_entry_size, |
90 | mlx4_log_num_mgm_entry_size, int, 0444); | 90 | mlx4_log_num_mgm_entry_size, int, 0444); |
91 | MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" | 91 | MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" |
92 | " of qp per mcg, for example:" | 92 | " of qp per mcg, for example:" |
93 | " 10 gives 248.range: 9<=" | 93 | " 10 gives 248.range: 7 <=" |
94 | " log_num_mgm_entry_size <= 12." | 94 | " log_num_mgm_entry_size <= 12." |
95 | " Not in use with device managed" | 95 | " To activate device managed" |
96 | " flow steering"); | 96 | " flow steering when available, set to -1"); |
97 | 97 | ||
98 | static bool enable_64b_cqe_eqe; | 98 | static bool enable_64b_cqe_eqe; |
99 | module_param(enable_64b_cqe_eqe, bool, 0444); | 99 | module_param(enable_64b_cqe_eqe, bool, 0444); |
@@ -281,28 +281,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
281 | dev->caps.max_gso_sz = dev_cap->max_gso_sz; | 281 | dev->caps.max_gso_sz = dev_cap->max_gso_sz; |
282 | dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; | 282 | dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; |
283 | 283 | ||
284 | if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { | ||
285 | dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
286 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
287 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
288 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
289 | } else { | ||
290 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && | ||
291 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { | ||
292 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; | ||
293 | } else { | ||
294 | dev->caps.steering_mode = MLX4_STEERING_MODE_A0; | ||
295 | |||
296 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || | ||
297 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
298 | mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " | ||
299 | "set to use B0 steering. Falling back to A0 steering mode.\n"); | ||
300 | } | ||
301 | dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); | ||
302 | } | ||
303 | mlx4_dbg(dev, "Steering mode is: %s\n", | ||
304 | mlx4_steering_mode_str(dev->caps.steering_mode)); | ||
305 | |||
306 | /* Sense port always allowed on supported devices for ConnectX-1 and -2 */ | 284 | /* Sense port always allowed on supported devices for ConnectX-1 and -2 */ |
307 | if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT) | 285 | if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT) |
308 | dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; | 286 | dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; |
@@ -493,6 +471,23 @@ int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) | |||
493 | } | 471 | } |
494 | EXPORT_SYMBOL(mlx4_is_slave_active); | 472 | EXPORT_SYMBOL(mlx4_is_slave_active); |
495 | 473 | ||
474 | static void slave_adjust_steering_mode(struct mlx4_dev *dev, | ||
475 | struct mlx4_dev_cap *dev_cap, | ||
476 | struct mlx4_init_hca_param *hca_param) | ||
477 | { | ||
478 | dev->caps.steering_mode = hca_param->steering_mode; | ||
479 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
480 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
481 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
482 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
483 | } else | ||
484 | dev->caps.num_qp_per_mgm = | ||
485 | 4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2); | ||
486 | |||
487 | mlx4_dbg(dev, "Steering mode is: %s\n", | ||
488 | mlx4_steering_mode_str(dev->caps.steering_mode)); | ||
489 | } | ||
490 | |||
496 | static int mlx4_slave_cap(struct mlx4_dev *dev) | 491 | static int mlx4_slave_cap(struct mlx4_dev *dev) |
497 | { | 492 | { |
498 | int err; | 493 | int err; |
@@ -635,6 +630,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
635 | dev->caps.cqe_size = 32; | 630 | dev->caps.cqe_size = 32; |
636 | } | 631 | } |
637 | 632 | ||
633 | slave_adjust_steering_mode(dev, &dev_cap, &hca_param); | ||
634 | |||
638 | return 0; | 635 | return 0; |
639 | 636 | ||
640 | err_mem: | 637 | err_mem: |
@@ -1321,6 +1318,59 @@ static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev) | |||
1321 | } | 1318 | } |
1322 | } | 1319 | } |
1323 | 1320 | ||
1321 | static int choose_log_fs_mgm_entry_size(int qp_per_entry) | ||
1322 | { | ||
1323 | int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; | ||
1324 | |||
1325 | for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE; | ||
1326 | i++) { | ||
1327 | if (qp_per_entry <= 4 * ((1 << i) / 16 - 2)) | ||
1328 | break; | ||
1329 | } | ||
1330 | |||
1331 | return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; | ||
1332 | } | ||
1333 | |||
1334 | static void choose_steering_mode(struct mlx4_dev *dev, | ||
1335 | struct mlx4_dev_cap *dev_cap) | ||
1336 | { | ||
1337 | if (mlx4_log_num_mgm_entry_size == -1 && | ||
1338 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && | ||
1339 | (!mlx4_is_mfunc(dev) || | ||
1340 | (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) && | ||
1341 | choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >= | ||
1342 | MLX4_MIN_MGM_LOG_ENTRY_SIZE) { | ||
1343 | dev->oper_log_mgm_entry_size = | ||
1344 | choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry); | ||
1345 | dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
1346 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
1347 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
1348 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
1349 | } else { | ||
1350 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && | ||
1351 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
1352 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; | ||
1353 | else { | ||
1354 | dev->caps.steering_mode = MLX4_STEERING_MODE_A0; | ||
1355 | |||
1356 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || | ||
1357 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
1358 | mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags " | ||
1359 | "set to use B0 steering. Falling back to A0 steering mode.\n"); | ||
1360 | } | ||
1361 | dev->oper_log_mgm_entry_size = | ||
1362 | mlx4_log_num_mgm_entry_size > 0 ? | ||
1363 | mlx4_log_num_mgm_entry_size : | ||
1364 | MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; | ||
1365 | dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); | ||
1366 | } | ||
1367 | mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, " | ||
1368 | "modparam log_num_mgm_entry_size = %d\n", | ||
1369 | mlx4_steering_mode_str(dev->caps.steering_mode), | ||
1370 | dev->oper_log_mgm_entry_size, | ||
1371 | mlx4_log_num_mgm_entry_size); | ||
1372 | } | ||
1373 | |||
1324 | static int mlx4_init_hca(struct mlx4_dev *dev) | 1374 | static int mlx4_init_hca(struct mlx4_dev *dev) |
1325 | { | 1375 | { |
1326 | struct mlx4_priv *priv = mlx4_priv(dev); | 1376 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -1360,6 +1410,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1360 | goto err_stop_fw; | 1410 | goto err_stop_fw; |
1361 | } | 1411 | } |
1362 | 1412 | ||
1413 | choose_steering_mode(dev, &dev_cap); | ||
1414 | |||
1363 | if (mlx4_is_master(dev)) | 1415 | if (mlx4_is_master(dev)) |
1364 | mlx4_parav_master_pf_caps(dev); | 1416 | mlx4_parav_master_pf_caps(dev); |
1365 | 1417 | ||
@@ -2452,6 +2504,17 @@ static int __init mlx4_verify_params(void) | |||
2452 | port_type_array[0] = true; | 2504 | port_type_array[0] = true; |
2453 | } | 2505 | } |
2454 | 2506 | ||
2507 | if (mlx4_log_num_mgm_entry_size != -1 && | ||
2508 | (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || | ||
2509 | mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) { | ||
2510 | pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not " | ||
2511 | "in legal range (-1 or %d..%d)\n", | ||
2512 | mlx4_log_num_mgm_entry_size, | ||
2513 | MLX4_MIN_MGM_LOG_ENTRY_SIZE, | ||
2514 | MLX4_MAX_MGM_LOG_ENTRY_SIZE); | ||
2515 | return -1; | ||
2516 | } | ||
2517 | |||
2455 | return 0; | 2518 | return 0; |
2456 | } | 2519 | } |
2457 | 2520 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index e151c21baf2b..1ee4db3c6400 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
@@ -54,12 +54,7 @@ struct mlx4_mgm { | |||
54 | 54 | ||
55 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) | 55 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) |
56 | { | 56 | { |
57 | if (dev->caps.steering_mode == | 57 | return 1 << dev->oper_log_mgm_entry_size; |
58 | MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
59 | return 1 << MLX4_FS_MGM_LOG_ENTRY_SIZE; | ||
60 | else | ||
61 | return min((1 << mlx4_log_num_mgm_entry_size), | ||
62 | MLX4_MAX_MGM_ENTRY_SIZE); | ||
63 | } | 58 | } |
64 | 59 | ||
65 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) | 60 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 1cf42036d7bb..116c5c29d2d1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -94,8 +94,10 @@ enum { | |||
94 | }; | 94 | }; |
95 | 95 | ||
96 | enum { | 96 | enum { |
97 | MLX4_MAX_MGM_ENTRY_SIZE = 0x1000, | 97 | MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE = 10, |
98 | MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2), | 98 | MLX4_MIN_MGM_LOG_ENTRY_SIZE = 7, |
99 | MLX4_MAX_MGM_LOG_ENTRY_SIZE = 12, | ||
100 | MLX4_MAX_QP_PER_MGM = 4 * ((1 << MLX4_MAX_MGM_LOG_ENTRY_SIZE) / 16 - 2), | ||
99 | MLX4_MTT_ENTRY_PER_SEG = 8, | 101 | MLX4_MTT_ENTRY_PER_SEG = 8, |
100 | }; | 102 | }; |
101 | 103 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index b05705f50f0f..561ed2a22a17 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -3071,6 +3071,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3071 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | 3071 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; |
3072 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; | 3072 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; |
3073 | int err; | 3073 | int err; |
3074 | int qpn; | ||
3074 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | 3075 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; |
3075 | struct _rule_hw *rule_header; | 3076 | struct _rule_hw *rule_header; |
3076 | int header_id; | 3077 | int header_id; |
@@ -3080,13 +3081,21 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3080 | return -EOPNOTSUPP; | 3081 | return -EOPNOTSUPP; |
3081 | 3082 | ||
3082 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | 3083 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; |
3084 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; | ||
3085 | err = get_res(dev, slave, qpn, RES_QP, NULL); | ||
3086 | if (err) { | ||
3087 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); | ||
3088 | return err; | ||
3089 | } | ||
3083 | rule_header = (struct _rule_hw *)(ctrl + 1); | 3090 | rule_header = (struct _rule_hw *)(ctrl + 1); |
3084 | header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); | 3091 | header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); |
3085 | 3092 | ||
3086 | switch (header_id) { | 3093 | switch (header_id) { |
3087 | case MLX4_NET_TRANS_RULE_ID_ETH: | 3094 | case MLX4_NET_TRANS_RULE_ID_ETH: |
3088 | if (validate_eth_header_mac(slave, rule_header, rlist)) | 3095 | if (validate_eth_header_mac(slave, rule_header, rlist)) { |
3089 | return -EINVAL; | 3096 | err = -EINVAL; |
3097 | goto err_put; | ||
3098 | } | ||
3090 | break; | 3099 | break; |
3091 | case MLX4_NET_TRANS_RULE_ID_IB: | 3100 | case MLX4_NET_TRANS_RULE_ID_IB: |
3092 | break; | 3101 | break; |
@@ -3094,14 +3103,17 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3094 | case MLX4_NET_TRANS_RULE_ID_TCP: | 3103 | case MLX4_NET_TRANS_RULE_ID_TCP: |
3095 | case MLX4_NET_TRANS_RULE_ID_UDP: | 3104 | case MLX4_NET_TRANS_RULE_ID_UDP: |
3096 | pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); | 3105 | pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); |
3097 | if (add_eth_header(dev, slave, inbox, rlist, header_id)) | 3106 | if (add_eth_header(dev, slave, inbox, rlist, header_id)) { |
3098 | return -EINVAL; | 3107 | err = -EINVAL; |
3108 | goto err_put; | ||
3109 | } | ||
3099 | vhcr->in_modifier += | 3110 | vhcr->in_modifier += |
3100 | sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; | 3111 | sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; |
3101 | break; | 3112 | break; |
3102 | default: | 3113 | default: |
3103 | pr_err("Corrupted mailbox.\n"); | 3114 | pr_err("Corrupted mailbox.\n"); |
3104 | return -EINVAL; | 3115 | err = -EINVAL; |
3116 | goto err_put; | ||
3105 | } | 3117 | } |
3106 | 3118 | ||
3107 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, | 3119 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, |
@@ -3109,16 +3121,18 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3109 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 3121 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, |
3110 | MLX4_CMD_NATIVE); | 3122 | MLX4_CMD_NATIVE); |
3111 | if (err) | 3123 | if (err) |
3112 | return err; | 3124 | goto err_put; |
3113 | 3125 | ||
3114 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); | 3126 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); |
3115 | if (err) { | 3127 | if (err) { |
3116 | mlx4_err(dev, "Fail to add flow steering resources.\n "); | 3128 | mlx4_err(dev, "Fail to add flow steering resources.\n "); |
3117 | /* detach rule*/ | 3129 | /* detach rule*/ |
3118 | mlx4_cmd(dev, vhcr->out_param, 0, 0, | 3130 | mlx4_cmd(dev, vhcr->out_param, 0, 0, |
3119 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 3131 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
3120 | MLX4_CMD_NATIVE); | 3132 | MLX4_CMD_NATIVE); |
3121 | } | 3133 | } |
3134 | err_put: | ||
3135 | put_res(dev, slave, qpn, RES_QP); | ||
3122 | return err; | 3136 | return err; |
3123 | } | 3137 | } |
3124 | 3138 | ||