t4_sge.c (269356) | t4_sge.c (270297) |
---|---|
1/*- 2 * Copyright (c) 2011 Chelsio Communications, Inc. 3 * All rights reserved. 4 * Written by: Navdeep Parhar <np@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2011 Chelsio Communications, Inc. 3 * All rights reserved. 4 * Written by: Navdeep Parhar <np@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: stable/10/sys/dev/cxgbe/t4_sge.c 269356 2014-07-31 23:04:41Z np $"); | 29__FBSDID("$FreeBSD: stable/10/sys/dev/cxgbe/t4_sge.c 270297 2014-08-21 19:54:02Z np $"); |
30 31#include "opt_inet.h" 32#include "opt_inet6.h" 33 34#include <sys/types.h> 35#include <sys/mbuf.h> 36#include <sys/socket.h> 37#include <sys/kernel.h> --- 12 unchanged lines hidden (view full) --- 50#include <net/if_vlan_var.h> 51#include <netinet/in.h> 52#include <netinet/ip.h> 53#include <netinet/ip6.h> 54#include <netinet/tcp.h> 55#include <machine/md_var.h> 56#include <vm/vm.h> 57#include <vm/pmap.h> | 30 31#include "opt_inet.h" 32#include "opt_inet6.h" 33 34#include <sys/types.h> 35#include <sys/mbuf.h> 36#include <sys/socket.h> 37#include <sys/kernel.h> --- 12 unchanged lines hidden (view full) --- 50#include <net/if_vlan_var.h> 51#include <netinet/in.h> 52#include <netinet/ip.h> 53#include <netinet/ip6.h> 54#include <netinet/tcp.h> 55#include <machine/md_var.h> 56#include <vm/vm.h> 57#include <vm/pmap.h> |
58#ifdef DEV_NETMAP 59#include <machine/bus.h> 60#include <sys/selinfo.h> 61#include <net/if_var.h> 62#include <net/netmap.h> 63#include <dev/netmap/netmap_kern.h> 64#endif |
|
58 59#include "common/common.h" 60#include "common/t4_regs.h" 61#include "common/t4_regs_values.h" 62#include "common/t4_msg.h" 63 64#ifdef T4_PKT_TIMESTAMP 65#define RX_COPY_THRESHOLD (MINCLSIZE - 8) 66#else 67#define RX_COPY_THRESHOLD MINCLSIZE 68#endif 69 70/* 71 * Ethernet frames are DMA'd at this byte offset into the freelist buffer. 72 * 0-7 are valid values. 73 */ | 65 66#include "common/common.h" 67#include "common/t4_regs.h" 68#include "common/t4_regs_values.h" 69#include "common/t4_msg.h" 70 71#ifdef T4_PKT_TIMESTAMP 72#define RX_COPY_THRESHOLD (MINCLSIZE - 8) 73#else 74#define RX_COPY_THRESHOLD MINCLSIZE 75#endif 76 77/* 78 * Ethernet frames are DMA'd at this byte offset into the freelist buffer. 79 * 0-7 are valid values. 80 */ |
74static int fl_pktshift = 2; | 81int fl_pktshift = 2; |
75TUNABLE_INT("hw.cxgbe.fl_pktshift", &fl_pktshift); 76 77/* 78 * Pad ethernet payload up to this boundary. 79 * -1: driver should figure out a good value. 80 * 0: disable padding. 81 * Any power of 2 from 32 to 4096 (both inclusive) is also a valid value. 82 */ | 82TUNABLE_INT("hw.cxgbe.fl_pktshift", &fl_pktshift); 83 84/* 85 * Pad ethernet payload up to this boundary. 86 * -1: driver should figure out a good value. 87 * 0: disable padding. 88 * Any power of 2 from 32 to 4096 (both inclusive) is also a valid value. 89 */ |
83static int fl_pad = -1; | 90int fl_pad = -1; |
84TUNABLE_INT("hw.cxgbe.fl_pad", &fl_pad); 85 86/* 87 * Status page length. 88 * -1: driver should figure out a good value. 89 * 64 or 128 are the only other valid values. 90 */ | 91TUNABLE_INT("hw.cxgbe.fl_pad", &fl_pad); 92 93/* 94 * Status page length. 95 * -1: driver should figure out a good value. 96 * 64 or 128 are the only other valid values. 97 */ |
91static int spg_len = -1; | 98int spg_len = -1; |
92TUNABLE_INT("hw.cxgbe.spg_len", &spg_len); 93 94/* 95 * Congestion drops. 96 * -1: no congestion feedback (not recommended). 97 * 0: backpressure the channel instead of dropping packets right away. 98 * 1: no backpressure, drop packets for the congested queue immediately. 99 */ --- 59 unchanged lines hidden (view full) --- 159/* A packet's SGL. This + m_pkthdr has all info needed for tx */ 160struct sgl { 161 int nsegs; /* # of segments in the SGL, 0 means imm. tx */ 162 int nflits; /* # of flits needed for the SGL */ 163 bus_dma_segment_t seg[TX_SGL_SEGS]; 164}; 165 166static int service_iq(struct sge_iq *, int); | 99TUNABLE_INT("hw.cxgbe.spg_len", &spg_len); 100 101/* 102 * Congestion drops. 103 * -1: no congestion feedback (not recommended). 104 * 0: backpressure the channel instead of dropping packets right away. 105 * 1: no backpressure, drop packets for the congested queue immediately. 106 */ --- 59 unchanged lines hidden (view full) --- 166/* A packet's SGL. This + m_pkthdr has all info needed for tx */ 167struct sgl { 168 int nsegs; /* # of segments in the SGL, 0 means imm. tx */ 169 int nflits; /* # of flits needed for the SGL */ 170 bus_dma_segment_t seg[TX_SGL_SEGS]; 171}; 172 173static int service_iq(struct sge_iq *, int); |
167static struct mbuf *get_fl_payload(struct adapter *, struct sge_fl *, uint32_t, 168 int *); | 174static struct mbuf *get_fl_payload(struct adapter *, struct sge_fl *, uint32_t); |
169static int t4_eth_rx(struct sge_iq *, const struct rss_header *, struct mbuf *); | 175static int t4_eth_rx(struct sge_iq *, const struct rss_header *, struct mbuf *); |
170static inline void init_iq(struct sge_iq *, struct adapter *, int, int, int, 171 int); | 176static inline void init_iq(struct sge_iq *, struct adapter *, int, int, int); |
172static inline void init_fl(struct adapter *, struct sge_fl *, int, int, int, 173 char *); 174static inline void init_eq(struct sge_eq *, int, int, uint8_t, uint16_t, 175 char *); 176static int alloc_ring(struct adapter *, size_t, bus_dma_tag_t *, bus_dmamap_t *, 177 bus_addr_t *, void **); 178static int free_ring(struct adapter *, bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 179 void *); --- 9 unchanged lines hidden (view full) --- 189static int alloc_rxq(struct port_info *, struct sge_rxq *, int, int, 190 struct sysctl_oid *); 191static int free_rxq(struct port_info *, struct sge_rxq *); 192#ifdef TCP_OFFLOAD 193static int alloc_ofld_rxq(struct port_info *, struct sge_ofld_rxq *, int, int, 194 struct sysctl_oid *); 195static int free_ofld_rxq(struct port_info *, struct sge_ofld_rxq *); 196#endif | 177static inline void init_fl(struct adapter *, struct sge_fl *, int, int, int, 178 char *); 179static inline void init_eq(struct sge_eq *, int, int, uint8_t, uint16_t, 180 char *); 181static int alloc_ring(struct adapter *, size_t, bus_dma_tag_t *, bus_dmamap_t *, 182 bus_addr_t *, void **); 183static int free_ring(struct adapter *, bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 184 void *); --- 9 unchanged lines hidden (view full) --- 194static int alloc_rxq(struct port_info *, struct sge_rxq *, int, int, 195 struct sysctl_oid *); 196static int free_rxq(struct port_info *, struct sge_rxq *); 197#ifdef TCP_OFFLOAD 198static int alloc_ofld_rxq(struct port_info *, struct sge_ofld_rxq *, int, int, 199 struct sysctl_oid *); 200static int free_ofld_rxq(struct port_info *, struct sge_ofld_rxq *); 201#endif |
202#ifdef DEV_NETMAP 203static int alloc_nm_rxq(struct port_info *, struct sge_nm_rxq *, int, int, 204 struct sysctl_oid *); 205static int free_nm_rxq(struct port_info *, struct sge_nm_rxq *); 206static int alloc_nm_txq(struct port_info *, struct sge_nm_txq *, int, int, 207 struct sysctl_oid *); 208static int free_nm_txq(struct port_info *, struct sge_nm_txq *); 209#endif |
|
197static int ctrl_eq_alloc(struct adapter *, struct sge_eq *); 198static int eth_eq_alloc(struct adapter *, struct port_info *, struct sge_eq *); 199#ifdef TCP_OFFLOAD 200static int ofld_eq_alloc(struct adapter *, struct port_info *, struct sge_eq *); 201#endif 202static int alloc_eq(struct adapter *, struct port_info *, struct sge_eq *); 203static int free_eq(struct adapter *, struct sge_eq *); 204static int alloc_wrq(struct adapter *, struct port_info *, struct sge_wrq *, 205 struct sysctl_oid *); 206static int free_wrq(struct adapter *, struct sge_wrq *); 207static int alloc_txq(struct port_info *, struct sge_txq *, int, 208 struct sysctl_oid *); 209static int free_txq(struct port_info *, struct sge_txq *); 210static void oneseg_dma_callback(void *, bus_dma_segment_t *, int, int); | 210static int ctrl_eq_alloc(struct adapter *, struct sge_eq *); 211static int eth_eq_alloc(struct adapter *, struct port_info *, struct sge_eq *); 212#ifdef TCP_OFFLOAD 213static int ofld_eq_alloc(struct adapter *, struct port_info *, struct sge_eq *); 214#endif 215static int alloc_eq(struct adapter *, struct port_info *, struct sge_eq *); 216static int free_eq(struct adapter *, struct sge_eq *); 217static int alloc_wrq(struct adapter *, struct port_info *, struct sge_wrq *, 218 struct sysctl_oid *); 219static int free_wrq(struct adapter *, struct sge_wrq *); 220static int alloc_txq(struct port_info *, struct sge_txq *, int, 221 struct sysctl_oid *); 222static int free_txq(struct port_info *, struct sge_txq *); 223static void oneseg_dma_callback(void *, bus_dma_segment_t *, int, int); |
211static inline bool is_new_response(const struct sge_iq *, struct rsp_ctrl **); 212static inline void iq_next(struct sge_iq *); | |
213static inline void ring_fl_db(struct adapter *, struct sge_fl *); 214static int refill_fl(struct adapter *, struct sge_fl *, int); 215static void refill_sfl(void *); 216static int alloc_fl_sdesc(struct sge_fl *); 217static void free_fl_sdesc(struct adapter *, struct sge_fl *); 218static void find_best_refill_source(struct adapter *, struct sge_fl *, int); 219static void find_safe_refill_source(struct adapter *, struct sge_fl *); 220static void add_fl_to_sfl(struct adapter *, struct sge_fl *); --- 610 unchanged lines hidden (view full) --- 831 832 free_mgmtq(sc); 833 free_fwq(sc); 834 835 return (0); 836} 837 838static inline int | 224static inline void ring_fl_db(struct adapter *, struct sge_fl *); 225static int refill_fl(struct adapter *, struct sge_fl *, int); 226static void refill_sfl(void *); 227static int alloc_fl_sdesc(struct sge_fl *); 228static void free_fl_sdesc(struct adapter *, struct sge_fl *); 229static void find_best_refill_source(struct adapter *, struct sge_fl *, int); 230static void find_safe_refill_source(struct adapter *, struct sge_fl *); 231static void add_fl_to_sfl(struct adapter *, struct sge_fl *); --- 610 unchanged lines hidden (view full) --- 842 843 free_mgmtq(sc); 844 free_fwq(sc); 845 846 return (0); 847} 848 849static inline int |
850port_intr_count(struct port_info *pi) 851{ 852 int rc = 0; 853 854 if (pi->flags & INTR_RXQ) 855 rc += pi->nrxq; 856#ifdef TCP_OFFLOAD 857 if (pi->flags & INTR_OFLD_RXQ) 858 rc += pi->nofldrxq; 859#endif 860#ifdef DEV_NETMAP 861 if (pi->flags & INTR_NM_RXQ) 862 rc += pi->nnmrxq; 863#endif 864 return (rc); 865} 866 867static inline int |
|
839first_vector(struct port_info *pi) 840{ 841 struct adapter *sc = pi->adapter; 842 int rc = T4_EXTRA_INTR, i; 843 844 if (sc->intr_count == 1) 845 return (0); 846 847 for_each_port(sc, i) { | 868first_vector(struct port_info *pi) 869{ 870 struct adapter *sc = pi->adapter; 871 int rc = T4_EXTRA_INTR, i; 872 873 if (sc->intr_count == 1) 874 return (0); 875 876 for_each_port(sc, i) { |
848 struct port_info *p = sc->port[i]; 849 | |
850 if (i == pi->port_id) 851 break; 852 | 877 if (i == pi->port_id) 878 break; 879 |
853#ifdef TCP_OFFLOAD 854 if (sc->flags & INTR_DIRECT) 855 rc += p->nrxq + p->nofldrxq; 856 else 857 rc += max(p->nrxq, p->nofldrxq); 858#else 859 /* 860 * Not compiled with offload support and intr_count > 1. Only 861 * NIC queues exist and they'd better be taking direct 862 * interrupts. 863 */ 864 KASSERT(sc->flags & INTR_DIRECT, 865 ("%s: intr_count %d, !INTR_DIRECT", __func__, 866 sc->intr_count)); 867 868 rc += p->nrxq; 869#endif | 880 rc += port_intr_count(sc->port[i]); |
870 } 871 872 return (rc); 873} 874 875/* 876 * Given an arbitrary "index," come up with an iq that can be used by other 877 * queues (of this port) for interrupt forwarding, SGE egress updates, etc. 878 * The iq returned is guaranteed to be something that takes direct interrupts. 879 */ 880static struct sge_iq * 881port_intr_iq(struct port_info *pi, int idx) 882{ 883 struct adapter *sc = pi->adapter; 884 struct sge *s = &sc->sge; 885 struct sge_iq *iq = NULL; | 881 } 882 883 return (rc); 884} 885 886/* 887 * Given an arbitrary "index," come up with an iq that can be used by other 888 * queues (of this port) for interrupt forwarding, SGE egress updates, etc. 889 * The iq returned is guaranteed to be something that takes direct interrupts. 890 */ 891static struct sge_iq * 892port_intr_iq(struct port_info *pi, int idx) 893{ 894 struct adapter *sc = pi->adapter; 895 struct sge *s = &sc->sge; 896 struct sge_iq *iq = NULL; |
897 int nintr, i; |
|
886 887 if (sc->intr_count == 1) 888 return (&sc->sge.fwq); 889 | 898 899 if (sc->intr_count == 1) 900 return (&sc->sge.fwq); 901 |
890#ifdef TCP_OFFLOAD 891 if (sc->flags & INTR_DIRECT) { 892 idx %= pi->nrxq + pi->nofldrxq; | 902 nintr = port_intr_count(pi); 903 KASSERT(nintr != 0, 904 ("%s: pi %p has no exclusive interrupts, total interrupts = %d", 905 __func__, pi, sc->intr_count)); 906#ifdef DEV_NETMAP 907 /* Exclude netmap queues as they can't take anyone else's interrupts */ 908 if (pi->flags & INTR_NM_RXQ) 909 nintr -= pi->nnmrxq; 910 KASSERT(nintr > 0, 911 ("%s: pi %p has nintr %d after netmap adjustment of %d", __func__, 912 pi, nintr, pi->nnmrxq)); 913#endif 914 i = idx % nintr; |
893 | 915 |
894 if (idx >= pi->nrxq) { 895 idx -= pi->nrxq; 896 iq = &s->ofld_rxq[pi->first_ofld_rxq + idx].iq; 897 } else 898 iq = &s->rxq[pi->first_rxq + idx].iq; 899 900 } else { 901 idx %= max(pi->nrxq, pi->nofldrxq); 902 903 if (pi->nrxq >= pi->nofldrxq) 904 iq = &s->rxq[pi->first_rxq + idx].iq; 905 else 906 iq = &s->ofld_rxq[pi->first_ofld_rxq + idx].iq; | 916 if (pi->flags & INTR_RXQ) { 917 if (i < pi->nrxq) { 918 iq = &s->rxq[pi->first_rxq + i].iq; 919 goto done; 920 } 921 i -= pi->nrxq; |
907 } | 922 } |
908#else 909 /* 910 * Not compiled with offload support and intr_count > 1. Only NIC 911 * queues exist and they'd better be taking direct interrupts. 912 */ 913 KASSERT(sc->flags & INTR_DIRECT, 914 ("%s: intr_count %d, !INTR_DIRECT", __func__, sc->intr_count)); 915 916 idx %= pi->nrxq; 917 iq = &s->rxq[pi->first_rxq + idx].iq; | 923#ifdef TCP_OFFLOAD 924 if (pi->flags & INTR_OFLD_RXQ) { 925 if (i < pi->nofldrxq) { 926 iq = &s->ofld_rxq[pi->first_ofld_rxq + i].iq; 927 goto done; 928 } 929 i -= pi->nofldrxq; 930 } |
918#endif | 931#endif |
919 920 KASSERT(iq->flags & IQ_INTR, ("%s: EDOOFUS", __func__)); | 932 panic("%s: pi %p, intr_flags 0x%lx, idx %d, total intr %d\n", __func__, 933 pi, pi->flags & INTR_ALL, idx, nintr); 934done: 935 MPASS(iq != NULL); 936 KASSERT(iq->flags & IQ_INTR, 937 ("%s: iq %p (port %p, intr_flags 0x%lx, idx %d)", __func__, iq, pi, 938 pi->flags & INTR_ALL, idx)); |
921 return (iq); 922} 923 924/* Maximum payload that can be delivered with a single iq descriptor */ 925static inline int 926mtu_to_max_payload(struct adapter *sc, int mtu, const int toe) 927{ 928 int payload; --- 20 unchanged lines hidden (view full) --- 949{ 950 int rc = 0, i, j, intr_idx, iqid; 951 struct sge_rxq *rxq; 952 struct sge_txq *txq; 953 struct sge_wrq *ctrlq; 954#ifdef TCP_OFFLOAD 955 struct sge_ofld_rxq *ofld_rxq; 956 struct sge_wrq *ofld_txq; | 939 return (iq); 940} 941 942/* Maximum payload that can be delivered with a single iq descriptor */ 943static inline int 944mtu_to_max_payload(struct adapter *sc, int mtu, const int toe) 945{ 946 int payload; --- 20 unchanged lines hidden (view full) --- 967{ 968 int rc = 0, i, j, intr_idx, iqid; 969 struct sge_rxq *rxq; 970 struct sge_txq *txq; 971 struct sge_wrq *ctrlq; 972#ifdef TCP_OFFLOAD 973 struct sge_ofld_rxq *ofld_rxq; 974 struct sge_wrq *ofld_txq; |
957 struct sysctl_oid *oid2 = NULL; | |
958#endif | 975#endif |
976#ifdef DEV_NETMAP 977 struct sge_nm_rxq *nm_rxq; 978 struct sge_nm_txq *nm_txq; 979#endif |
|
959 char name[16]; 960 struct adapter *sc = pi->adapter; 961 struct ifnet *ifp = pi->ifp; 962 struct sysctl_oid *oid = device_get_sysctl_tree(pi->dev); 963 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid); 964 int maxp, pack, mtu = ifp->if_mtu; 965 | 980 char name[16]; 981 struct adapter *sc = pi->adapter; 982 struct ifnet *ifp = pi->ifp; 983 struct sysctl_oid *oid = device_get_sysctl_tree(pi->dev); 984 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid); 985 int maxp, pack, mtu = ifp->if_mtu; 986 |
966 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "rxq", CTLFLAG_RD, 967 NULL, "rx queues"); 968 969#ifdef TCP_OFFLOAD 970 if (is_offload(sc)) { 971 oid2 = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ofld_rxq", 972 CTLFLAG_RD, NULL, 973 "rx queues for offloaded TCP connections"); 974 } 975#endif 976 | |
977 /* Interrupt vector to start from (when using multiple vectors) */ 978 intr_idx = first_vector(pi); 979 980 /* | 987 /* Interrupt vector to start from (when using multiple vectors) */ 988 intr_idx = first_vector(pi); 989 990 /* |
981 * First pass over all rx queues (NIC and TOE): | 991 * First pass over all NIC and TOE rx queues: |
982 * a) initialize iq and fl 983 * b) allocate queue iff it will take direct interrupts. 984 */ 985 maxp = mtu_to_max_payload(sc, mtu, 0); 986 pack = enable_buffer_packing(sc); | 992 * a) initialize iq and fl 993 * b) allocate queue iff it will take direct interrupts. 994 */ 995 maxp = mtu_to_max_payload(sc, mtu, 0); 996 pack = enable_buffer_packing(sc); |
997 if (pi->flags & INTR_RXQ) { 998 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "rxq", 999 CTLFLAG_RD, NULL, "rx queues"); 1000 } |
|
987 for_each_rxq(pi, i, rxq) { 988 | 1001 for_each_rxq(pi, i, rxq) { 1002 |
989 init_iq(&rxq->iq, sc, pi->tmr_idx, pi->pktc_idx, pi->qsize_rxq, 990 RX_IQ_ESIZE); | 1003 init_iq(&rxq->iq, sc, pi->tmr_idx, pi->pktc_idx, pi->qsize_rxq); |
991 992 snprintf(name, sizeof(name), "%s rxq%d-fl", 993 device_get_nameunit(pi->dev), i); 994 init_fl(sc, &rxq->fl, pi->qsize_rxq / 8, maxp, pack, name); 995 | 1004 1005 snprintf(name, sizeof(name), "%s rxq%d-fl", 1006 device_get_nameunit(pi->dev), i); 1007 init_fl(sc, &rxq->fl, pi->qsize_rxq / 8, maxp, pack, name); 1008 |
996 if (sc->flags & INTR_DIRECT 997#ifdef TCP_OFFLOAD 998 || (sc->intr_count > 1 && pi->nrxq >= pi->nofldrxq) 999#endif 1000 ) { | 1009 if (pi->flags & INTR_RXQ) { |
1001 rxq->iq.flags |= IQ_INTR; 1002 rc = alloc_rxq(pi, rxq, intr_idx, i, oid); 1003 if (rc != 0) 1004 goto done; 1005 intr_idx++; 1006 } 1007 } | 1010 rxq->iq.flags |= IQ_INTR; 1011 rc = alloc_rxq(pi, rxq, intr_idx, i, oid); 1012 if (rc != 0) 1013 goto done; 1014 intr_idx++; 1015 } 1016 } |
1008 | |
1009#ifdef TCP_OFFLOAD 1010 maxp = mtu_to_max_payload(sc, mtu, 1); | 1017#ifdef TCP_OFFLOAD 1018 maxp = mtu_to_max_payload(sc, mtu, 1); |
1019 if (is_offload(sc) && pi->flags & INTR_OFLD_RXQ) { 1020 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ofld_rxq", 1021 CTLFLAG_RD, NULL, 1022 "rx queues for offloaded TCP connections"); 1023 } |
|
1011 for_each_ofld_rxq(pi, i, ofld_rxq) { 1012 1013 init_iq(&ofld_rxq->iq, sc, pi->tmr_idx, pi->pktc_idx, | 1024 for_each_ofld_rxq(pi, i, ofld_rxq) { 1025 1026 init_iq(&ofld_rxq->iq, sc, pi->tmr_idx, pi->pktc_idx, |
1014 pi->qsize_rxq, RX_IQ_ESIZE); | 1027 pi->qsize_rxq); |
1015 1016 snprintf(name, sizeof(name), "%s ofld_rxq%d-fl", 1017 device_get_nameunit(pi->dev), i); 1018 init_fl(sc, &ofld_rxq->fl, pi->qsize_rxq / 8, maxp, pack, name); 1019 | 1028 1029 snprintf(name, sizeof(name), "%s ofld_rxq%d-fl", 1030 device_get_nameunit(pi->dev), i); 1031 init_fl(sc, &ofld_rxq->fl, pi->qsize_rxq / 8, maxp, pack, name); 1032 |
1020 if (sc->flags & INTR_DIRECT || 1021 (sc->intr_count > 1 && pi->nofldrxq > pi->nrxq)) { | 1033 if (pi->flags & INTR_OFLD_RXQ) { |
1022 ofld_rxq->iq.flags |= IQ_INTR; | 1034 ofld_rxq->iq.flags |= IQ_INTR; |
1023 rc = alloc_ofld_rxq(pi, ofld_rxq, intr_idx, i, oid2); | 1035 rc = alloc_ofld_rxq(pi, ofld_rxq, intr_idx, i, oid); |
1024 if (rc != 0) 1025 goto done; 1026 intr_idx++; 1027 } 1028 } 1029#endif | 1036 if (rc != 0) 1037 goto done; 1038 intr_idx++; 1039 } 1040 } 1041#endif |
1042#ifdef DEV_NETMAP 1043 /* 1044 * We don't have buffers to back the netmap rx queues right now so we 1045 * create the queues in a way that doesn't set off any congestion signal 1046 * in the chip. 1047 */ 1048 if (pi->flags & INTR_NM_RXQ) { 1049 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "nm_rxq", 1050 CTLFLAG_RD, NULL, "rx queues for netmap"); 1051 for_each_nm_rxq(pi, i, nm_rxq) { 1052 rc = alloc_nm_rxq(pi, nm_rxq, intr_idx, i, oid); 1053 if (rc != 0) 1054 goto done; 1055 intr_idx++; 1056 } 1057 } 1058#endif |
|
1030 1031 /* | 1059 1060 /* |
1032 * Second pass over all rx queues (NIC and TOE). The queues forwarding | 1061 * Second pass over all NIC and TOE rx queues. The queues forwarding |
1033 * their interrupts are allocated now. 1034 */ 1035 j = 0; | 1062 * their interrupts are allocated now. 1063 */ 1064 j = 0; |
1036 for_each_rxq(pi, i, rxq) { 1037 if (rxq->iq.flags & IQ_INTR) 1038 continue; | 1065 if (!(pi->flags & INTR_RXQ)) { 1066 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "rxq", 1067 CTLFLAG_RD, NULL, "rx queues"); 1068 for_each_rxq(pi, i, rxq) { 1069 MPASS(!(rxq->iq.flags & IQ_INTR)); |
1039 | 1070 |
1040 intr_idx = port_intr_iq(pi, j)->abs_id; | 1071 intr_idx = port_intr_iq(pi, j)->abs_id; |
1041 | 1072 |
1042 rc = alloc_rxq(pi, rxq, intr_idx, i, oid); 1043 if (rc != 0) 1044 goto done; 1045 j++; | 1073 rc = alloc_rxq(pi, rxq, intr_idx, i, oid); 1074 if (rc != 0) 1075 goto done; 1076 j++; 1077 } |
1046 } | 1078 } |
1047 | |
1048#ifdef TCP_OFFLOAD | 1079#ifdef TCP_OFFLOAD |
1049 for_each_ofld_rxq(pi, i, ofld_rxq) { 1050 if (ofld_rxq->iq.flags & IQ_INTR) 1051 continue; | 1080 if (is_offload(sc) && !(pi->flags & INTR_OFLD_RXQ)) { 1081 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ofld_rxq", 1082 CTLFLAG_RD, NULL, 1083 "rx queues for offloaded TCP connections"); 1084 for_each_ofld_rxq(pi, i, ofld_rxq) { 1085 MPASS(!(ofld_rxq->iq.flags & IQ_INTR)); |
1052 | 1086 |
1053 intr_idx = port_intr_iq(pi, j)->abs_id; | 1087 intr_idx = port_intr_iq(pi, j)->abs_id; |
1054 | 1088 |
1055 rc = alloc_ofld_rxq(pi, ofld_rxq, intr_idx, i, oid2); 1056 if (rc != 0) 1057 goto done; 1058 j++; | 1089 rc = alloc_ofld_rxq(pi, ofld_rxq, intr_idx, i, oid); 1090 if (rc != 0) 1091 goto done; 1092 j++; 1093 } |
1059 } 1060#endif | 1094 } 1095#endif |
1096#ifdef DEV_NETMAP 1097 if (!(pi->flags & INTR_NM_RXQ)) 1098 CXGBE_UNIMPLEMENTED(__func__); 1099#endif |
|
1061 1062 /* 1063 * Now the tx queues. Only one pass needed. 1064 */ 1065 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "txq", CTLFLAG_RD, 1066 NULL, "tx queues"); 1067 j = 0; 1068 for_each_txq(pi, i, txq) { | 1100 1101 /* 1102 * Now the tx queues. Only one pass needed. 1103 */ 1104 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "txq", CTLFLAG_RD, 1105 NULL, "tx queues"); 1106 j = 0; 1107 for_each_txq(pi, i, txq) { |
1069 uint16_t iqid; 1070 | |
1071 iqid = port_intr_iq(pi, j)->cntxt_id; | 1108 iqid = port_intr_iq(pi, j)->cntxt_id; |
1072 | |
1073 snprintf(name, sizeof(name), "%s txq%d", 1074 device_get_nameunit(pi->dev), i); 1075 init_eq(&txq->eq, EQ_ETH, pi->qsize_txq, pi->tx_chan, iqid, 1076 name); 1077 1078 rc = alloc_txq(pi, txq, i, oid); 1079 if (rc != 0) 1080 goto done; 1081 j++; 1082 } | 1109 snprintf(name, sizeof(name), "%s txq%d", 1110 device_get_nameunit(pi->dev), i); 1111 init_eq(&txq->eq, EQ_ETH, pi->qsize_txq, pi->tx_chan, iqid, 1112 name); 1113 1114 rc = alloc_txq(pi, txq, i, oid); 1115 if (rc != 0) 1116 goto done; 1117 j++; 1118 } |
1083 | |
1084#ifdef TCP_OFFLOAD 1085 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ofld_txq", 1086 CTLFLAG_RD, NULL, "tx queues for offloaded TCP connections"); 1087 for_each_ofld_txq(pi, i, ofld_txq) { | 1119#ifdef TCP_OFFLOAD 1120 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ofld_txq", 1121 CTLFLAG_RD, NULL, "tx queues for offloaded TCP connections"); 1122 for_each_ofld_txq(pi, i, ofld_txq) { |
1088 uint16_t iqid; | 1123 struct sysctl_oid *oid2; |
1089 1090 iqid = port_intr_iq(pi, j)->cntxt_id; | 1124 1125 iqid = port_intr_iq(pi, j)->cntxt_id; |
1091 | |
1092 snprintf(name, sizeof(name), "%s ofld_txq%d", 1093 device_get_nameunit(pi->dev), i); 1094 init_eq(&ofld_txq->eq, EQ_OFLD, pi->qsize_txq, pi->tx_chan, 1095 iqid, name); 1096 1097 snprintf(name, sizeof(name), "%d", i); 1098 oid2 = SYSCTL_ADD_NODE(&pi->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 1099 name, CTLFLAG_RD, NULL, "offload tx queue"); 1100 1101 rc = alloc_wrq(sc, pi, ofld_txq, oid2); 1102 if (rc != 0) 1103 goto done; 1104 j++; 1105 } 1106#endif | 1126 snprintf(name, sizeof(name), "%s ofld_txq%d", 1127 device_get_nameunit(pi->dev), i); 1128 init_eq(&ofld_txq->eq, EQ_OFLD, pi->qsize_txq, pi->tx_chan, 1129 iqid, name); 1130 1131 snprintf(name, sizeof(name), "%d", i); 1132 oid2 = SYSCTL_ADD_NODE(&pi->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 1133 name, CTLFLAG_RD, NULL, "offload tx queue"); 1134 1135 rc = alloc_wrq(sc, pi, ofld_txq, oid2); 1136 if (rc != 0) 1137 goto done; 1138 j++; 1139 } 1140#endif |
1141#ifdef DEV_NETMAP 1142 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "nm_txq", 1143 CTLFLAG_RD, NULL, "tx queues for netmap use"); 1144 for_each_nm_txq(pi, i, nm_txq) { 1145 iqid = pi->first_nm_rxq + (j % pi->nnmrxq); 1146 rc = alloc_nm_txq(pi, nm_txq, iqid, i, oid); 1147 if (rc != 0) 1148 goto done; 1149 j++; 1150 } 1151#endif |
|
1107 1108 /* 1109 * Finally, the control queue. 1110 */ 1111 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ctrlq", CTLFLAG_RD, 1112 NULL, "ctrl queue"); 1113 ctrlq = &sc->sge.ctrlq[pi->port_id]; 1114 iqid = port_intr_iq(pi, 0)->cntxt_id; --- 17 unchanged lines hidden (view full) --- 1132 int i; 1133 struct adapter *sc = pi->adapter; 1134 struct sge_rxq *rxq; 1135 struct sge_txq *txq; 1136#ifdef TCP_OFFLOAD 1137 struct sge_ofld_rxq *ofld_rxq; 1138 struct sge_wrq *ofld_txq; 1139#endif | 1152 1153 /* 1154 * Finally, the control queue. 1155 */ 1156 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "ctrlq", CTLFLAG_RD, 1157 NULL, "ctrl queue"); 1158 ctrlq = &sc->sge.ctrlq[pi->port_id]; 1159 iqid = port_intr_iq(pi, 0)->cntxt_id; --- 17 unchanged lines hidden (view full) --- 1177 int i; 1178 struct adapter *sc = pi->adapter; 1179 struct sge_rxq *rxq; 1180 struct sge_txq *txq; 1181#ifdef TCP_OFFLOAD 1182 struct sge_ofld_rxq *ofld_rxq; 1183 struct sge_wrq *ofld_txq; 1184#endif |
1185#ifdef DEV_NETMAP 1186 struct sge_nm_rxq *nm_rxq; 1187 struct sge_nm_txq *nm_txq; 1188#endif |
|
1140 1141 /* Do this before freeing the queues */ 1142 if (pi->flags & PORT_SYSCTL_CTX) { 1143 sysctl_ctx_free(&pi->ctx); 1144 pi->flags &= ~PORT_SYSCTL_CTX; 1145 } 1146 1147 /* 1148 * Take down all the tx queues first, as they reference the rx queues 1149 * (for egress updates, etc.). 1150 */ 1151 1152 free_wrq(sc, &sc->sge.ctrlq[pi->port_id]); 1153 1154 for_each_txq(pi, i, txq) { 1155 free_txq(pi, txq); 1156 } | 1189 1190 /* Do this before freeing the queues */ 1191 if (pi->flags & PORT_SYSCTL_CTX) { 1192 sysctl_ctx_free(&pi->ctx); 1193 pi->flags &= ~PORT_SYSCTL_CTX; 1194 } 1195 1196 /* 1197 * Take down all the tx queues first, as they reference the rx queues 1198 * (for egress updates, etc.). 1199 */ 1200 1201 free_wrq(sc, &sc->sge.ctrlq[pi->port_id]); 1202 1203 for_each_txq(pi, i, txq) { 1204 free_txq(pi, txq); 1205 } |
1157 | |
1158#ifdef TCP_OFFLOAD 1159 for_each_ofld_txq(pi, i, ofld_txq) { 1160 free_wrq(sc, ofld_txq); 1161 } 1162#endif | 1206#ifdef TCP_OFFLOAD 1207 for_each_ofld_txq(pi, i, ofld_txq) { 1208 free_wrq(sc, ofld_txq); 1209 } 1210#endif |
1211#ifdef DEV_NETMAP 1212 for_each_nm_txq(pi, i, nm_txq) 1213 free_nm_txq(pi, nm_txq); 1214#endif |
|
1163 1164 /* 1165 * Then take down the rx queues that forward their interrupts, as they 1166 * reference other rx queues. 1167 */ 1168 1169 for_each_rxq(pi, i, rxq) { 1170 if ((rxq->iq.flags & IQ_INTR) == 0) 1171 free_rxq(pi, rxq); 1172 } | 1215 1216 /* 1217 * Then take down the rx queues that forward their interrupts, as they 1218 * reference other rx queues. 1219 */ 1220 1221 for_each_rxq(pi, i, rxq) { 1222 if ((rxq->iq.flags & IQ_INTR) == 0) 1223 free_rxq(pi, rxq); 1224 } |
1173 | |
1174#ifdef TCP_OFFLOAD 1175 for_each_ofld_rxq(pi, i, ofld_rxq) { 1176 if ((ofld_rxq->iq.flags & IQ_INTR) == 0) 1177 free_ofld_rxq(pi, ofld_rxq); 1178 } 1179#endif | 1225#ifdef TCP_OFFLOAD 1226 for_each_ofld_rxq(pi, i, ofld_rxq) { 1227 if ((ofld_rxq->iq.flags & IQ_INTR) == 0) 1228 free_ofld_rxq(pi, ofld_rxq); 1229 } 1230#endif |
1231#ifdef DEV_NETMAP 1232 for_each_nm_rxq(pi, i, nm_rxq) 1233 free_nm_rxq(pi, nm_rxq); 1234#endif |
|
1180 1181 /* 1182 * Then take down the rx queues that take direct interrupts. 1183 */ 1184 1185 for_each_rxq(pi, i, rxq) { 1186 if (rxq->iq.flags & IQ_INTR) 1187 free_rxq(pi, rxq); 1188 } | 1235 1236 /* 1237 * Then take down the rx queues that take direct interrupts. 1238 */ 1239 1240 for_each_rxq(pi, i, rxq) { 1241 if (rxq->iq.flags & IQ_INTR) 1242 free_rxq(pi, rxq); 1243 } |
1189 | |
1190#ifdef TCP_OFFLOAD 1191 for_each_ofld_rxq(pi, i, ofld_rxq) { 1192 if (ofld_rxq->iq.flags & IQ_INTR) 1193 free_ofld_rxq(pi, ofld_rxq); 1194 } 1195#endif | 1244#ifdef TCP_OFFLOAD 1245 for_each_ofld_rxq(pi, i, ofld_rxq) { 1246 if (ofld_rxq->iq.flags & IQ_INTR) 1247 free_ofld_rxq(pi, ofld_rxq); 1248 } 1249#endif |
1250#ifdef DEV_NETMAP 1251 CXGBE_UNIMPLEMENTED(__func__); 1252#endif |
|
1196 1197 return (0); 1198} 1199 1200/* 1201 * Deals with errors and the firmware event queue. All data rx queues forward 1202 * their interrupt to the firmware event queue. 1203 */ --- 45 unchanged lines hidden (view full) --- 1249/* 1250 * Deals with anything and everything on the given ingress queue. 1251 */ 1252static int 1253service_iq(struct sge_iq *iq, int budget) 1254{ 1255 struct sge_iq *q; 1256 struct sge_rxq *rxq = iq_to_rxq(iq); /* Use iff iq is part of rxq */ | 1253 1254 return (0); 1255} 1256 1257/* 1258 * Deals with errors and the firmware event queue. All data rx queues forward 1259 * their interrupt to the firmware event queue. 1260 */ --- 45 unchanged lines hidden (view full) --- 1306/* 1307 * Deals with anything and everything on the given ingress queue. 1308 */ 1309static int 1310service_iq(struct sge_iq *iq, int budget) 1311{ 1312 struct sge_iq *q; 1313 struct sge_rxq *rxq = iq_to_rxq(iq); /* Use iff iq is part of rxq */ |
1257 struct sge_fl *fl = &rxq->fl; /* Use iff IQ_HAS_FL */ | 1314 struct sge_fl *fl; /* Use iff IQ_HAS_FL */ |
1258 struct adapter *sc = iq->adapter; | 1315 struct adapter *sc = iq->adapter; |
1259 struct rsp_ctrl *ctrl; 1260 const struct rss_header *rss; 1261 int ndescs = 0, limit, fl_bufs_used = 0; 1262 int rsp_type; | 1316 struct iq_desc *d = &iq->desc[iq->cidx]; 1317 int ndescs = 0, limit; 1318 int rsp_type, refill; |
1263 uint32_t lq; | 1319 uint32_t lq; |
1320 uint16_t fl_hw_cidx; |
|
1264 struct mbuf *m0; 1265 STAILQ_HEAD(, sge_iq) iql = STAILQ_HEAD_INITIALIZER(iql); 1266#if defined(INET) || defined(INET6) 1267 const struct timeval lro_timeout = {0, sc->lro_timeout}; 1268#endif 1269 | 1321 struct mbuf *m0; 1322 STAILQ_HEAD(, sge_iq) iql = STAILQ_HEAD_INITIALIZER(iql); 1323#if defined(INET) || defined(INET6) 1324 const struct timeval lro_timeout = {0, sc->lro_timeout}; 1325#endif 1326 |
1270 limit = budget ? budget : iq->qsize / 8; 1271 | |
1272 KASSERT(iq->state == IQS_BUSY, ("%s: iq %p not BUSY", __func__, iq)); 1273 | 1327 KASSERT(iq->state == IQS_BUSY, ("%s: iq %p not BUSY", __func__, iq)); 1328 |
1329 limit = budget ? budget : iq->qsize / 16; 1330 1331 if (iq->flags & IQ_HAS_FL) { 1332 fl = &rxq->fl; 1333 fl_hw_cidx = fl->hw_cidx; /* stable snapshot */ 1334 } else { 1335 fl = NULL; 1336 fl_hw_cidx = 0; /* to silence gcc warning */ 1337 } 1338 |
|
1274 /* 1275 * We always come back and check the descriptor ring for new indirect 1276 * interrupts and other responses after running a single handler. 1277 */ 1278 for (;;) { | 1339 /* 1340 * We always come back and check the descriptor ring for new indirect 1341 * interrupts and other responses after running a single handler. 1342 */ 1343 for (;;) { |
1279 while (is_new_response(iq, &ctrl)) { | 1344 while ((d->rsp.u.type_gen & F_RSPD_GEN) == iq->gen) { |
1280 1281 rmb(); 1282 | 1345 1346 rmb(); 1347 |
1348 refill = 0; |
|
1283 m0 = NULL; | 1349 m0 = NULL; |
1284 rsp_type = G_RSPD_TYPE(ctrl->u.type_gen); 1285 lq = be32toh(ctrl->pldbuflen_qid); 1286 rss = (const void *)iq->cdesc; | 1350 rsp_type = G_RSPD_TYPE(d->rsp.u.type_gen); 1351 lq = be32toh(d->rsp.pldbuflen_qid); |
1287 1288 switch (rsp_type) { 1289 case X_RSPD_TYPE_FLBUF: 1290 1291 KASSERT(iq->flags & IQ_HAS_FL, 1292 ("%s: data for an iq (%p) with no freelist", 1293 __func__, iq)); 1294 | 1352 1353 switch (rsp_type) { 1354 case X_RSPD_TYPE_FLBUF: 1355 1356 KASSERT(iq->flags & IQ_HAS_FL, 1357 ("%s: data for an iq (%p) with no freelist", 1358 __func__, iq)); 1359 |
1295 m0 = get_fl_payload(sc, fl, lq, &fl_bufs_used); | 1360 m0 = get_fl_payload(sc, fl, lq); |
1296 if (__predict_false(m0 == NULL)) 1297 goto process_iql; | 1361 if (__predict_false(m0 == NULL)) 1362 goto process_iql; |
1363 refill = IDXDIFF(fl->hw_cidx, fl_hw_cidx, fl->sidx) > 2; |
|
1298#ifdef T4_PKT_TIMESTAMP 1299 /* 1300 * 60 bit timestamp for the payload is 1301 * *(uint64_t *)m0->m_pktdat. Note that it is 1302 * in the leading free-space in the mbuf. The 1303 * kernel can clobber it during a pullup, 1304 * m_copymdata, etc. You need to make sure that 1305 * the mbuf reaches you unmolested if you care 1306 * about the timestamp. 1307 */ 1308 *(uint64_t *)m0->m_pktdat = 1309 be64toh(ctrl->u.last_flit) & 1310 0xfffffffffffffff; 1311#endif 1312 1313 /* fall through */ 1314 1315 case X_RSPD_TYPE_CPL: | 1364#ifdef T4_PKT_TIMESTAMP 1365 /* 1366 * 60 bit timestamp for the payload is 1367 * *(uint64_t *)m0->m_pktdat. Note that it is 1368 * in the leading free-space in the mbuf. The 1369 * kernel can clobber it during a pullup, 1370 * m_copymdata, etc. You need to make sure that 1371 * the mbuf reaches you unmolested if you care 1372 * about the timestamp. 1373 */ 1374 *(uint64_t *)m0->m_pktdat = 1375 be64toh(ctrl->u.last_flit) & 1376 0xfffffffffffffff; 1377#endif 1378 1379 /* fall through */ 1380 1381 case X_RSPD_TYPE_CPL: |
1316 KASSERT(rss->opcode < NUM_CPL_CMDS, | 1382 KASSERT(d->rss.opcode < NUM_CPL_CMDS, |
1317 ("%s: bad opcode %02x.", __func__, | 1383 ("%s: bad opcode %02x.", __func__, |
1318 rss->opcode)); 1319 sc->cpl_handler[rss->opcode](iq, rss, m0); | 1384 d->rss.opcode)); 1385 sc->cpl_handler[d->rss.opcode](iq, &d->rss, m0); |
1320 break; 1321 1322 case X_RSPD_TYPE_INTR: 1323 1324 /* 1325 * Interrupts should be forwarded only to queues 1326 * that are not forwarding their interrupts. 1327 * This means service_iq can recurse but only 1 --- 5 unchanged lines hidden (view full) --- 1333 1334 /* 1335 * There are 1K interrupt-capable queues (qids 0 1336 * through 1023). A response type indicating a 1337 * forwarded interrupt with a qid >= 1K is an 1338 * iWARP async notification. 1339 */ 1340 if (lq >= 1024) { | 1386 break; 1387 1388 case X_RSPD_TYPE_INTR: 1389 1390 /* 1391 * Interrupts should be forwarded only to queues 1392 * that are not forwarding their interrupts. 1393 * This means service_iq can recurse but only 1 --- 5 unchanged lines hidden (view full) --- 1399 1400 /* 1401 * There are 1K interrupt-capable queues (qids 0 1402 * through 1023). A response type indicating a 1403 * forwarded interrupt with a qid >= 1K is an 1404 * iWARP async notification. 1405 */ 1406 if (lq >= 1024) { |
1341 sc->an_handler(iq, ctrl); | 1407 sc->an_handler(iq, &d->rsp); |
1342 break; 1343 } 1344 1345 q = sc->sge.iqmap[lq - sc->sge.iq_start]; 1346 if (atomic_cmpset_int(&q->state, IQS_IDLE, 1347 IQS_BUSY)) { | 1408 break; 1409 } 1410 1411 q = sc->sge.iqmap[lq - sc->sge.iq_start]; 1412 if (atomic_cmpset_int(&q->state, IQS_IDLE, 1413 IQS_BUSY)) { |
1348 if (service_iq(q, q->qsize / 8) == 0) { | 1414 if (service_iq(q, q->qsize / 16) == 0) { |
1349 atomic_cmpset_int(&q->state, 1350 IQS_BUSY, IQS_IDLE); 1351 } else { 1352 STAILQ_INSERT_TAIL(&iql, q, 1353 link); 1354 } 1355 } 1356 break; 1357 1358 default: 1359 KASSERT(0, 1360 ("%s: illegal response type %d on iq %p", 1361 __func__, rsp_type, iq)); 1362 log(LOG_ERR, 1363 "%s: illegal response type %d on iq %p", 1364 device_get_nameunit(sc->dev), rsp_type, iq); 1365 break; 1366 } 1367 | 1415 atomic_cmpset_int(&q->state, 1416 IQS_BUSY, IQS_IDLE); 1417 } else { 1418 STAILQ_INSERT_TAIL(&iql, q, 1419 link); 1420 } 1421 } 1422 break; 1423 1424 default: 1425 KASSERT(0, 1426 ("%s: illegal response type %d on iq %p", 1427 __func__, rsp_type, iq)); 1428 log(LOG_ERR, 1429 "%s: illegal response type %d on iq %p", 1430 device_get_nameunit(sc->dev), rsp_type, iq); 1431 break; 1432 } 1433 |
1368 if (fl_bufs_used >= 16) { 1369 FL_LOCK(fl); 1370 fl->needed += fl_bufs_used; 1371 refill_fl(sc, fl, 32); 1372 FL_UNLOCK(fl); 1373 fl_bufs_used = 0; | 1434 d++; 1435 if (__predict_false(++iq->cidx == iq->sidx)) { 1436 iq->cidx = 0; 1437 iq->gen ^= F_RSPD_GEN; 1438 d = &iq->desc[0]; |
1374 } | 1439 } |
1375 1376 iq_next(iq); 1377 if (++ndescs == limit) { | 1440 if (__predict_false(++ndescs == limit)) { |
1378 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), 1379 V_CIDXINC(ndescs) | 1380 V_INGRESSQID(iq->cntxt_id) | 1381 V_SEINTARM(V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX))); 1382 ndescs = 0; 1383 1384#if defined(INET) || defined(INET6) 1385 if (iq->flags & IQ_LRO_ENABLED && 1386 sc->lro_timeout != 0) { 1387 tcp_lro_flush_inactive(&rxq->lro, 1388 &lro_timeout); 1389 } 1390#endif 1391 1392 if (budget) { | 1441 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), 1442 V_CIDXINC(ndescs) | 1443 V_INGRESSQID(iq->cntxt_id) | 1444 V_SEINTARM(V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX))); 1445 ndescs = 0; 1446 1447#if defined(INET) || defined(INET6) 1448 if (iq->flags & IQ_LRO_ENABLED && 1449 sc->lro_timeout != 0) { 1450 tcp_lro_flush_inactive(&rxq->lro, 1451 &lro_timeout); 1452 } 1453#endif 1454 1455 if (budget) { |
1393 if (fl_bufs_used) { | 1456 if (iq->flags & IQ_HAS_FL) { |
1394 FL_LOCK(fl); | 1457 FL_LOCK(fl); |
1395 fl->needed += fl_bufs_used; | |
1396 refill_fl(sc, fl, 32); 1397 FL_UNLOCK(fl); 1398 } 1399 return (EINPROGRESS); 1400 } 1401 } | 1458 refill_fl(sc, fl, 32); 1459 FL_UNLOCK(fl); 1460 } 1461 return (EINPROGRESS); 1462 } 1463 } |
1464 if (refill) { 1465 FL_LOCK(fl); 1466 refill_fl(sc, fl, 32); 1467 FL_UNLOCK(fl); 1468 fl_hw_cidx = fl->hw_cidx; 1469 } |
|
1402 } 1403 1404process_iql: 1405 if (STAILQ_EMPTY(&iql)) 1406 break; 1407 1408 /* 1409 * Process the head only, and send it to the back of the list if --- 22 unchanged lines hidden (view full) --- 1432 1433 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndescs) | 1434 V_INGRESSQID((u32)iq->cntxt_id) | V_SEINTARM(iq->intr_params)); 1435 1436 if (iq->flags & IQ_HAS_FL) { 1437 int starved; 1438 1439 FL_LOCK(fl); | 1470 } 1471 1472process_iql: 1473 if (STAILQ_EMPTY(&iql)) 1474 break; 1475 1476 /* 1477 * Process the head only, and send it to the back of the list if --- 22 unchanged lines hidden (view full) --- 1500 1501 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndescs) | 1502 V_INGRESSQID((u32)iq->cntxt_id) | V_SEINTARM(iq->intr_params)); 1503 1504 if (iq->flags & IQ_HAS_FL) { 1505 int starved; 1506 1507 FL_LOCK(fl); |
1440 fl->needed += fl_bufs_used; | |
1441 starved = refill_fl(sc, fl, 64); 1442 FL_UNLOCK(fl); 1443 if (__predict_false(starved != 0)) 1444 add_fl_to_sfl(sc, fl); 1445 } 1446 1447 return (0); 1448} --- 52 unchanged lines hidden (view full) --- 1501 struct cluster_layout *cll = &sd->cll; 1502 struct sw_zone_info *swz = &sc->sge.sw_zone_info[cll->zidx]; 1503 struct hw_buf_info *hwb = &sc->sge.hw_buf_info[cll->hwidx]; 1504 struct cluster_metadata *clm = cl_metadata(sc, fl, cll, sd->cl); 1505 int len, padded_len; 1506 caddr_t payload; 1507 1508 len = min(total, hwb->size - fl->rx_offset); | 1508 starved = refill_fl(sc, fl, 64); 1509 FL_UNLOCK(fl); 1510 if (__predict_false(starved != 0)) 1511 add_fl_to_sfl(sc, fl); 1512 } 1513 1514 return (0); 1515} --- 52 unchanged lines hidden (view full) --- 1568 struct cluster_layout *cll = &sd->cll; 1569 struct sw_zone_info *swz = &sc->sge.sw_zone_info[cll->zidx]; 1570 struct hw_buf_info *hwb = &sc->sge.hw_buf_info[cll->hwidx]; 1571 struct cluster_metadata *clm = cl_metadata(sc, fl, cll, sd->cl); 1572 int len, padded_len; 1573 caddr_t payload; 1574 1575 len = min(total, hwb->size - fl->rx_offset); |
1509 padded_len = roundup2(len, fl_pad); | 1576 padded_len = roundup2(len, fl->buf_boundary); |
1510 payload = sd->cl + cll->region1 + fl->rx_offset; 1511 1512 if (sc->sc_do_rxcopy && len < RX_COPY_THRESHOLD) { 1513 1514 /* 1515 * Copy payload into a freshly allocated mbuf. 1516 */ 1517 --- 49 unchanged lines hidden (view full) --- 1567 sd->cl = NULL; /* consumed, not a recycle candidate */ 1568 } 1569 } 1570 if (flags & M_PKTHDR) 1571 m->m_pkthdr.len = total; 1572 m->m_len = len; 1573 1574 if (fl->flags & FL_BUF_PACKING) { | 1577 payload = sd->cl + cll->region1 + fl->rx_offset; 1578 1579 if (sc->sc_do_rxcopy && len < RX_COPY_THRESHOLD) { 1580 1581 /* 1582 * Copy payload into a freshly allocated mbuf. 1583 */ 1584 --- 49 unchanged lines hidden (view full) --- 1634 sd->cl = NULL; /* consumed, not a recycle candidate */ 1635 } 1636 } 1637 if (flags & M_PKTHDR) 1638 m->m_pkthdr.len = total; 1639 m->m_len = len; 1640 1641 if (fl->flags & FL_BUF_PACKING) { |
1575 fl->rx_offset += roundup2(padded_len, sc->sge.pack_boundary); | 1642 fl->rx_offset += padded_len; |
1576 MPASS(fl->rx_offset <= hwb->size); 1577 if (fl->rx_offset < hwb->size) 1578 return (m); /* without advancing the cidx */ 1579 } 1580 | 1643 MPASS(fl->rx_offset <= hwb->size); 1644 if (fl->rx_offset < hwb->size) 1645 return (m); /* without advancing the cidx */ 1646 } 1647 |
1581 if (__predict_false(++fl->cidx == fl->cap)) 1582 fl->cidx = 0; | 1648 if (__predict_false(++fl->cidx % 8 == 0)) { 1649 uint16_t cidx = fl->cidx / 8; 1650 1651 if (__predict_false(cidx == fl->sidx)) 1652 fl->cidx = cidx = 0; 1653 fl->hw_cidx = cidx; 1654 } |
1583 fl->rx_offset = 0; 1584 1585 return (m); 1586} 1587 1588static struct mbuf * | 1655 fl->rx_offset = 0; 1656 1657 return (m); 1658} 1659 1660static struct mbuf * |
1589get_fl_payload(struct adapter *sc, struct sge_fl *fl, uint32_t len_newbuf, 1590 int *fl_bufs_used) | 1661get_fl_payload(struct adapter *sc, struct sge_fl *fl, uint32_t len_newbuf) |
1591{ 1592 struct mbuf *m0, *m, **pnext; | 1662{ 1663 struct mbuf *m0, *m, **pnext; |
1593 u_int nbuf, len; | 1664 u_int len; |
1594 | 1665 |
1595 /* 1596 * No assertion for the fl lock because we don't need it. This routine 1597 * is called only from the rx interrupt handler and it only updates 1598 * fl->cidx. (Contrast that with fl->pidx/fl->needed which could be 1599 * updated in the rx interrupt handler or the starvation helper routine. 1600 * That's why code that manipulates fl->pidx/fl->needed needs the fl 1601 * lock but this routine does not). 1602 */ 1603 1604 nbuf = 0; | |
1605 len = G_RSPD_LEN(len_newbuf); | 1666 len = G_RSPD_LEN(len_newbuf); |
1606 if (__predict_false(fl->m0 != NULL)) { | 1667 if (__predict_false(fl->flags & FL_BUF_RESUME)) { |
1607 M_ASSERTPKTHDR(fl->m0); 1608 MPASS(len == fl->m0->m_pkthdr.len); 1609 MPASS(fl->remaining < len); 1610 1611 m0 = fl->m0; 1612 pnext = fl->pnext; 1613 len = fl->remaining; | 1668 M_ASSERTPKTHDR(fl->m0); 1669 MPASS(len == fl->m0->m_pkthdr.len); 1670 MPASS(fl->remaining < len); 1671 1672 m0 = fl->m0; 1673 pnext = fl->pnext; 1674 len = fl->remaining; |
1614 fl->m0 = NULL; | 1675 fl->flags &= ~FL_BUF_RESUME; |
1615 goto get_segment; 1616 } 1617 1618 if (fl->rx_offset > 0 && len_newbuf & F_RSPD_NEWBUF) { | 1676 goto get_segment; 1677 } 1678 1679 if (fl->rx_offset > 0 && len_newbuf & F_RSPD_NEWBUF) { |
1619 nbuf++; | |
1620 fl->rx_offset = 0; | 1680 fl->rx_offset = 0; |
1621 if (__predict_false(++fl->cidx == fl->cap)) 1622 fl->cidx = 0; | 1681 if (__predict_false(++fl->cidx % 8 == 0)) { 1682 uint16_t cidx = fl->cidx / 8; 1683 1684 if (__predict_false(cidx == fl->sidx)) 1685 fl->cidx = cidx = 0; 1686 fl->hw_cidx = cidx; 1687 } |
1623 } 1624 1625 /* 1626 * Payload starts at rx_offset in the current hw buffer. Its length is 1627 * 'len' and it may span multiple hw buffers. 1628 */ 1629 1630 m0 = get_scatter_segment(sc, fl, len, M_PKTHDR); 1631 if (m0 == NULL) | 1688 } 1689 1690 /* 1691 * Payload starts at rx_offset in the current hw buffer. Its length is 1692 * 'len' and it may span multiple hw buffers. 1693 */ 1694 1695 m0 = get_scatter_segment(sc, fl, len, M_PKTHDR); 1696 if (m0 == NULL) |
1632 goto done; | 1697 return (NULL); |
1633 len -= m0->m_len; 1634 pnext = &m0->m_next; 1635 while (len > 0) { | 1698 len -= m0->m_len; 1699 pnext = &m0->m_next; 1700 while (len > 0) { |
1636 nbuf++; | |
1637get_segment: 1638 MPASS(fl->rx_offset == 0); 1639 m = get_scatter_segment(sc, fl, len, 0); | 1701get_segment: 1702 MPASS(fl->rx_offset == 0); 1703 m = get_scatter_segment(sc, fl, len, 0); |
1640 if (m == NULL) { | 1704 if (__predict_false(m == NULL)) { |
1641 fl->m0 = m0; 1642 fl->pnext = pnext; 1643 fl->remaining = len; | 1705 fl->m0 = m0; 1706 fl->pnext = pnext; 1707 fl->remaining = len; |
1644 m0 = NULL; 1645 goto done; | 1708 fl->flags |= FL_BUF_RESUME; 1709 return (NULL); |
1646 } 1647 *pnext = m; 1648 pnext = &m->m_next; 1649 len -= m->m_len; 1650 } 1651 *pnext = NULL; | 1710 } 1711 *pnext = m; 1712 pnext = &m->m_next; 1713 len -= m->m_len; 1714 } 1715 *pnext = NULL; |
1652 if (fl->rx_offset == 0) 1653 nbuf++; 1654done: 1655 (*fl_bufs_used) += nbuf; | 1716 |
1656 return (m0); 1657} 1658 1659static int 1660t4_eth_rx(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m0) 1661{ 1662 struct sge_rxq *rxq = iq_to_rxq(iq); 1663 struct ifnet *ifp = rxq->ifp; --- 371 unchanged lines hidden (view full) --- 2035can_resume_tx(struct sge_eq *eq) 2036{ 2037 2038 return (eq->avail + reclaimable(eq) >= tx_resume_threshold(eq)); 2039} 2040 2041static inline void 2042init_iq(struct sge_iq *iq, struct adapter *sc, int tmr_idx, int pktc_idx, | 1717 return (m0); 1718} 1719 1720static int 1721t4_eth_rx(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m0) 1722{ 1723 struct sge_rxq *rxq = iq_to_rxq(iq); 1724 struct ifnet *ifp = rxq->ifp; --- 371 unchanged lines hidden (view full) --- 2096can_resume_tx(struct sge_eq *eq) 2097{ 2098 2099 return (eq->avail + reclaimable(eq) >= tx_resume_threshold(eq)); 2100} 2101 2102static inline void 2103init_iq(struct sge_iq *iq, struct adapter *sc, int tmr_idx, int pktc_idx, |
2043 int qsize, int esize) | 2104 int qsize) |
2044{ | 2105{ |
2106 |
|
2045 KASSERT(tmr_idx >= 0 && tmr_idx < SGE_NTIMERS, 2046 ("%s: bad tmr_idx %d", __func__, tmr_idx)); 2047 KASSERT(pktc_idx < SGE_NCOUNTERS, /* -ve is ok, means don't use */ 2048 ("%s: bad pktc_idx %d", __func__, pktc_idx)); 2049 2050 iq->flags = 0; 2051 iq->adapter = sc; 2052 iq->intr_params = V_QINTR_TIMER_IDX(tmr_idx); 2053 iq->intr_pktc_idx = SGE_NCOUNTERS - 1; 2054 if (pktc_idx >= 0) { 2055 iq->intr_params |= F_QINTR_CNT_EN; 2056 iq->intr_pktc_idx = pktc_idx; 2057 } 2058 iq->qsize = roundup2(qsize, 16); /* See FW_IQ_CMD/iqsize */ | 2107 KASSERT(tmr_idx >= 0 && tmr_idx < SGE_NTIMERS, 2108 ("%s: bad tmr_idx %d", __func__, tmr_idx)); 2109 KASSERT(pktc_idx < SGE_NCOUNTERS, /* -ve is ok, means don't use */ 2110 ("%s: bad pktc_idx %d", __func__, pktc_idx)); 2111 2112 iq->flags = 0; 2113 iq->adapter = sc; 2114 iq->intr_params = V_QINTR_TIMER_IDX(tmr_idx); 2115 iq->intr_pktc_idx = SGE_NCOUNTERS - 1; 2116 if (pktc_idx >= 0) { 2117 iq->intr_params |= F_QINTR_CNT_EN; 2118 iq->intr_pktc_idx = pktc_idx; 2119 } 2120 iq->qsize = roundup2(qsize, 16); /* See FW_IQ_CMD/iqsize */ |
2059 iq->esize = max(esize, 16); /* See FW_IQ_CMD/iqesize */ | 2121 iq->sidx = iq->qsize - spg_len / IQ_ESIZE; |
2060} 2061 2062static inline void 2063init_fl(struct adapter *sc, struct sge_fl *fl, int qsize, int maxp, int pack, 2064 char *name) 2065{ 2066 2067 fl->qsize = qsize; | 2122} 2123 2124static inline void 2125init_fl(struct adapter *sc, struct sge_fl *fl, int qsize, int maxp, int pack, 2126 char *name) 2127{ 2128 2129 fl->qsize = qsize; |
2130 fl->sidx = qsize - spg_len / EQ_ESIZE; |
|
2068 strlcpy(fl->lockname, name, sizeof(fl->lockname)); 2069 if (pack) 2070 fl->flags |= FL_BUF_PACKING; 2071 find_best_refill_source(sc, fl, maxp); 2072 find_safe_refill_source(sc, fl); 2073} 2074 2075static inline void --- 76 unchanged lines hidden (view full) --- 2152 int intr_idx, int cong) 2153{ 2154 int rc, i, cntxt_id; 2155 size_t len; 2156 struct fw_iq_cmd c; 2157 struct adapter *sc = iq->adapter; 2158 __be32 v = 0; 2159 | 2131 strlcpy(fl->lockname, name, sizeof(fl->lockname)); 2132 if (pack) 2133 fl->flags |= FL_BUF_PACKING; 2134 find_best_refill_source(sc, fl, maxp); 2135 find_safe_refill_source(sc, fl); 2136} 2137 2138static inline void --- 76 unchanged lines hidden (view full) --- 2215 int intr_idx, int cong) 2216{ 2217 int rc, i, cntxt_id; 2218 size_t len; 2219 struct fw_iq_cmd c; 2220 struct adapter *sc = iq->adapter; 2221 __be32 v = 0; 2222 |
2160 len = iq->qsize * iq->esize; | 2223 len = iq->qsize * IQ_ESIZE; |
2161 rc = alloc_ring(sc, len, &iq->desc_tag, &iq->desc_map, &iq->ba, 2162 (void **)&iq->desc); 2163 if (rc != 0) 2164 return (rc); 2165 2166 bzero(&c, sizeof(c)); 2167 c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST | 2168 F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(sc->pf) | --- 15 unchanged lines hidden (view full) --- 2184 2185 c.type_to_iqandstindex = htobe32(v | 2186 V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) | 2187 V_FW_IQ_CMD_VIID(pi->viid) | 2188 V_FW_IQ_CMD_IQANUD(X_UPDATEDELIVERY_INTERRUPT)); 2189 c.iqdroprss_to_iqesize = htobe16(V_FW_IQ_CMD_IQPCIECH(pi->tx_chan) | 2190 F_FW_IQ_CMD_IQGTSMODE | 2191 V_FW_IQ_CMD_IQINTCNTTHRESH(iq->intr_pktc_idx) | | 2224 rc = alloc_ring(sc, len, &iq->desc_tag, &iq->desc_map, &iq->ba, 2225 (void **)&iq->desc); 2226 if (rc != 0) 2227 return (rc); 2228 2229 bzero(&c, sizeof(c)); 2230 c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST | 2231 F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(sc->pf) | --- 15 unchanged lines hidden (view full) --- 2247 2248 c.type_to_iqandstindex = htobe32(v | 2249 V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) | 2250 V_FW_IQ_CMD_VIID(pi->viid) | 2251 V_FW_IQ_CMD_IQANUD(X_UPDATEDELIVERY_INTERRUPT)); 2252 c.iqdroprss_to_iqesize = htobe16(V_FW_IQ_CMD_IQPCIECH(pi->tx_chan) | 2253 F_FW_IQ_CMD_IQGTSMODE | 2254 V_FW_IQ_CMD_IQINTCNTTHRESH(iq->intr_pktc_idx) | |
2192 V_FW_IQ_CMD_IQESIZE(ilog2(iq->esize) - 4)); | 2255 V_FW_IQ_CMD_IQESIZE(ilog2(IQ_ESIZE) - 4)); |
2193 c.iqsize = htobe16(iq->qsize); 2194 c.iqaddr = htobe64(iq->ba); 2195 if (cong >= 0) 2196 c.iqns_to_fl0congen = htobe32(F_FW_IQ_CMD_IQFLINTCONGEN); 2197 2198 if (fl) { 2199 mtx_init(&fl->fl_lock, fl->lockname, NULL, MTX_DEF); 2200 | 2256 c.iqsize = htobe16(iq->qsize); 2257 c.iqaddr = htobe64(iq->ba); 2258 if (cong >= 0) 2259 c.iqns_to_fl0congen = htobe32(F_FW_IQ_CMD_IQFLINTCONGEN); 2260 2261 if (fl) { 2262 mtx_init(&fl->fl_lock, fl->lockname, NULL, MTX_DEF); 2263 |
2201 len = fl->qsize * RX_FL_ESIZE; | 2264 len = fl->qsize * EQ_ESIZE; |
2202 rc = alloc_ring(sc, len, &fl->desc_tag, &fl->desc_map, 2203 &fl->ba, (void **)&fl->desc); 2204 if (rc) 2205 return (rc); 2206 2207 /* Allocate space for one software descriptor per buffer. */ | 2265 rc = alloc_ring(sc, len, &fl->desc_tag, &fl->desc_map, 2266 &fl->ba, (void **)&fl->desc); 2267 if (rc) 2268 return (rc); 2269 2270 /* Allocate space for one software descriptor per buffer. */ |
2208 fl->cap = (fl->qsize - spg_len / RX_FL_ESIZE) * 8; | |
2209 rc = alloc_fl_sdesc(fl); 2210 if (rc != 0) { 2211 device_printf(sc->dev, 2212 "failed to setup fl software descriptors: %d\n", 2213 rc); 2214 return (rc); 2215 } | 2271 rc = alloc_fl_sdesc(fl); 2272 if (rc != 0) { 2273 device_printf(sc->dev, 2274 "failed to setup fl software descriptors: %d\n", 2275 rc); 2276 return (rc); 2277 } |
2216 fl->needed = fl->cap; 2217 fl->lowat = fl->flags & FL_BUF_PACKING ? 2218 roundup2(sc->sge.fl_starve_threshold2, 8) : 2219 roundup2(sc->sge.fl_starve_threshold, 8); | |
2220 | 2278 |
2279 if (fl->flags & FL_BUF_PACKING) { 2280 fl->lowat = roundup2(sc->sge.fl_starve_threshold2, 8); 2281 fl->buf_boundary = max(fl_pad, sc->sge.pack_boundary); 2282 } else { 2283 fl->lowat = roundup2(sc->sge.fl_starve_threshold, 8); 2284 fl->buf_boundary = fl_pad; 2285 } 2286 |
|
2221 c.iqns_to_fl0congen |= 2222 htobe32(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) | 2223 F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO | 2224 (fl_pad ? F_FW_IQ_CMD_FL0PADEN : 0) | 2225 (fl->flags & FL_BUF_PACKING ? F_FW_IQ_CMD_FL0PACKEN : 2226 0)); 2227 if (cong >= 0) { 2228 c.iqns_to_fl0congen |= --- 10 unchanged lines hidden (view full) --- 2239 2240 rc = -t4_wr_mbox(sc, sc->mbox, &c, sizeof(c), &c); 2241 if (rc != 0) { 2242 device_printf(sc->dev, 2243 "failed to create ingress queue: %d\n", rc); 2244 return (rc); 2245 } 2246 | 2287 c.iqns_to_fl0congen |= 2288 htobe32(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) | 2289 F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO | 2290 (fl_pad ? F_FW_IQ_CMD_FL0PADEN : 0) | 2291 (fl->flags & FL_BUF_PACKING ? F_FW_IQ_CMD_FL0PACKEN : 2292 0)); 2293 if (cong >= 0) { 2294 c.iqns_to_fl0congen |= --- 10 unchanged lines hidden (view full) --- 2305 2306 rc = -t4_wr_mbox(sc, sc->mbox, &c, sizeof(c), &c); 2307 if (rc != 0) { 2308 device_printf(sc->dev, 2309 "failed to create ingress queue: %d\n", rc); 2310 return (rc); 2311 } 2312 |
2247 iq->cdesc = iq->desc; | |
2248 iq->cidx = 0; | 2313 iq->cidx = 0; |
2249 iq->gen = 1; | 2314 iq->gen = F_RSPD_GEN; |
2250 iq->intr_next = iq->intr_params; 2251 iq->cntxt_id = be16toh(c.iqid); 2252 iq->abs_id = be16toh(c.physiqid); 2253 iq->flags |= IQ_ALLOCATED; 2254 2255 cntxt_id = iq->cntxt_id - sc->sge.iq_start; 2256 if (cntxt_id >= sc->sge.niq) { 2257 panic ("%s: iq->cntxt_id (%d) more than the max (%d)", __func__, 2258 cntxt_id, sc->sge.niq - 1); 2259 } 2260 sc->sge.iqmap[cntxt_id] = iq; 2261 2262 if (fl) { | 2315 iq->intr_next = iq->intr_params; 2316 iq->cntxt_id = be16toh(c.iqid); 2317 iq->abs_id = be16toh(c.physiqid); 2318 iq->flags |= IQ_ALLOCATED; 2319 2320 cntxt_id = iq->cntxt_id - sc->sge.iq_start; 2321 if (cntxt_id >= sc->sge.niq) { 2322 panic ("%s: iq->cntxt_id (%d) more than the max (%d)", __func__, 2323 cntxt_id, sc->sge.niq - 1); 2324 } 2325 sc->sge.iqmap[cntxt_id] = iq; 2326 2327 if (fl) { |
2328 u_int qid; 2329 2330 iq->flags |= IQ_HAS_FL; |
|
2263 fl->cntxt_id = be16toh(c.fl0id); 2264 fl->pidx = fl->cidx = 0; 2265 2266 cntxt_id = fl->cntxt_id - sc->sge.eq_start; 2267 if (cntxt_id >= sc->sge.neq) { 2268 panic("%s: fl->cntxt_id (%d) more than the max (%d)", 2269 __func__, cntxt_id, sc->sge.neq - 1); 2270 } 2271 sc->sge.eqmap[cntxt_id] = (void *)fl; 2272 | 2331 fl->cntxt_id = be16toh(c.fl0id); 2332 fl->pidx = fl->cidx = 0; 2333 2334 cntxt_id = fl->cntxt_id - sc->sge.eq_start; 2335 if (cntxt_id >= sc->sge.neq) { 2336 panic("%s: fl->cntxt_id (%d) more than the max (%d)", 2337 __func__, cntxt_id, sc->sge.neq - 1); 2338 } 2339 sc->sge.eqmap[cntxt_id] = (void *)fl; 2340 |
2341 qid = fl->cntxt_id; 2342 if (isset(&sc->doorbells, DOORBELL_UDB)) { 2343 uint32_t s_qpp = sc->sge.eq_s_qpp; 2344 uint32_t mask = (1 << s_qpp) - 1; 2345 volatile uint8_t *udb; 2346 2347 udb = sc->udbs_base + UDBS_DB_OFFSET; 2348 udb += (qid >> s_qpp) << PAGE_SHIFT; 2349 qid &= mask; 2350 if (qid < PAGE_SIZE / UDBS_SEG_SIZE) { 2351 udb += qid << UDBS_SEG_SHIFT; 2352 qid = 0; 2353 } 2354 fl->udb = (volatile void *)udb; 2355 } 2356 fl->dbval = F_DBPRIO | V_QID(qid); 2357 if (is_t5(sc)) 2358 fl->dbval |= F_DBTYPE; 2359 |
|
2273 FL_LOCK(fl); 2274 /* Enough to make sure the SGE doesn't think it's starved */ 2275 refill_fl(sc, fl, fl->lowat); 2276 FL_UNLOCK(fl); | 2360 FL_LOCK(fl); 2361 /* Enough to make sure the SGE doesn't think it's starved */ 2362 refill_fl(sc, fl, fl->lowat); 2363 FL_UNLOCK(fl); |
2277 2278 iq->flags |= IQ_HAS_FL; | |
2279 } 2280 2281 if (is_t5(sc) && cong >= 0) { 2282 uint32_t param, val; 2283 2284 param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | 2285 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) | 2286 V_FW_PARAMS_PARAM_YZ(iq->cntxt_id); --- 104 unchanged lines hidden (view full) --- 2391static int 2392alloc_fwq(struct adapter *sc) 2393{ 2394 int rc, intr_idx; 2395 struct sge_iq *fwq = &sc->sge.fwq; 2396 struct sysctl_oid *oid = device_get_sysctl_tree(sc->dev); 2397 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid); 2398 | 2364 } 2365 2366 if (is_t5(sc) && cong >= 0) { 2367 uint32_t param, val; 2368 2369 param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | 2370 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) | 2371 V_FW_PARAMS_PARAM_YZ(iq->cntxt_id); --- 104 unchanged lines hidden (view full) --- 2476static int 2477alloc_fwq(struct adapter *sc) 2478{ 2479 int rc, intr_idx; 2480 struct sge_iq *fwq = &sc->sge.fwq; 2481 struct sysctl_oid *oid = device_get_sysctl_tree(sc->dev); 2482 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid); 2483 |
2399 init_iq(fwq, sc, 0, 0, FW_IQ_QSIZE, FW_IQ_ESIZE); | 2484 init_iq(fwq, sc, 0, 0, FW_IQ_QSIZE); |
2400 fwq->flags |= IQ_INTR; /* always */ 2401 intr_idx = sc->intr_count > 1 ? 1 : 0; 2402 rc = alloc_iq_fl(sc->port[0], fwq, NULL, intr_idx, -1); 2403 if (rc != 0) { 2404 device_printf(sc->dev, 2405 "failed to create firmware event queue: %d\n", rc); 2406 return (rc); 2407 } --- 72 unchanged lines hidden (view full) --- 2480 int rc; 2481 struct sysctl_oid_list *children; 2482 char name[16]; 2483 2484 rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, tnl_cong(pi)); 2485 if (rc != 0) 2486 return (rc); 2487 | 2485 fwq->flags |= IQ_INTR; /* always */ 2486 intr_idx = sc->intr_count > 1 ? 1 : 0; 2487 rc = alloc_iq_fl(sc->port[0], fwq, NULL, intr_idx, -1); 2488 if (rc != 0) { 2489 device_printf(sc->dev, 2490 "failed to create firmware event queue: %d\n", rc); 2491 return (rc); 2492 } --- 72 unchanged lines hidden (view full) --- 2565 int rc; 2566 struct sysctl_oid_list *children; 2567 char name[16]; 2568 2569 rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, tnl_cong(pi)); 2570 if (rc != 0) 2571 return (rc); 2572 |
2573 /* 2574 * The freelist is just barely above the starvation threshold right now, 2575 * fill it up a bit more. 2576 */ |
|
2488 FL_LOCK(&rxq->fl); | 2577 FL_LOCK(&rxq->fl); |
2489 refill_fl(pi->adapter, &rxq->fl, rxq->fl.needed / 8); | 2578 refill_fl(pi->adapter, &rxq->fl, 128); |
2490 FL_UNLOCK(&rxq->fl); 2491 2492#if defined(INET) || defined(INET6) 2493 rc = tcp_lro_init(&rxq->lro); 2494 if (rc != 0) 2495 return (rc); 2496 rxq->lro.ifp = pi->ifp; /* also indicates LRO init'ed */ 2497 --- 98 unchanged lines hidden (view full) --- 2596 rc = free_iq_fl(pi, &ofld_rxq->iq, &ofld_rxq->fl); 2597 if (rc == 0) 2598 bzero(ofld_rxq, sizeof(*ofld_rxq)); 2599 2600 return (rc); 2601} 2602#endif 2603 | 2579 FL_UNLOCK(&rxq->fl); 2580 2581#if defined(INET) || defined(INET6) 2582 rc = tcp_lro_init(&rxq->lro); 2583 if (rc != 0) 2584 return (rc); 2585 rxq->lro.ifp = pi->ifp; /* also indicates LRO init'ed */ 2586 --- 98 unchanged lines hidden (view full) --- 2685 rc = free_iq_fl(pi, &ofld_rxq->iq, &ofld_rxq->fl); 2686 if (rc == 0) 2687 bzero(ofld_rxq, sizeof(*ofld_rxq)); 2688 2689 return (rc); 2690} 2691#endif 2692 |
2693#ifdef DEV_NETMAP |
|
2604static int | 2694static int |
2695alloc_nm_rxq(struct port_info *pi, struct sge_nm_rxq *nm_rxq, int intr_idx, 2696 int idx, struct sysctl_oid *oid) 2697{ 2698 int rc; 2699 struct sysctl_oid_list *children; 2700 struct sysctl_ctx_list *ctx; 2701 char name[16]; 2702 size_t len; 2703 struct adapter *sc = pi->adapter; 2704 struct netmap_adapter *na = NA(pi->nm_ifp); 2705 2706 MPASS(na != NULL); 2707 2708 len = pi->qsize_rxq * IQ_ESIZE; 2709 rc = alloc_ring(sc, len, &nm_rxq->iq_desc_tag, &nm_rxq->iq_desc_map, 2710 &nm_rxq->iq_ba, (void **)&nm_rxq->iq_desc); 2711 if (rc != 0) 2712 return (rc); 2713 2714 len = na->num_rx_desc * EQ_ESIZE + spg_len; 2715 rc = alloc_ring(sc, len, &nm_rxq->fl_desc_tag, &nm_rxq->fl_desc_map, 2716 &nm_rxq->fl_ba, (void **)&nm_rxq->fl_desc); 2717 if (rc != 0) 2718 return (rc); 2719 2720 nm_rxq->pi = pi; 2721 nm_rxq->nid = idx; 2722 nm_rxq->iq_cidx = 0; 2723 nm_rxq->iq_sidx = pi->qsize_rxq - spg_len / IQ_ESIZE; 2724 nm_rxq->iq_gen = F_RSPD_GEN; 2725 nm_rxq->fl_pidx = nm_rxq->fl_cidx = 0; 2726 nm_rxq->fl_sidx = na->num_rx_desc; 2727 nm_rxq->intr_idx = intr_idx; 2728 2729 ctx = &pi->ctx; 2730 children = SYSCTL_CHILDREN(oid); 2731 2732 snprintf(name, sizeof(name), "%d", idx); 2733 oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name, CTLFLAG_RD, NULL, 2734 "rx queue"); 2735 children = SYSCTL_CHILDREN(oid); 2736 2737 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "abs_id", 2738 CTLTYPE_INT | CTLFLAG_RD, &nm_rxq->iq_abs_id, 0, sysctl_uint16, 2739 "I", "absolute id of the queue"); 2740 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cntxt_id", 2741 CTLTYPE_INT | CTLFLAG_RD, &nm_rxq->iq_cntxt_id, 0, sysctl_uint16, 2742 "I", "SGE context id of the queue"); 2743 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cidx", 2744 CTLTYPE_INT | CTLFLAG_RD, &nm_rxq->iq_cidx, 0, sysctl_uint16, "I", 2745 "consumer index"); 2746 2747 children = SYSCTL_CHILDREN(oid); 2748 oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "fl", CTLFLAG_RD, NULL, 2749 "freelist"); 2750 children = SYSCTL_CHILDREN(oid); 2751 2752 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cntxt_id", 2753 CTLTYPE_INT | CTLFLAG_RD, &nm_rxq->fl_cntxt_id, 0, sysctl_uint16, 2754 "I", "SGE context id of the freelist"); 2755 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "cidx", CTLFLAG_RD, 2756 &nm_rxq->fl_cidx, 0, "consumer index"); 2757 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "pidx", CTLFLAG_RD, 2758 &nm_rxq->fl_pidx, 0, "producer index"); 2759 2760 return (rc); 2761} 2762 2763 2764static int 2765free_nm_rxq(struct port_info *pi, struct sge_nm_rxq *nm_rxq) 2766{ 2767 struct adapter *sc = pi->adapter; 2768 2769 free_ring(sc, nm_rxq->iq_desc_tag, nm_rxq->iq_desc_map, nm_rxq->iq_ba, 2770 nm_rxq->iq_desc); 2771 free_ring(sc, nm_rxq->fl_desc_tag, nm_rxq->fl_desc_map, nm_rxq->fl_ba, 2772 nm_rxq->fl_desc); 2773 2774 return (0); 2775} 2776 2777static int 2778alloc_nm_txq(struct port_info *pi, struct sge_nm_txq *nm_txq, int iqidx, int idx, 2779 struct sysctl_oid *oid) 2780{ 2781 int rc; 2782 size_t len; 2783 struct adapter *sc = pi->adapter; 2784 struct netmap_adapter *na = NA(pi->nm_ifp); 2785 char name[16]; 2786 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid); 2787 2788 len = na->num_tx_desc * EQ_ESIZE + spg_len; 2789 rc = alloc_ring(sc, len, &nm_txq->desc_tag, &nm_txq->desc_map, 2790 &nm_txq->ba, (void **)&nm_txq->desc); 2791 if (rc) 2792 return (rc); 2793 2794 nm_txq->pidx = nm_txq->cidx = 0; 2795 nm_txq->sidx = na->num_tx_desc; 2796 nm_txq->nid = idx; 2797 nm_txq->iqidx = iqidx; 2798 nm_txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) | 2799 V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(sc->pf)); 2800 2801 snprintf(name, sizeof(name), "%d", idx); 2802 oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, name, CTLFLAG_RD, 2803 NULL, "netmap tx queue"); 2804 children = SYSCTL_CHILDREN(oid); 2805 2806 SYSCTL_ADD_UINT(&pi->ctx, children, OID_AUTO, "cntxt_id", CTLFLAG_RD, 2807 &nm_txq->cntxt_id, 0, "SGE context id of the queue"); 2808 SYSCTL_ADD_PROC(&pi->ctx, children, OID_AUTO, "cidx", 2809 CTLTYPE_INT | CTLFLAG_RD, &nm_txq->cidx, 0, sysctl_uint16, "I", 2810 "consumer index"); 2811 SYSCTL_ADD_PROC(&pi->ctx, children, OID_AUTO, "pidx", 2812 CTLTYPE_INT | CTLFLAG_RD, &nm_txq->pidx, 0, sysctl_uint16, "I", 2813 "producer index"); 2814 2815 return (rc); 2816} 2817 2818static int 2819free_nm_txq(struct port_info *pi, struct sge_nm_txq *nm_txq) 2820{ 2821 struct adapter *sc = pi->adapter; 2822 2823 free_ring(sc, nm_txq->desc_tag, nm_txq->desc_map, nm_txq->ba, 2824 nm_txq->desc); 2825 2826 return (0); 2827} 2828#endif 2829 2830static int |
|
2605ctrl_eq_alloc(struct adapter *sc, struct sge_eq *eq) 2606{ 2607 int rc, cntxt_id; 2608 struct fw_eq_ctrl_cmd c; 2609 2610 bzero(&c, sizeof(c)); 2611 2612 c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_EQ_CTRL_CMD) | F_FW_CMD_REQUEST | --- 170 unchanged lines hidden (view full) --- 2783 isset(&eq->doorbells, DOORBELL_WCWR)) { 2784 uint32_t s_qpp = sc->sge.eq_s_qpp; 2785 uint32_t mask = (1 << s_qpp) - 1; 2786 volatile uint8_t *udb; 2787 2788 udb = sc->udbs_base + UDBS_DB_OFFSET; 2789 udb += (eq->cntxt_id >> s_qpp) << PAGE_SHIFT; /* pg offset */ 2790 eq->udb_qid = eq->cntxt_id & mask; /* id in page */ | 2831ctrl_eq_alloc(struct adapter *sc, struct sge_eq *eq) 2832{ 2833 int rc, cntxt_id; 2834 struct fw_eq_ctrl_cmd c; 2835 2836 bzero(&c, sizeof(c)); 2837 2838 c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_EQ_CTRL_CMD) | F_FW_CMD_REQUEST | --- 170 unchanged lines hidden (view full) --- 3009 isset(&eq->doorbells, DOORBELL_WCWR)) { 3010 uint32_t s_qpp = sc->sge.eq_s_qpp; 3011 uint32_t mask = (1 << s_qpp) - 1; 3012 volatile uint8_t *udb; 3013 3014 udb = sc->udbs_base + UDBS_DB_OFFSET; 3015 udb += (eq->cntxt_id >> s_qpp) << PAGE_SHIFT; /* pg offset */ 3016 eq->udb_qid = eq->cntxt_id & mask; /* id in page */ |
2791 if (eq->udb_qid > PAGE_SIZE / UDBS_SEG_SIZE) | 3017 if (eq->udb_qid >= PAGE_SIZE / UDBS_SEG_SIZE) |
2792 clrbit(&eq->doorbells, DOORBELL_WCWR); 2793 else { 2794 udb += eq->udb_qid << UDBS_SEG_SHIFT; /* seg offset */ 2795 eq->udb_qid = 0; 2796 } 2797 eq->udb = (volatile void *)udb; 2798 } 2799 --- 211 unchanged lines hidden (view full) --- 3011 bus_addr_t *ba = arg; 3012 3013 KASSERT(nseg == 1, 3014 ("%s meant for single segment mappings only.", __func__)); 3015 3016 *ba = error ? 0 : segs->ds_addr; 3017} 3018 | 3018 clrbit(&eq->doorbells, DOORBELL_WCWR); 3019 else { 3020 udb += eq->udb_qid << UDBS_SEG_SHIFT; /* seg offset */ 3021 eq->udb_qid = 0; 3022 } 3023 eq->udb = (volatile void *)udb; 3024 } 3025 --- 211 unchanged lines hidden (view full) --- 3237 bus_addr_t *ba = arg; 3238 3239 KASSERT(nseg == 1, 3240 ("%s meant for single segment mappings only.", __func__)); 3241 3242 *ba = error ? 0 : segs->ds_addr; 3243} 3244 |
3019static inline bool 3020is_new_response(const struct sge_iq *iq, struct rsp_ctrl **ctrl) 3021{ 3022 *ctrl = (void *)((uintptr_t)iq->cdesc + 3023 (iq->esize - sizeof(struct rsp_ctrl))); 3024 3025 return (((*ctrl)->u.type_gen >> S_RSPD_GEN) == iq->gen); 3026} 3027 | |
3028static inline void | 3245static inline void |
3029iq_next(struct sge_iq *iq) 3030{ 3031 iq->cdesc = (void *) ((uintptr_t)iq->cdesc + iq->esize); 3032 if (__predict_false(++iq->cidx == iq->qsize - 1)) { 3033 iq->cidx = 0; 3034 iq->gen ^= 1; 3035 iq->cdesc = iq->desc; 3036 } 3037} 3038 3039#define FL_HW_IDX(x) ((x) >> 3) 3040static inline void | |
3041ring_fl_db(struct adapter *sc, struct sge_fl *fl) 3042{ | 3246ring_fl_db(struct adapter *sc, struct sge_fl *fl) 3247{ |
3043 int ndesc = fl->pending / 8; 3044 uint32_t v; | 3248 uint32_t n, v; |
3045 | 3249 |
3046 if (FL_HW_IDX(fl->pidx) == FL_HW_IDX(fl->cidx)) 3047 ndesc--; /* hold back one credit */ | 3250 n = IDXDIFF(fl->pidx / 8, fl->dbidx, fl->sidx); 3251 MPASS(n > 0); |
3048 | 3252 |
3049 if (ndesc <= 0) 3050 return; /* nothing to do */ 3051 3052 v = F_DBPRIO | V_QID(fl->cntxt_id) | V_PIDX(ndesc); 3053 if (is_t5(sc)) 3054 v |= F_DBTYPE; 3055 | |
3056 wmb(); | 3253 wmb(); |
3057 3058 t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL), v); 3059 fl->pending -= ndesc * 8; | 3254 v = fl->dbval | V_PIDX(n); 3255 if (fl->udb) 3256 *fl->udb = htole32(v); 3257 else 3258 t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL), v); 3259 IDXINCR(fl->dbidx, n, fl->sidx); |
3060} 3061 3062/* | 3260} 3261 3262/* |
3063 * Fill up the freelist by upto nbufs and maybe ring its doorbell. | 3263 * Fills up the freelist by allocating upto 'n' buffers. Buffers that are 3264 * recycled do not count towards this allocation budget. |
3064 * | 3265 * |
3065 * Returns non-zero to indicate that it should be added to the list of starving 3066 * freelists. | 3266 * Returns non-zero to indicate that this freelist should be added to the list 3267 * of starving freelists. |
3067 */ 3068static int | 3268 */ 3269static int |
3069refill_fl(struct adapter *sc, struct sge_fl *fl, int nbufs) | 3270refill_fl(struct adapter *sc, struct sge_fl *fl, int n) |
3070{ | 3271{ |
3071 __be64 *d = &fl->desc[fl->pidx]; 3072 struct fl_sdesc *sd = &fl->sdesc[fl->pidx]; | 3272 __be64 *d; 3273 struct fl_sdesc *sd; |
3073 uintptr_t pa; 3074 caddr_t cl; | 3274 uintptr_t pa; 3275 caddr_t cl; |
3075 struct cluster_layout *cll = &fl->cll_def; /* default layout */ 3076 struct sw_zone_info *swz = &sc->sge.sw_zone_info[cll->zidx]; | 3276 struct cluster_layout *cll; 3277 struct sw_zone_info *swz; |
3077 struct cluster_metadata *clm; | 3278 struct cluster_metadata *clm; |
3279 uint16_t max_pidx; 3280 uint16_t hw_cidx = fl->hw_cidx; /* stable snapshot */ |
|
3078 3079 FL_LOCK_ASSERT_OWNED(fl); 3080 | 3281 3282 FL_LOCK_ASSERT_OWNED(fl); 3283 |
3081 if (nbufs > fl->needed) 3082 nbufs = fl->needed; 3083 nbufs -= (fl->pidx + nbufs) % 8; | 3284 /* 3285 * We always stop at the begining of the hardware descriptor that's just 3286 * before the one with the hw cidx. This is to avoid hw pidx = hw cidx, 3287 * which would mean an empty freelist to the chip. 3288 */ 3289 max_pidx = __predict_false(hw_cidx == 0) ? fl->sidx - 1 : hw_cidx - 1; 3290 if (fl->pidx == max_pidx * 8) 3291 return (0); |
3084 | 3292 |
3085 while (nbufs--) { | 3293 d = &fl->desc[fl->pidx]; 3294 sd = &fl->sdesc[fl->pidx]; 3295 cll = &fl->cll_def; /* default layout */ 3296 swz = &sc->sge.sw_zone_info[cll->zidx]; |
3086 | 3297 |
3298 while (n > 0) { 3299 |
|
3087 if (sd->cl != NULL) { 3088 3089 if (sd->nmbuf == 0) { 3090 /* 3091 * Fast recycle without involving any atomics on 3092 * the cluster's metadata (if the cluster has 3093 * metadata). This happens when all frames 3094 * received in the cluster were small enough to --- 32 unchanged lines hidden (view full) --- 3127 break; 3128 3129 /* fall back to the safe zone */ 3130 cll = &fl->cll_alt; 3131 swz = &sc->sge.sw_zone_info[cll->zidx]; 3132 goto alloc; 3133 } 3134 fl->cl_allocated++; | 3300 if (sd->cl != NULL) { 3301 3302 if (sd->nmbuf == 0) { 3303 /* 3304 * Fast recycle without involving any atomics on 3305 * the cluster's metadata (if the cluster has 3306 * metadata). This happens when all frames 3307 * received in the cluster were small enough to --- 32 unchanged lines hidden (view full) --- 3340 break; 3341 3342 /* fall back to the safe zone */ 3343 cll = &fl->cll_alt; 3344 swz = &sc->sge.sw_zone_info[cll->zidx]; 3345 goto alloc; 3346 } 3347 fl->cl_allocated++; |
3348 n--; |
|
3135 3136 pa = pmap_kextract((vm_offset_t)cl); 3137 pa += cll->region1; 3138 sd->cl = cl; 3139 sd->cll = *cll; 3140 *d = htobe64(pa | cll->hwidx); 3141 clm = cl_metadata(sc, fl, cll, cl); 3142 if (clm != NULL) { 3143recycled: 3144#ifdef INVARIANTS 3145 clm->sd = sd; 3146#endif 3147 clm->refcount = 1; 3148 } 3149 sd->nmbuf = 0; 3150recycled_fast: | 3349 3350 pa = pmap_kextract((vm_offset_t)cl); 3351 pa += cll->region1; 3352 sd->cl = cl; 3353 sd->cll = *cll; 3354 *d = htobe64(pa | cll->hwidx); 3355 clm = cl_metadata(sc, fl, cll, cl); 3356 if (clm != NULL) { 3357recycled: 3358#ifdef INVARIANTS 3359 clm->sd = sd; 3360#endif 3361 clm->refcount = 1; 3362 } 3363 sd->nmbuf = 0; 3364recycled_fast: |
3151 fl->pending++; 3152 fl->needed--; | |
3153 d++; 3154 sd++; | 3365 d++; 3366 sd++; |
3155 if (__predict_false(++fl->pidx == fl->cap)) { 3156 fl->pidx = 0; 3157 sd = fl->sdesc; 3158 d = fl->desc; | 3367 if (__predict_false(++fl->pidx % 8 == 0)) { 3368 uint16_t pidx = fl->pidx / 8; 3369 3370 if (__predict_false(pidx == fl->sidx)) { 3371 fl->pidx = 0; 3372 pidx = 0; 3373 sd = fl->sdesc; 3374 d = fl->desc; 3375 } 3376 if (pidx == max_pidx) 3377 break; 3378 3379 if (IDXDIFF(pidx, fl->dbidx, fl->sidx) >= 4) 3380 ring_fl_db(sc, fl); |
3159 } 3160 } 3161 | 3381 } 3382 } 3383 |
3162 if (fl->pending >= 8) | 3384 if (fl->pidx / 8 != fl->dbidx) |
3163 ring_fl_db(sc, fl); 3164 3165 return (FL_RUNNING_LOW(fl) && !(fl->flags & FL_STARVING)); 3166} 3167 3168/* 3169 * Attempt to refill all starving freelists. 3170 */ --- 18 unchanged lines hidden (view full) --- 3189 callout_schedule(&sc->sfl_callout, hz / 5); 3190 mtx_unlock(&sc->sfl_lock); 3191} 3192 3193static int 3194alloc_fl_sdesc(struct sge_fl *fl) 3195{ 3196 | 3385 ring_fl_db(sc, fl); 3386 3387 return (FL_RUNNING_LOW(fl) && !(fl->flags & FL_STARVING)); 3388} 3389 3390/* 3391 * Attempt to refill all starving freelists. 3392 */ --- 18 unchanged lines hidden (view full) --- 3411 callout_schedule(&sc->sfl_callout, hz / 5); 3412 mtx_unlock(&sc->sfl_lock); 3413} 3414 3415static int 3416alloc_fl_sdesc(struct sge_fl *fl) 3417{ 3418 |
3197 fl->sdesc = malloc(fl->cap * sizeof(struct fl_sdesc), M_CXGBE, | 3419 fl->sdesc = malloc(fl->sidx * 8 * sizeof(struct fl_sdesc), M_CXGBE, |
3198 M_ZERO | M_WAITOK); 3199 3200 return (0); 3201} 3202 3203static void 3204free_fl_sdesc(struct adapter *sc, struct sge_fl *fl) 3205{ 3206 struct fl_sdesc *sd; 3207 struct cluster_metadata *clm; 3208 struct cluster_layout *cll; 3209 int i; 3210 3211 sd = fl->sdesc; | 3420 M_ZERO | M_WAITOK); 3421 3422 return (0); 3423} 3424 3425static void 3426free_fl_sdesc(struct adapter *sc, struct sge_fl *fl) 3427{ 3428 struct fl_sdesc *sd; 3429 struct cluster_metadata *clm; 3430 struct cluster_layout *cll; 3431 int i; 3432 3433 sd = fl->sdesc; |
3212 for (i = 0; i < fl->cap; i++, sd++) { | 3434 for (i = 0; i < fl->sidx * 8; i++, sd++) { |
3213 if (sd->cl == NULL) 3214 continue; 3215 3216 cll = &sd->cll; 3217 clm = cl_metadata(sc, fl, cll, sd->cl); 3218 if (sd->nmbuf == 0) 3219 uma_zfree(sc->sge.sw_zone_info[cll->zidx].zone, sd->cl); 3220 else if (clm && atomic_fetchadd_int(&clm->refcount, -1) == 1) { --- 1117 unchanged lines hidden --- | 3435 if (sd->cl == NULL) 3436 continue; 3437 3438 cll = &sd->cll; 3439 clm = cl_metadata(sc, fl, cll, sd->cl); 3440 if (sd->nmbuf == 0) 3441 uma_zfree(sc->sge.sw_zone_info[cll->zidx].zone, sd->cl); 3442 else if (clm && atomic_fetchadd_int(&clm->refcount, -1) == 1) { --- 1117 unchanged lines hidden --- |