if_mcx.c revision 1.22 1 1.22 jmcneill /* $NetBSD: if_mcx.c,v 1.22 2021/09/26 20:14:07 jmcneill Exp $ */
2 1.20 jmcneill /* $OpenBSD: if_mcx.c,v 1.101 2021/06/02 19:16:11 patrick Exp $ */
3 1.1 jmcneill
4 1.1 jmcneill /*
5 1.1 jmcneill * Copyright (c) 2017 David Gwynne <dlg (at) openbsd.org>
6 1.1 jmcneill * Copyright (c) 2019 Jonathan Matthew <jmatthew (at) openbsd.org>
7 1.1 jmcneill *
8 1.1 jmcneill * Permission to use, copy, modify, and distribute this software for any
9 1.1 jmcneill * purpose with or without fee is hereby granted, provided that the above
10 1.1 jmcneill * copyright notice and this permission notice appear in all copies.
11 1.1 jmcneill *
12 1.1 jmcneill * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 1.1 jmcneill * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 1.1 jmcneill * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 1.1 jmcneill * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 1.1 jmcneill * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 1.1 jmcneill * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 1.1 jmcneill * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 1.1 jmcneill */
20 1.1 jmcneill
21 1.1 jmcneill #ifdef _KERNEL_OPT
22 1.1 jmcneill #include "opt_net_mpsafe.h"
23 1.1 jmcneill #endif
24 1.1 jmcneill
25 1.14 jmcneill #include <sys/cdefs.h>
26 1.22 jmcneill __KERNEL_RCSID(0, "$NetBSD: if_mcx.c,v 1.22 2021/09/26 20:14:07 jmcneill Exp $");
27 1.14 jmcneill
28 1.1 jmcneill #include <sys/param.h>
29 1.1 jmcneill #include <sys/systm.h>
30 1.1 jmcneill #include <sys/sockio.h>
31 1.1 jmcneill #include <sys/mbuf.h>
32 1.1 jmcneill #include <sys/kernel.h>
33 1.1 jmcneill #include <sys/socket.h>
34 1.1 jmcneill #include <sys/device.h>
35 1.1 jmcneill #include <sys/pool.h>
36 1.1 jmcneill #include <sys/queue.h>
37 1.1 jmcneill #include <sys/callout.h>
38 1.1 jmcneill #include <sys/workqueue.h>
39 1.1 jmcneill #include <sys/atomic.h>
40 1.15 jmcneill #include <sys/timetc.h>
41 1.1 jmcneill #include <sys/kmem.h>
42 1.1 jmcneill #include <sys/bus.h>
43 1.15 jmcneill #include <sys/interrupt.h>
44 1.16 jmcneill #include <sys/pcq.h>
45 1.16 jmcneill #include <sys/cpu.h>
46 1.1 jmcneill
47 1.1 jmcneill #include <machine/intr.h>
48 1.1 jmcneill
49 1.1 jmcneill #include <net/if.h>
50 1.1 jmcneill #include <net/if_dl.h>
51 1.1 jmcneill #include <net/if_ether.h>
52 1.1 jmcneill #include <net/if_media.h>
53 1.15 jmcneill #include <net/if_vlanvar.h>
54 1.15 jmcneill #include <net/toeplitz.h>
55 1.1 jmcneill
56 1.1 jmcneill #include <net/bpf.h>
57 1.1 jmcneill
58 1.1 jmcneill #include <netinet/in.h>
59 1.1 jmcneill
60 1.1 jmcneill #include <dev/pci/pcireg.h>
61 1.1 jmcneill #include <dev/pci/pcivar.h>
62 1.1 jmcneill #include <dev/pci/pcidevs.h>
63 1.1 jmcneill
64 1.15 jmcneill /* TODO: Port kstat key/value stuff to evcnt/sysmon */
65 1.15 jmcneill #define NKSTAT 0
66 1.15 jmcneill
67 1.12 thorpej /* XXX This driver is not yet MP-safe; don't claim to be! */
68 1.12 thorpej /* #ifdef NET_MPSAFE */
69 1.12 thorpej /* #define MCX_MPSAFE 1 */
70 1.12 thorpej /* #define CALLOUT_FLAGS CALLOUT_MPSAFE */
71 1.12 thorpej /* #else */
72 1.1 jmcneill #define CALLOUT_FLAGS 0
73 1.12 thorpej /* #endif */
74 1.1 jmcneill
75 1.16 jmcneill #define MCX_TXQ_NUM 2048
76 1.16 jmcneill
77 1.1 jmcneill #define BUS_DMASYNC_PRERW (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
78 1.1 jmcneill #define BUS_DMASYNC_POSTRW (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
79 1.1 jmcneill
80 1.1 jmcneill #define MCX_HCA_BAR PCI_MAPREG_START /* BAR 0 */
81 1.1 jmcneill
82 1.15 jmcneill #define MCX_FW_VER 0x0000
83 1.15 jmcneill #define MCX_FW_VER_MAJOR(_v) ((_v) & 0xffff)
84 1.15 jmcneill #define MCX_FW_VER_MINOR(_v) ((_v) >> 16)
85 1.15 jmcneill #define MCX_CMDIF_FW_SUBVER 0x0004
86 1.15 jmcneill #define MCX_FW_VER_SUBMINOR(_v) ((_v) & 0xffff)
87 1.15 jmcneill #define MCX_CMDIF(_v) ((_v) >> 16)
88 1.1 jmcneill
89 1.15 jmcneill #define MCX_ISSI 1 /* as per the PRM */
90 1.15 jmcneill #define MCX_CMD_IF_SUPPORTED 5
91 1.1 jmcneill
92 1.15 jmcneill #define MCX_HARDMTU 9500
93 1.1 jmcneill
94 1.15 jmcneill #define MCX_PAGE_SHIFT 12
95 1.15 jmcneill #define MCX_PAGE_SIZE (1 << MCX_PAGE_SHIFT)
96 1.1 jmcneill
97 1.1 jmcneill /* queue sizes */
98 1.15 jmcneill #define MCX_LOG_EQ_SIZE 7
99 1.15 jmcneill #define MCX_LOG_CQ_SIZE 12
100 1.15 jmcneill #define MCX_LOG_RQ_SIZE 10
101 1.15 jmcneill #define MCX_LOG_SQ_SIZE 11
102 1.15 jmcneill
103 1.15 jmcneill #define MCX_MAX_QUEUES 16
104 1.1 jmcneill
105 1.1 jmcneill /* completion event moderation - about 10khz, or 90% of the cq */
106 1.15 jmcneill #define MCX_CQ_MOD_PERIOD 50
107 1.15 jmcneill #define MCX_CQ_MOD_COUNTER \
108 1.15 jmcneill (((1 << (MCX_LOG_CQ_SIZE - 1)) * 9) / 10)
109 1.15 jmcneill
110 1.15 jmcneill #define MCX_LOG_SQ_ENTRY_SIZE 6
111 1.15 jmcneill #define MCX_SQ_ENTRY_MAX_SLOTS 4
112 1.15 jmcneill #define MCX_SQ_SEGS_PER_SLOT \
113 1.1 jmcneill (sizeof(struct mcx_sq_entry) / sizeof(struct mcx_sq_entry_seg))
114 1.15 jmcneill #define MCX_SQ_MAX_SEGMENTS \
115 1.1 jmcneill 1 + ((MCX_SQ_ENTRY_MAX_SLOTS-1) * MCX_SQ_SEGS_PER_SLOT)
116 1.1 jmcneill
117 1.15 jmcneill #define MCX_LOG_FLOW_TABLE_SIZE 5
118 1.15 jmcneill #define MCX_NUM_STATIC_FLOWS 4 /* promisc, allmulti, ucast, bcast */
119 1.15 jmcneill #define MCX_NUM_MCAST_FLOWS \
120 1.1 jmcneill ((1 << MCX_LOG_FLOW_TABLE_SIZE) - MCX_NUM_STATIC_FLOWS)
121 1.1 jmcneill
122 1.15 jmcneill #define MCX_SQ_INLINE_SIZE 18
123 1.15 jmcneill CTASSERT(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN == MCX_SQ_INLINE_SIZE);
124 1.1 jmcneill
125 1.1 jmcneill /* doorbell offsets */
126 1.15 jmcneill #define MCX_DOORBELL_AREA_SIZE MCX_PAGE_SIZE
127 1.1 jmcneill
128 1.15 jmcneill #define MCX_CQ_DOORBELL_BASE 0
129 1.15 jmcneill #define MCX_CQ_DOORBELL_STRIDE 64
130 1.15 jmcneill
131 1.15 jmcneill #define MCX_WQ_DOORBELL_BASE MCX_PAGE_SIZE/2
132 1.15 jmcneill #define MCX_WQ_DOORBELL_STRIDE 64
133 1.15 jmcneill /* make sure the doorbells fit */
134 1.15 jmcneill CTASSERT(MCX_MAX_QUEUES * MCX_CQ_DOORBELL_STRIDE < MCX_WQ_DOORBELL_BASE);
135 1.15 jmcneill CTASSERT(MCX_MAX_QUEUES * MCX_WQ_DOORBELL_STRIDE <
136 1.15 jmcneill MCX_DOORBELL_AREA_SIZE - MCX_WQ_DOORBELL_BASE);
137 1.15 jmcneill
138 1.15 jmcneill #define MCX_WQ_DOORBELL_MASK 0xffff
139 1.1 jmcneill
140 1.1 jmcneill /* uar registers */
141 1.15 jmcneill #define MCX_UAR_CQ_DOORBELL 0x20
142 1.15 jmcneill #define MCX_UAR_EQ_DOORBELL_ARM 0x40
143 1.15 jmcneill #define MCX_UAR_EQ_DOORBELL 0x48
144 1.15 jmcneill #define MCX_UAR_BF 0x800
145 1.1 jmcneill
146 1.15 jmcneill #define MCX_CMDQ_ADDR_HI 0x0010
147 1.15 jmcneill #define MCX_CMDQ_ADDR_LO 0x0014
148 1.1 jmcneill #define MCX_CMDQ_ADDR_NMASK 0xfff
149 1.1 jmcneill #define MCX_CMDQ_LOG_SIZE(_v) ((_v) >> 4 & 0xf)
150 1.1 jmcneill #define MCX_CMDQ_LOG_STRIDE(_v) ((_v) >> 0 & 0xf)
151 1.1 jmcneill #define MCX_CMDQ_INTERFACE_MASK (0x3 << 8)
152 1.1 jmcneill #define MCX_CMDQ_INTERFACE_FULL_DRIVER (0x0 << 8)
153 1.1 jmcneill #define MCX_CMDQ_INTERFACE_DISABLED (0x1 << 8)
154 1.1 jmcneill
155 1.1 jmcneill #define MCX_CMDQ_DOORBELL 0x0018
156 1.1 jmcneill
157 1.15 jmcneill #define MCX_STATE 0x01fc
158 1.15 jmcneill #define MCX_STATE_MASK (1U << 31)
159 1.15 jmcneill #define MCX_STATE_INITIALIZING (1 << 31)
160 1.15 jmcneill #define MCX_STATE_READY (0 << 31)
161 1.15 jmcneill #define MCX_STATE_INTERFACE_MASK (0x3 << 24)
162 1.15 jmcneill #define MCX_STATE_INTERFACE_FULL_DRIVER (0x0 << 24)
163 1.15 jmcneill #define MCX_STATE_INTERFACE_DISABLED (0x1 << 24)
164 1.15 jmcneill
165 1.15 jmcneill #define MCX_INTERNAL_TIMER 0x1000
166 1.15 jmcneill #define MCX_INTERNAL_TIMER_H 0x1000
167 1.15 jmcneill #define MCX_INTERNAL_TIMER_L 0x1004
168 1.15 jmcneill
169 1.15 jmcneill #define MCX_CLEAR_INT 0x100c
170 1.15 jmcneill
171 1.15 jmcneill #define MCX_REG_OP_WRITE 0
172 1.15 jmcneill #define MCX_REG_OP_READ 1
173 1.15 jmcneill
174 1.15 jmcneill #define MCX_REG_PMLP 0x5002
175 1.15 jmcneill #define MCX_REG_PMTU 0x5003
176 1.15 jmcneill #define MCX_REG_PTYS 0x5004
177 1.15 jmcneill #define MCX_REG_PAOS 0x5006
178 1.15 jmcneill #define MCX_REG_PFCC 0x5007
179 1.15 jmcneill #define MCX_REG_PPCNT 0x5008
180 1.15 jmcneill #define MCX_REG_MTCAP 0x9009 /* mgmt temp capabilities */
181 1.15 jmcneill #define MCX_REG_MTMP 0x900a /* mgmt temp */
182 1.15 jmcneill #define MCX_REG_MCIA 0x9014
183 1.15 jmcneill #define MCX_REG_MCAM 0x907f
184 1.15 jmcneill
185 1.15 jmcneill #define MCX_ETHER_CAP_SGMII 0
186 1.15 jmcneill #define MCX_ETHER_CAP_1000_KX 1
187 1.15 jmcneill #define MCX_ETHER_CAP_10G_CX4 2
188 1.15 jmcneill #define MCX_ETHER_CAP_10G_KX4 3
189 1.15 jmcneill #define MCX_ETHER_CAP_10G_KR 4
190 1.15 jmcneill #define MCX_ETHER_CAP_20G_KR2 5
191 1.15 jmcneill #define MCX_ETHER_CAP_40G_CR4 6
192 1.15 jmcneill #define MCX_ETHER_CAP_40G_KR4 7
193 1.15 jmcneill #define MCX_ETHER_CAP_56G_R4 8
194 1.15 jmcneill #define MCX_ETHER_CAP_10G_CR 12
195 1.15 jmcneill #define MCX_ETHER_CAP_10G_SR 13
196 1.15 jmcneill #define MCX_ETHER_CAP_10G_LR 14
197 1.15 jmcneill #define MCX_ETHER_CAP_40G_SR4 15
198 1.15 jmcneill #define MCX_ETHER_CAP_40G_LR4 16
199 1.15 jmcneill #define MCX_ETHER_CAP_50G_SR2 18
200 1.15 jmcneill #define MCX_ETHER_CAP_100G_CR4 20
201 1.15 jmcneill #define MCX_ETHER_CAP_100G_SR4 21
202 1.15 jmcneill #define MCX_ETHER_CAP_100G_KR4 22
203 1.15 jmcneill #define MCX_ETHER_CAP_100G_LR4 23
204 1.15 jmcneill #define MCX_ETHER_CAP_100_TX 24
205 1.15 jmcneill #define MCX_ETHER_CAP_1000_T 25
206 1.15 jmcneill #define MCX_ETHER_CAP_10G_T 26
207 1.15 jmcneill #define MCX_ETHER_CAP_25G_CR 27
208 1.15 jmcneill #define MCX_ETHER_CAP_25G_KR 28
209 1.15 jmcneill #define MCX_ETHER_CAP_25G_SR 29
210 1.15 jmcneill #define MCX_ETHER_CAP_50G_CR2 30
211 1.15 jmcneill #define MCX_ETHER_CAP_50G_KR2 31
212 1.15 jmcneill
213 1.15 jmcneill #define MCX_MAX_CQE 32
214 1.15 jmcneill
215 1.15 jmcneill #define MCX_CMD_QUERY_HCA_CAP 0x100
216 1.15 jmcneill #define MCX_CMD_QUERY_ADAPTER 0x101
217 1.15 jmcneill #define MCX_CMD_INIT_HCA 0x102
218 1.15 jmcneill #define MCX_CMD_TEARDOWN_HCA 0x103
219 1.15 jmcneill #define MCX_CMD_ENABLE_HCA 0x104
220 1.15 jmcneill #define MCX_CMD_DISABLE_HCA 0x105
221 1.15 jmcneill #define MCX_CMD_QUERY_PAGES 0x107
222 1.15 jmcneill #define MCX_CMD_MANAGE_PAGES 0x108
223 1.15 jmcneill #define MCX_CMD_SET_HCA_CAP 0x109
224 1.15 jmcneill #define MCX_CMD_QUERY_ISSI 0x10a
225 1.15 jmcneill #define MCX_CMD_SET_ISSI 0x10b
226 1.15 jmcneill #define MCX_CMD_SET_DRIVER_VERSION 0x10d
227 1.15 jmcneill #define MCX_CMD_QUERY_SPECIAL_CONTEXTS 0x203
228 1.15 jmcneill #define MCX_CMD_CREATE_EQ 0x301
229 1.15 jmcneill #define MCX_CMD_DESTROY_EQ 0x302
230 1.15 jmcneill #define MCX_CMD_QUERY_EQ 0x303
231 1.15 jmcneill #define MCX_CMD_CREATE_CQ 0x400
232 1.15 jmcneill #define MCX_CMD_DESTROY_CQ 0x401
233 1.15 jmcneill #define MCX_CMD_QUERY_CQ 0x402
234 1.15 jmcneill #define MCX_CMD_QUERY_NIC_VPORT_CONTEXT 0x754
235 1.1 jmcneill #define MCX_CMD_MODIFY_NIC_VPORT_CONTEXT \
236 1.15 jmcneill 0x755
237 1.15 jmcneill #define MCX_CMD_QUERY_VPORT_COUNTERS 0x770
238 1.15 jmcneill #define MCX_CMD_ALLOC_PD 0x800
239 1.15 jmcneill #define MCX_CMD_ALLOC_UAR 0x802
240 1.15 jmcneill #define MCX_CMD_ACCESS_REG 0x805
241 1.15 jmcneill #define MCX_CMD_ALLOC_TRANSPORT_DOMAIN 0x816
242 1.15 jmcneill #define MCX_CMD_CREATE_TIR 0x900
243 1.15 jmcneill #define MCX_CMD_DESTROY_TIR 0x902
244 1.15 jmcneill #define MCX_CMD_CREATE_SQ 0x904
245 1.15 jmcneill #define MCX_CMD_MODIFY_SQ 0x905
246 1.15 jmcneill #define MCX_CMD_DESTROY_SQ 0x906
247 1.15 jmcneill #define MCX_CMD_QUERY_SQ 0x907
248 1.15 jmcneill #define MCX_CMD_CREATE_RQ 0x908
249 1.15 jmcneill #define MCX_CMD_MODIFY_RQ 0x909
250 1.15 jmcneill #define MCX_CMD_DESTROY_RQ 0x90a
251 1.15 jmcneill #define MCX_CMD_QUERY_RQ 0x90b
252 1.15 jmcneill #define MCX_CMD_CREATE_TIS 0x912
253 1.15 jmcneill #define MCX_CMD_DESTROY_TIS 0x914
254 1.15 jmcneill #define MCX_CMD_CREATE_RQT 0x916
255 1.15 jmcneill #define MCX_CMD_DESTROY_RQT 0x918
256 1.15 jmcneill #define MCX_CMD_SET_FLOW_TABLE_ROOT 0x92f
257 1.15 jmcneill #define MCX_CMD_CREATE_FLOW_TABLE 0x930
258 1.15 jmcneill #define MCX_CMD_DESTROY_FLOW_TABLE 0x931
259 1.15 jmcneill #define MCX_CMD_QUERY_FLOW_TABLE 0x932
260 1.15 jmcneill #define MCX_CMD_CREATE_FLOW_GROUP 0x933
261 1.15 jmcneill #define MCX_CMD_DESTROY_FLOW_GROUP 0x934
262 1.15 jmcneill #define MCX_CMD_QUERY_FLOW_GROUP 0x935
263 1.15 jmcneill #define MCX_CMD_SET_FLOW_TABLE_ENTRY 0x936
264 1.15 jmcneill #define MCX_CMD_QUERY_FLOW_TABLE_ENTRY 0x937
265 1.15 jmcneill #define MCX_CMD_DELETE_FLOW_TABLE_ENTRY 0x938
266 1.15 jmcneill #define MCX_CMD_ALLOC_FLOW_COUNTER 0x939
267 1.15 jmcneill #define MCX_CMD_QUERY_FLOW_COUNTER 0x93b
268 1.15 jmcneill
269 1.15 jmcneill #define MCX_QUEUE_STATE_RST 0
270 1.15 jmcneill #define MCX_QUEUE_STATE_RDY 1
271 1.15 jmcneill #define MCX_QUEUE_STATE_ERR 3
272 1.1 jmcneill
273 1.15 jmcneill #define MCX_FLOW_TABLE_TYPE_RX 0
274 1.15 jmcneill #define MCX_FLOW_TABLE_TYPE_TX 1
275 1.1 jmcneill
276 1.15 jmcneill #define MCX_CMDQ_INLINE_DATASIZE 16
277 1.1 jmcneill
278 1.1 jmcneill struct mcx_cmdq_entry {
279 1.1 jmcneill uint8_t cq_type;
280 1.1 jmcneill #define MCX_CMDQ_TYPE_PCIE 0x7
281 1.1 jmcneill uint8_t cq_reserved0[3];
282 1.1 jmcneill
283 1.1 jmcneill uint32_t cq_input_length;
284 1.1 jmcneill uint64_t cq_input_ptr;
285 1.1 jmcneill uint8_t cq_input_data[MCX_CMDQ_INLINE_DATASIZE];
286 1.1 jmcneill
287 1.1 jmcneill uint8_t cq_output_data[MCX_CMDQ_INLINE_DATASIZE];
288 1.1 jmcneill uint64_t cq_output_ptr;
289 1.1 jmcneill uint32_t cq_output_length;
290 1.1 jmcneill
291 1.1 jmcneill uint8_t cq_token;
292 1.1 jmcneill uint8_t cq_signature;
293 1.1 jmcneill uint8_t cq_reserved1[1];
294 1.1 jmcneill uint8_t cq_status;
295 1.1 jmcneill #define MCX_CQ_STATUS_SHIFT 1
296 1.1 jmcneill #define MCX_CQ_STATUS_MASK (0x7f << MCX_CQ_STATUS_SHIFT)
297 1.1 jmcneill #define MCX_CQ_STATUS_OK (0x00 << MCX_CQ_STATUS_SHIFT)
298 1.1 jmcneill #define MCX_CQ_STATUS_INT_ERR (0x01 << MCX_CQ_STATUS_SHIFT)
299 1.1 jmcneill #define MCX_CQ_STATUS_BAD_OPCODE (0x02 << MCX_CQ_STATUS_SHIFT)
300 1.1 jmcneill #define MCX_CQ_STATUS_BAD_PARAM (0x03 << MCX_CQ_STATUS_SHIFT)
301 1.1 jmcneill #define MCX_CQ_STATUS_BAD_SYS_STATE (0x04 << MCX_CQ_STATUS_SHIFT)
302 1.1 jmcneill #define MCX_CQ_STATUS_BAD_RESOURCE (0x05 << MCX_CQ_STATUS_SHIFT)
303 1.1 jmcneill #define MCX_CQ_STATUS_RESOURCE_BUSY (0x06 << MCX_CQ_STATUS_SHIFT)
304 1.1 jmcneill #define MCX_CQ_STATUS_EXCEED_LIM (0x08 << MCX_CQ_STATUS_SHIFT)
305 1.1 jmcneill #define MCX_CQ_STATUS_BAD_RES_STATE (0x09 << MCX_CQ_STATUS_SHIFT)
306 1.1 jmcneill #define MCX_CQ_STATUS_BAD_INDEX (0x0a << MCX_CQ_STATUS_SHIFT)
307 1.1 jmcneill #define MCX_CQ_STATUS_NO_RESOURCES (0x0f << MCX_CQ_STATUS_SHIFT)
308 1.1 jmcneill #define MCX_CQ_STATUS_BAD_INPUT_LEN (0x50 << MCX_CQ_STATUS_SHIFT)
309 1.1 jmcneill #define MCX_CQ_STATUS_BAD_OUTPUT_LEN (0x51 << MCX_CQ_STATUS_SHIFT)
310 1.1 jmcneill #define MCX_CQ_STATUS_BAD_RESOURCE_STATE \
311 1.1 jmcneill (0x10 << MCX_CQ_STATUS_SHIFT)
312 1.1 jmcneill #define MCX_CQ_STATUS_BAD_SIZE (0x40 << MCX_CQ_STATUS_SHIFT)
313 1.1 jmcneill #define MCX_CQ_STATUS_OWN_MASK 0x1
314 1.1 jmcneill #define MCX_CQ_STATUS_OWN_SW 0x0
315 1.1 jmcneill #define MCX_CQ_STATUS_OWN_HW 0x1
316 1.1 jmcneill } __packed __aligned(8);
317 1.1 jmcneill
318 1.1 jmcneill #define MCX_CMDQ_MAILBOX_DATASIZE 512
319 1.1 jmcneill
320 1.1 jmcneill struct mcx_cmdq_mailbox {
321 1.1 jmcneill uint8_t mb_data[MCX_CMDQ_MAILBOX_DATASIZE];
322 1.1 jmcneill uint8_t mb_reserved0[48];
323 1.1 jmcneill uint64_t mb_next_ptr;
324 1.1 jmcneill uint32_t mb_block_number;
325 1.1 jmcneill uint8_t mb_reserved1[1];
326 1.1 jmcneill uint8_t mb_token;
327 1.1 jmcneill uint8_t mb_ctrl_signature;
328 1.1 jmcneill uint8_t mb_signature;
329 1.1 jmcneill } __packed __aligned(8);
330 1.1 jmcneill
331 1.1 jmcneill #define MCX_CMDQ_MAILBOX_ALIGN (1 << 10)
332 1.1 jmcneill #define MCX_CMDQ_MAILBOX_SIZE roundup(sizeof(struct mcx_cmdq_mailbox), \
333 1.1 jmcneill MCX_CMDQ_MAILBOX_ALIGN)
334 1.1 jmcneill /*
335 1.18 andvar * command mailbox structures
336 1.1 jmcneill */
337 1.1 jmcneill
338 1.1 jmcneill struct mcx_cmd_enable_hca_in {
339 1.1 jmcneill uint16_t cmd_opcode;
340 1.1 jmcneill uint8_t cmd_reserved0[4];
341 1.1 jmcneill uint16_t cmd_op_mod;
342 1.1 jmcneill uint8_t cmd_reserved1[2];
343 1.1 jmcneill uint16_t cmd_function_id;
344 1.1 jmcneill uint8_t cmd_reserved2[4];
345 1.1 jmcneill } __packed __aligned(4);
346 1.1 jmcneill
347 1.1 jmcneill struct mcx_cmd_enable_hca_out {
348 1.1 jmcneill uint8_t cmd_status;
349 1.1 jmcneill uint8_t cmd_reserved0[3];
350 1.1 jmcneill uint32_t cmd_syndrome;
351 1.1 jmcneill uint8_t cmd_reserved1[4];
352 1.1 jmcneill } __packed __aligned(4);
353 1.1 jmcneill
354 1.1 jmcneill struct mcx_cmd_init_hca_in {
355 1.1 jmcneill uint16_t cmd_opcode;
356 1.1 jmcneill uint8_t cmd_reserved0[4];
357 1.1 jmcneill uint16_t cmd_op_mod;
358 1.1 jmcneill uint8_t cmd_reserved1[8];
359 1.1 jmcneill } __packed __aligned(4);
360 1.1 jmcneill
361 1.1 jmcneill struct mcx_cmd_init_hca_out {
362 1.1 jmcneill uint8_t cmd_status;
363 1.1 jmcneill uint8_t cmd_reserved0[3];
364 1.1 jmcneill uint32_t cmd_syndrome;
365 1.1 jmcneill uint8_t cmd_reserved1[8];
366 1.1 jmcneill } __packed __aligned(4);
367 1.1 jmcneill
368 1.1 jmcneill struct mcx_cmd_teardown_hca_in {
369 1.1 jmcneill uint16_t cmd_opcode;
370 1.1 jmcneill uint8_t cmd_reserved0[4];
371 1.1 jmcneill uint16_t cmd_op_mod;
372 1.1 jmcneill uint8_t cmd_reserved1[2];
373 1.1 jmcneill #define MCX_CMD_TEARDOWN_HCA_GRACEFUL 0x0
374 1.1 jmcneill #define MCX_CMD_TEARDOWN_HCA_PANIC 0x1
375 1.1 jmcneill uint16_t cmd_profile;
376 1.1 jmcneill uint8_t cmd_reserved2[4];
377 1.1 jmcneill } __packed __aligned(4);
378 1.1 jmcneill
379 1.1 jmcneill struct mcx_cmd_teardown_hca_out {
380 1.1 jmcneill uint8_t cmd_status;
381 1.1 jmcneill uint8_t cmd_reserved0[3];
382 1.1 jmcneill uint32_t cmd_syndrome;
383 1.1 jmcneill uint8_t cmd_reserved1[8];
384 1.1 jmcneill } __packed __aligned(4);
385 1.1 jmcneill
386 1.1 jmcneill struct mcx_cmd_access_reg_in {
387 1.1 jmcneill uint16_t cmd_opcode;
388 1.1 jmcneill uint8_t cmd_reserved0[4];
389 1.1 jmcneill uint16_t cmd_op_mod;
390 1.1 jmcneill uint8_t cmd_reserved1[2];
391 1.1 jmcneill uint16_t cmd_register_id;
392 1.1 jmcneill uint32_t cmd_argument;
393 1.1 jmcneill } __packed __aligned(4);
394 1.1 jmcneill
395 1.1 jmcneill struct mcx_cmd_access_reg_out {
396 1.1 jmcneill uint8_t cmd_status;
397 1.1 jmcneill uint8_t cmd_reserved0[3];
398 1.1 jmcneill uint32_t cmd_syndrome;
399 1.1 jmcneill uint8_t cmd_reserved1[8];
400 1.1 jmcneill } __packed __aligned(4);
401 1.1 jmcneill
402 1.1 jmcneill struct mcx_reg_pmtu {
403 1.1 jmcneill uint8_t rp_reserved1;
404 1.1 jmcneill uint8_t rp_local_port;
405 1.1 jmcneill uint8_t rp_reserved2[2];
406 1.1 jmcneill uint16_t rp_max_mtu;
407 1.1 jmcneill uint8_t rp_reserved3[2];
408 1.1 jmcneill uint16_t rp_admin_mtu;
409 1.1 jmcneill uint8_t rp_reserved4[2];
410 1.1 jmcneill uint16_t rp_oper_mtu;
411 1.1 jmcneill uint8_t rp_reserved5[2];
412 1.1 jmcneill } __packed __aligned(4);
413 1.1 jmcneill
414 1.1 jmcneill struct mcx_reg_ptys {
415 1.1 jmcneill uint8_t rp_reserved1;
416 1.1 jmcneill uint8_t rp_local_port;
417 1.1 jmcneill uint8_t rp_reserved2;
418 1.1 jmcneill uint8_t rp_proto_mask;
419 1.1 jmcneill #define MCX_REG_PTYS_PROTO_MASK_ETH (1 << 2)
420 1.1 jmcneill uint8_t rp_reserved3[8];
421 1.1 jmcneill uint32_t rp_eth_proto_cap;
422 1.1 jmcneill uint8_t rp_reserved4[8];
423 1.1 jmcneill uint32_t rp_eth_proto_admin;
424 1.1 jmcneill uint8_t rp_reserved5[8];
425 1.1 jmcneill uint32_t rp_eth_proto_oper;
426 1.1 jmcneill uint8_t rp_reserved6[24];
427 1.1 jmcneill } __packed __aligned(4);
428 1.1 jmcneill
429 1.1 jmcneill struct mcx_reg_paos {
430 1.1 jmcneill uint8_t rp_reserved1;
431 1.1 jmcneill uint8_t rp_local_port;
432 1.1 jmcneill uint8_t rp_admin_status;
433 1.1 jmcneill #define MCX_REG_PAOS_ADMIN_STATUS_UP 1
434 1.1 jmcneill #define MCX_REG_PAOS_ADMIN_STATUS_DOWN 2
435 1.1 jmcneill #define MCX_REG_PAOS_ADMIN_STATUS_UP_ONCE 3
436 1.1 jmcneill #define MCX_REG_PAOS_ADMIN_STATUS_DISABLED 4
437 1.1 jmcneill uint8_t rp_oper_status;
438 1.1 jmcneill #define MCX_REG_PAOS_OPER_STATUS_UP 1
439 1.1 jmcneill #define MCX_REG_PAOS_OPER_STATUS_DOWN 2
440 1.1 jmcneill #define MCX_REG_PAOS_OPER_STATUS_FAILED 4
441 1.1 jmcneill uint8_t rp_admin_state_update;
442 1.1 jmcneill #define MCX_REG_PAOS_ADMIN_STATE_UPDATE_EN (1 << 7)
443 1.1 jmcneill uint8_t rp_reserved2[11];
444 1.1 jmcneill } __packed __aligned(4);
445 1.1 jmcneill
446 1.1 jmcneill struct mcx_reg_pfcc {
447 1.1 jmcneill uint8_t rp_reserved1;
448 1.1 jmcneill uint8_t rp_local_port;
449 1.1 jmcneill uint8_t rp_reserved2[3];
450 1.1 jmcneill uint8_t rp_prio_mask_tx;
451 1.1 jmcneill uint8_t rp_reserved3;
452 1.1 jmcneill uint8_t rp_prio_mask_rx;
453 1.1 jmcneill uint8_t rp_pptx_aptx;
454 1.1 jmcneill uint8_t rp_pfctx;
455 1.1 jmcneill uint8_t rp_fctx_dis;
456 1.1 jmcneill uint8_t rp_reserved4;
457 1.1 jmcneill uint8_t rp_pprx_aprx;
458 1.1 jmcneill uint8_t rp_pfcrx;
459 1.1 jmcneill uint8_t rp_reserved5[2];
460 1.1 jmcneill uint16_t rp_dev_stall_min;
461 1.1 jmcneill uint16_t rp_dev_stall_crit;
462 1.1 jmcneill uint8_t rp_reserved6[12];
463 1.1 jmcneill } __packed __aligned(4);
464 1.1 jmcneill
465 1.1 jmcneill #define MCX_PMLP_MODULE_NUM_MASK 0xff
466 1.1 jmcneill struct mcx_reg_pmlp {
467 1.1 jmcneill uint8_t rp_rxtx;
468 1.1 jmcneill uint8_t rp_local_port;
469 1.1 jmcneill uint8_t rp_reserved0;
470 1.1 jmcneill uint8_t rp_width;
471 1.1 jmcneill uint32_t rp_lane0_mapping;
472 1.1 jmcneill uint32_t rp_lane1_mapping;
473 1.1 jmcneill uint32_t rp_lane2_mapping;
474 1.1 jmcneill uint32_t rp_lane3_mapping;
475 1.1 jmcneill uint8_t rp_reserved1[44];
476 1.1 jmcneill } __packed __aligned(4);
477 1.1 jmcneill
478 1.15 jmcneill struct mcx_reg_ppcnt {
479 1.15 jmcneill uint8_t ppcnt_swid;
480 1.15 jmcneill uint8_t ppcnt_local_port;
481 1.15 jmcneill uint8_t ppcnt_pnat;
482 1.15 jmcneill uint8_t ppcnt_grp;
483 1.15 jmcneill #define MCX_REG_PPCNT_GRP_IEEE8023 0x00
484 1.15 jmcneill #define MCX_REG_PPCNT_GRP_RFC2863 0x01
485 1.15 jmcneill #define MCX_REG_PPCNT_GRP_RFC2819 0x02
486 1.15 jmcneill #define MCX_REG_PPCNT_GRP_RFC3635 0x03
487 1.15 jmcneill #define MCX_REG_PPCNT_GRP_PER_PRIO 0x10
488 1.15 jmcneill #define MCX_REG_PPCNT_GRP_PER_TC 0x11
489 1.15 jmcneill #define MCX_REG_PPCNT_GRP_PER_RX_BUFFER 0x11
490 1.15 jmcneill
491 1.15 jmcneill uint8_t ppcnt_clr;
492 1.15 jmcneill uint8_t ppcnt_reserved1[2];
493 1.15 jmcneill uint8_t ppcnt_prio_tc;
494 1.15 jmcneill #define MCX_REG_PPCNT_CLR (1 << 7)
495 1.15 jmcneill
496 1.15 jmcneill uint8_t ppcnt_counter_set[248];
497 1.15 jmcneill } __packed __aligned(8);
498 1.15 jmcneill CTASSERT(sizeof(struct mcx_reg_ppcnt) == 256);
499 1.15 jmcneill CTASSERT((offsetof(struct mcx_reg_ppcnt, ppcnt_counter_set) %
500 1.15 jmcneill sizeof(uint64_t)) == 0);
501 1.15 jmcneill
502 1.15 jmcneill enum mcx_ppcnt_ieee8023 {
503 1.15 jmcneill frames_transmitted_ok,
504 1.15 jmcneill frames_received_ok,
505 1.15 jmcneill frame_check_sequence_errors,
506 1.15 jmcneill alignment_errors,
507 1.15 jmcneill octets_transmitted_ok,
508 1.15 jmcneill octets_received_ok,
509 1.15 jmcneill multicast_frames_xmitted_ok,
510 1.15 jmcneill broadcast_frames_xmitted_ok,
511 1.15 jmcneill multicast_frames_received_ok,
512 1.15 jmcneill broadcast_frames_received_ok,
513 1.15 jmcneill in_range_length_errors,
514 1.15 jmcneill out_of_range_length_field,
515 1.15 jmcneill frame_too_long_errors,
516 1.15 jmcneill symbol_error_during_carrier,
517 1.15 jmcneill mac_control_frames_transmitted,
518 1.15 jmcneill mac_control_frames_received,
519 1.15 jmcneill unsupported_opcodes_received,
520 1.15 jmcneill pause_mac_ctrl_frames_received,
521 1.15 jmcneill pause_mac_ctrl_frames_transmitted,
522 1.15 jmcneill
523 1.15 jmcneill mcx_ppcnt_ieee8023_count
524 1.15 jmcneill };
525 1.15 jmcneill CTASSERT(mcx_ppcnt_ieee8023_count * sizeof(uint64_t) == 0x98);
526 1.15 jmcneill
527 1.15 jmcneill enum mcx_ppcnt_rfc2863 {
528 1.15 jmcneill in_octets,
529 1.15 jmcneill in_ucast_pkts,
530 1.15 jmcneill in_discards,
531 1.15 jmcneill in_errors,
532 1.15 jmcneill in_unknown_protos,
533 1.15 jmcneill out_octets,
534 1.15 jmcneill out_ucast_pkts,
535 1.15 jmcneill out_discards,
536 1.15 jmcneill out_errors,
537 1.15 jmcneill in_multicast_pkts,
538 1.15 jmcneill in_broadcast_pkts,
539 1.15 jmcneill out_multicast_pkts,
540 1.15 jmcneill out_broadcast_pkts,
541 1.15 jmcneill
542 1.15 jmcneill mcx_ppcnt_rfc2863_count
543 1.15 jmcneill };
544 1.15 jmcneill CTASSERT(mcx_ppcnt_rfc2863_count * sizeof(uint64_t) == 0x68);
545 1.15 jmcneill
546 1.15 jmcneill enum mcx_ppcnt_rfc2819 {
547 1.15 jmcneill drop_events,
548 1.15 jmcneill octets,
549 1.15 jmcneill pkts,
550 1.15 jmcneill broadcast_pkts,
551 1.15 jmcneill multicast_pkts,
552 1.15 jmcneill crc_align_errors,
553 1.15 jmcneill undersize_pkts,
554 1.15 jmcneill oversize_pkts,
555 1.15 jmcneill fragments,
556 1.15 jmcneill jabbers,
557 1.15 jmcneill collisions,
558 1.15 jmcneill pkts64octets,
559 1.15 jmcneill pkts65to127octets,
560 1.15 jmcneill pkts128to255octets,
561 1.15 jmcneill pkts256to511octets,
562 1.15 jmcneill pkts512to1023octets,
563 1.15 jmcneill pkts1024to1518octets,
564 1.15 jmcneill pkts1519to2047octets,
565 1.15 jmcneill pkts2048to4095octets,
566 1.15 jmcneill pkts4096to8191octets,
567 1.15 jmcneill pkts8192to10239octets,
568 1.15 jmcneill
569 1.15 jmcneill mcx_ppcnt_rfc2819_count
570 1.15 jmcneill };
571 1.15 jmcneill CTASSERT((mcx_ppcnt_rfc2819_count * sizeof(uint64_t)) == 0xa8);
572 1.15 jmcneill
573 1.15 jmcneill enum mcx_ppcnt_rfc3635 {
574 1.15 jmcneill dot3stats_alignment_errors,
575 1.15 jmcneill dot3stats_fcs_errors,
576 1.15 jmcneill dot3stats_single_collision_frames,
577 1.15 jmcneill dot3stats_multiple_collision_frames,
578 1.15 jmcneill dot3stats_sqe_test_errors,
579 1.15 jmcneill dot3stats_deferred_transmissions,
580 1.15 jmcneill dot3stats_late_collisions,
581 1.15 jmcneill dot3stats_excessive_collisions,
582 1.15 jmcneill dot3stats_internal_mac_transmit_errors,
583 1.15 jmcneill dot3stats_carrier_sense_errors,
584 1.15 jmcneill dot3stats_frame_too_longs,
585 1.15 jmcneill dot3stats_internal_mac_receive_errors,
586 1.15 jmcneill dot3stats_symbol_errors,
587 1.15 jmcneill dot3control_in_unknown_opcodes,
588 1.15 jmcneill dot3in_pause_frames,
589 1.15 jmcneill dot3out_pause_frames,
590 1.15 jmcneill
591 1.15 jmcneill mcx_ppcnt_rfc3635_count
592 1.15 jmcneill };
593 1.15 jmcneill CTASSERT((mcx_ppcnt_rfc3635_count * sizeof(uint64_t)) == 0x80);
594 1.15 jmcneill
595 1.15 jmcneill struct mcx_reg_mcam {
596 1.15 jmcneill uint8_t _reserved1[1];
597 1.15 jmcneill uint8_t mcam_feature_group;
598 1.15 jmcneill uint8_t _reserved2[1];
599 1.15 jmcneill uint8_t mcam_access_reg_group;
600 1.15 jmcneill uint8_t _reserved3[4];
601 1.15 jmcneill uint8_t mcam_access_reg_cap_mask[16];
602 1.15 jmcneill uint8_t _reserved4[16];
603 1.15 jmcneill uint8_t mcam_feature_cap_mask[16];
604 1.15 jmcneill uint8_t _reserved5[16];
605 1.15 jmcneill } __packed __aligned(4);
606 1.15 jmcneill
607 1.15 jmcneill #define MCX_BITFIELD_BIT(bf, b) (bf[(sizeof bf - 1) - (b / 8)] & (b % 8))
608 1.15 jmcneill
609 1.15 jmcneill #define MCX_MCAM_FEATURE_CAP_SENSOR_MAP 6
610 1.15 jmcneill
611 1.15 jmcneill struct mcx_reg_mtcap {
612 1.15 jmcneill uint8_t _reserved1[3];
613 1.15 jmcneill uint8_t mtcap_sensor_count;
614 1.15 jmcneill uint8_t _reserved2[4];
615 1.15 jmcneill
616 1.15 jmcneill uint64_t mtcap_sensor_map;
617 1.15 jmcneill };
618 1.15 jmcneill
619 1.15 jmcneill struct mcx_reg_mtmp {
620 1.15 jmcneill uint8_t _reserved1[2];
621 1.15 jmcneill uint16_t mtmp_sensor_index;
622 1.15 jmcneill
623 1.15 jmcneill uint8_t _reserved2[2];
624 1.15 jmcneill uint16_t mtmp_temperature;
625 1.15 jmcneill
626 1.15 jmcneill uint16_t mtmp_mte_mtr;
627 1.15 jmcneill #define MCX_REG_MTMP_MTE (1 << 15)
628 1.15 jmcneill #define MCX_REG_MTMP_MTR (1 << 14)
629 1.15 jmcneill uint16_t mtmp_max_temperature;
630 1.15 jmcneill
631 1.15 jmcneill uint16_t mtmp_tee;
632 1.15 jmcneill #define MCX_REG_MTMP_TEE_NOPE (0 << 14)
633 1.15 jmcneill #define MCX_REG_MTMP_TEE_GENERATE (1 << 14)
634 1.15 jmcneill #define MCX_REG_MTMP_TEE_GENERATE_ONE (2 << 14)
635 1.15 jmcneill uint16_t mtmp_temperature_threshold_hi;
636 1.15 jmcneill
637 1.15 jmcneill uint8_t _reserved3[2];
638 1.15 jmcneill uint16_t mtmp_temperature_threshold_lo;
639 1.15 jmcneill
640 1.15 jmcneill uint8_t _reserved4[4];
641 1.15 jmcneill
642 1.15 jmcneill uint8_t mtmp_sensor_name[8];
643 1.15 jmcneill };
644 1.15 jmcneill CTASSERT(sizeof(struct mcx_reg_mtmp) == 0x20);
645 1.15 jmcneill CTASSERT(offsetof(struct mcx_reg_mtmp, mtmp_sensor_name) == 0x18);
646 1.15 jmcneill
647 1.1 jmcneill #define MCX_MCIA_EEPROM_BYTES 32
648 1.1 jmcneill struct mcx_reg_mcia {
649 1.1 jmcneill uint8_t rm_l;
650 1.1 jmcneill uint8_t rm_module;
651 1.1 jmcneill uint8_t rm_reserved0;
652 1.1 jmcneill uint8_t rm_status;
653 1.1 jmcneill uint8_t rm_i2c_addr;
654 1.1 jmcneill uint8_t rm_page_num;
655 1.1 jmcneill uint16_t rm_dev_addr;
656 1.1 jmcneill uint16_t rm_reserved1;
657 1.1 jmcneill uint16_t rm_size;
658 1.1 jmcneill uint32_t rm_reserved2;
659 1.1 jmcneill uint8_t rm_data[48];
660 1.1 jmcneill } __packed __aligned(4);
661 1.1 jmcneill
662 1.1 jmcneill struct mcx_cmd_query_issi_in {
663 1.1 jmcneill uint16_t cmd_opcode;
664 1.1 jmcneill uint8_t cmd_reserved0[4];
665 1.1 jmcneill uint16_t cmd_op_mod;
666 1.1 jmcneill uint8_t cmd_reserved1[8];
667 1.1 jmcneill } __packed __aligned(4);
668 1.1 jmcneill
669 1.1 jmcneill struct mcx_cmd_query_issi_il_out {
670 1.1 jmcneill uint8_t cmd_status;
671 1.1 jmcneill uint8_t cmd_reserved0[3];
672 1.1 jmcneill uint32_t cmd_syndrome;
673 1.1 jmcneill uint8_t cmd_reserved1[2];
674 1.1 jmcneill uint16_t cmd_current_issi;
675 1.1 jmcneill uint8_t cmd_reserved2[4];
676 1.1 jmcneill } __packed __aligned(4);
677 1.1 jmcneill
678 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_query_issi_il_out) == MCX_CMDQ_INLINE_DATASIZE);
679 1.1 jmcneill
680 1.1 jmcneill struct mcx_cmd_query_issi_mb_out {
681 1.1 jmcneill uint8_t cmd_reserved2[16];
682 1.1 jmcneill uint8_t cmd_supported_issi[80]; /* very big endian */
683 1.1 jmcneill } __packed __aligned(4);
684 1.1 jmcneill
685 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_query_issi_mb_out) <= MCX_CMDQ_MAILBOX_DATASIZE);
686 1.1 jmcneill
687 1.1 jmcneill struct mcx_cmd_set_issi_in {
688 1.1 jmcneill uint16_t cmd_opcode;
689 1.1 jmcneill uint8_t cmd_reserved0[4];
690 1.1 jmcneill uint16_t cmd_op_mod;
691 1.1 jmcneill uint8_t cmd_reserved1[2];
692 1.1 jmcneill uint16_t cmd_current_issi;
693 1.1 jmcneill uint8_t cmd_reserved2[4];
694 1.1 jmcneill } __packed __aligned(4);
695 1.1 jmcneill
696 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_set_issi_in) <= MCX_CMDQ_INLINE_DATASIZE);
697 1.1 jmcneill
698 1.1 jmcneill struct mcx_cmd_set_issi_out {
699 1.1 jmcneill uint8_t cmd_status;
700 1.1 jmcneill uint8_t cmd_reserved0[3];
701 1.1 jmcneill uint32_t cmd_syndrome;
702 1.1 jmcneill uint8_t cmd_reserved1[8];
703 1.1 jmcneill } __packed __aligned(4);
704 1.1 jmcneill
705 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_set_issi_out) <= MCX_CMDQ_INLINE_DATASIZE);
706 1.1 jmcneill
707 1.1 jmcneill struct mcx_cmd_query_pages_in {
708 1.1 jmcneill uint16_t cmd_opcode;
709 1.1 jmcneill uint8_t cmd_reserved0[4];
710 1.1 jmcneill uint16_t cmd_op_mod;
711 1.1 jmcneill #define MCX_CMD_QUERY_PAGES_BOOT 0x01
712 1.1 jmcneill #define MCX_CMD_QUERY_PAGES_INIT 0x02
713 1.1 jmcneill #define MCX_CMD_QUERY_PAGES_REGULAR 0x03
714 1.1 jmcneill uint8_t cmd_reserved1[8];
715 1.1 jmcneill } __packed __aligned(4);
716 1.1 jmcneill
717 1.1 jmcneill struct mcx_cmd_query_pages_out {
718 1.1 jmcneill uint8_t cmd_status;
719 1.1 jmcneill uint8_t cmd_reserved0[3];
720 1.1 jmcneill uint32_t cmd_syndrome;
721 1.1 jmcneill uint8_t cmd_reserved1[2];
722 1.1 jmcneill uint16_t cmd_func_id;
723 1.15 jmcneill int32_t cmd_num_pages;
724 1.1 jmcneill } __packed __aligned(4);
725 1.1 jmcneill
726 1.1 jmcneill struct mcx_cmd_manage_pages_in {
727 1.1 jmcneill uint16_t cmd_opcode;
728 1.1 jmcneill uint8_t cmd_reserved0[4];
729 1.1 jmcneill uint16_t cmd_op_mod;
730 1.1 jmcneill #define MCX_CMD_MANAGE_PAGES_ALLOC_FAIL \
731 1.1 jmcneill 0x00
732 1.1 jmcneill #define MCX_CMD_MANAGE_PAGES_ALLOC_SUCCESS \
733 1.1 jmcneill 0x01
734 1.1 jmcneill #define MCX_CMD_MANAGE_PAGES_HCA_RETURN_PAGES \
735 1.1 jmcneill 0x02
736 1.1 jmcneill uint8_t cmd_reserved1[2];
737 1.1 jmcneill uint16_t cmd_func_id;
738 1.1 jmcneill uint32_t cmd_input_num_entries;
739 1.1 jmcneill } __packed __aligned(4);
740 1.1 jmcneill
741 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_manage_pages_in) == MCX_CMDQ_INLINE_DATASIZE);
742 1.1 jmcneill
743 1.1 jmcneill struct mcx_cmd_manage_pages_out {
744 1.1 jmcneill uint8_t cmd_status;
745 1.1 jmcneill uint8_t cmd_reserved0[3];
746 1.1 jmcneill uint32_t cmd_syndrome;
747 1.1 jmcneill uint32_t cmd_output_num_entries;
748 1.1 jmcneill uint8_t cmd_reserved1[4];
749 1.1 jmcneill } __packed __aligned(4);
750 1.1 jmcneill
751 1.1 jmcneill CTASSERT(sizeof(struct mcx_cmd_manage_pages_out) == MCX_CMDQ_INLINE_DATASIZE);
752 1.1 jmcneill
753 1.1 jmcneill struct mcx_cmd_query_hca_cap_in {
754 1.1 jmcneill uint16_t cmd_opcode;
755 1.1 jmcneill uint8_t cmd_reserved0[4];
756 1.1 jmcneill uint16_t cmd_op_mod;
757 1.1 jmcneill #define MCX_CMD_QUERY_HCA_CAP_MAX (0x0 << 0)
758 1.1 jmcneill #define MCX_CMD_QUERY_HCA_CAP_CURRENT (0x1 << 0)
759 1.1 jmcneill #define MCX_CMD_QUERY_HCA_CAP_DEVICE (0x0 << 1)
760 1.1 jmcneill #define MCX_CMD_QUERY_HCA_CAP_OFFLOAD (0x1 << 1)
761 1.1 jmcneill #define MCX_CMD_QUERY_HCA_CAP_FLOW (0x7 << 1)
762 1.1 jmcneill uint8_t cmd_reserved1[8];
763 1.1 jmcneill } __packed __aligned(4);
764 1.1 jmcneill
765 1.1 jmcneill struct mcx_cmd_query_hca_cap_out {
766 1.1 jmcneill uint8_t cmd_status;
767 1.1 jmcneill uint8_t cmd_reserved0[3];
768 1.1 jmcneill uint32_t cmd_syndrome;
769 1.1 jmcneill uint8_t cmd_reserved1[8];
770 1.1 jmcneill } __packed __aligned(4);
771 1.1 jmcneill
772 1.1 jmcneill #define MCX_HCA_CAP_LEN 0x1000
773 1.1 jmcneill #define MCX_HCA_CAP_NMAILBOXES \
774 1.1 jmcneill (MCX_HCA_CAP_LEN / MCX_CMDQ_MAILBOX_DATASIZE)
775 1.1 jmcneill
776 1.1 jmcneill #if __GNUC_PREREQ__(4, 3)
777 1.1 jmcneill #define __counter__ __COUNTER__
778 1.1 jmcneill #else
779 1.1 jmcneill #define __counter__ __LINE__
780 1.1 jmcneill #endif
781 1.1 jmcneill
782 1.1 jmcneill #define __token(_tok, _num) _tok##_num
783 1.1 jmcneill #define _token(_tok, _num) __token(_tok, _num)
784 1.1 jmcneill #define __reserved__ _token(__reserved, __counter__)
785 1.1 jmcneill
786 1.1 jmcneill struct mcx_cap_device {
787 1.1 jmcneill uint8_t reserved0[16];
788 1.1 jmcneill
789 1.1 jmcneill uint8_t log_max_srq_sz;
790 1.1 jmcneill uint8_t log_max_qp_sz;
791 1.1 jmcneill uint8_t __reserved__[1];
792 1.1 jmcneill uint8_t log_max_qp; /* 5 bits */
793 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_QP 0x1f
794 1.1 jmcneill
795 1.1 jmcneill uint8_t __reserved__[1];
796 1.1 jmcneill uint8_t log_max_srq; /* 5 bits */
797 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_SRQ 0x1f
798 1.1 jmcneill uint8_t __reserved__[2];
799 1.1 jmcneill
800 1.1 jmcneill uint8_t __reserved__[1];
801 1.1 jmcneill uint8_t log_max_cq_sz;
802 1.1 jmcneill uint8_t __reserved__[1];
803 1.1 jmcneill uint8_t log_max_cq; /* 5 bits */
804 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_CQ 0x1f
805 1.1 jmcneill
806 1.1 jmcneill uint8_t log_max_eq_sz;
807 1.1 jmcneill uint8_t log_max_mkey; /* 6 bits */
808 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_MKEY 0x3f
809 1.1 jmcneill uint8_t __reserved__[1];
810 1.1 jmcneill uint8_t log_max_eq; /* 4 bits */
811 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_EQ 0x0f
812 1.1 jmcneill
813 1.1 jmcneill uint8_t max_indirection;
814 1.1 jmcneill uint8_t log_max_mrw_sz; /* 7 bits */
815 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_MRW_SZ 0x7f
816 1.1 jmcneill uint8_t teardown_log_max_msf_list_size;
817 1.1 jmcneill #define MCX_CAP_DEVICE_FORCE_TEARDOWN 0x80
818 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_MSF_LIST_SIZE \
819 1.1 jmcneill 0x3f
820 1.1 jmcneill uint8_t log_max_klm_list_size; /* 6 bits */
821 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_KLM_LIST_SIZE \
822 1.1 jmcneill 0x3f
823 1.1 jmcneill
824 1.1 jmcneill uint8_t __reserved__[1];
825 1.1 jmcneill uint8_t log_max_ra_req_dc; /* 6 bits */
826 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_REQ_DC 0x3f
827 1.1 jmcneill uint8_t __reserved__[1];
828 1.1 jmcneill uint8_t log_max_ra_res_dc; /* 6 bits */
829 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RA_RES_DC \
830 1.1 jmcneill 0x3f
831 1.1 jmcneill
832 1.1 jmcneill uint8_t __reserved__[1];
833 1.1 jmcneill uint8_t log_max_ra_req_qp; /* 6 bits */
834 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RA_REQ_QP \
835 1.1 jmcneill 0x3f
836 1.1 jmcneill uint8_t __reserved__[1];
837 1.1 jmcneill uint8_t log_max_ra_res_qp; /* 6 bits */
838 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RA_RES_QP \
839 1.1 jmcneill 0x3f
840 1.1 jmcneill
841 1.1 jmcneill uint8_t flags1;
842 1.1 jmcneill #define MCX_CAP_DEVICE_END_PAD 0x80
843 1.1 jmcneill #define MCX_CAP_DEVICE_CC_QUERY_ALLOWED 0x40
844 1.1 jmcneill #define MCX_CAP_DEVICE_CC_MODIFY_ALLOWED \
845 1.1 jmcneill 0x20
846 1.1 jmcneill #define MCX_CAP_DEVICE_START_PAD 0x10
847 1.1 jmcneill #define MCX_CAP_DEVICE_128BYTE_CACHELINE \
848 1.1 jmcneill 0x08
849 1.1 jmcneill uint8_t __reserved__[1];
850 1.1 jmcneill uint16_t gid_table_size;
851 1.1 jmcneill
852 1.1 jmcneill uint16_t flags2;
853 1.1 jmcneill #define MCX_CAP_DEVICE_OUT_OF_SEQ_CNT 0x8000
854 1.1 jmcneill #define MCX_CAP_DEVICE_VPORT_COUNTERS 0x4000
855 1.1 jmcneill #define MCX_CAP_DEVICE_RETRANSMISSION_Q_COUNTERS \
856 1.1 jmcneill 0x2000
857 1.1 jmcneill #define MCX_CAP_DEVICE_DEBUG 0x1000
858 1.1 jmcneill #define MCX_CAP_DEVICE_MODIFY_RQ_COUNTERS_SET_ID \
859 1.1 jmcneill 0x8000
860 1.1 jmcneill #define MCX_CAP_DEVICE_RQ_DELAY_DROP 0x4000
861 1.1 jmcneill #define MCX_CAP_DEVICe_MAX_QP_CNT_MASK 0x03ff
862 1.1 jmcneill uint16_t pkey_table_size;
863 1.1 jmcneill
864 1.1 jmcneill uint8_t flags3;
865 1.1 jmcneill #define MCX_CAP_DEVICE_VPORT_GROUP_MANAGER \
866 1.1 jmcneill 0x80
867 1.1 jmcneill #define MCX_CAP_DEVICE_VHCA_GROUP_MANAGER \
868 1.1 jmcneill 0x40
869 1.1 jmcneill #define MCX_CAP_DEVICE_IB_VIRTUAL 0x20
870 1.1 jmcneill #define MCX_CAP_DEVICE_ETH_VIRTUAL 0x10
871 1.1 jmcneill #define MCX_CAP_DEVICE_ETS 0x04
872 1.1 jmcneill #define MCX_CAP_DEVICE_NIC_FLOW_TABLE 0x02
873 1.1 jmcneill #define MCX_CAP_DEVICE_ESWITCH_FLOW_TABLE \
874 1.1 jmcneill 0x01
875 1.1 jmcneill uint8_t local_ca_ack_delay; /* 5 bits */
876 1.1 jmcneill #define MCX_CAP_DEVICE_LOCAL_CA_ACK_DELAY \
877 1.1 jmcneill 0x1f
878 1.15 jmcneill #define MCX_CAP_DEVICE_MCAM_REG 0x40
879 1.1 jmcneill uint8_t port_type;
880 1.1 jmcneill #define MCX_CAP_DEVICE_PORT_MODULE_EVENT \
881 1.1 jmcneill 0x80
882 1.1 jmcneill #define MCX_CAP_DEVICE_PORT_TYPE 0x03
883 1.15 jmcneill #define MCX_CAP_DEVICE_PORT_TYPE_ETH 0x01
884 1.1 jmcneill uint8_t num_ports;
885 1.1 jmcneill
886 1.1 jmcneill uint8_t snapshot_log_max_msg;
887 1.1 jmcneill #define MCX_CAP_DEVICE_SNAPSHOT 0x80
888 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_MSG 0x1f
889 1.1 jmcneill uint8_t max_tc; /* 4 bits */
890 1.1 jmcneill #define MCX_CAP_DEVICE_MAX_TC 0x0f
891 1.1 jmcneill uint8_t flags4;
892 1.1 jmcneill #define MCX_CAP_DEVICE_TEMP_WARN_EVENT 0x80
893 1.1 jmcneill #define MCX_CAP_DEVICE_DCBX 0x40
894 1.1 jmcneill #define MCX_CAP_DEVICE_ROL_S 0x02
895 1.1 jmcneill #define MCX_CAP_DEVICE_ROL_G 0x01
896 1.1 jmcneill uint8_t wol;
897 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_S 0x40
898 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_G 0x20
899 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_A 0x10
900 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_B 0x08
901 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_M 0x04
902 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_U 0x02
903 1.1 jmcneill #define MCX_CAP_DEVICE_WOL_P 0x01
904 1.1 jmcneill
905 1.1 jmcneill uint16_t stat_rate_support;
906 1.1 jmcneill uint8_t __reserved__[1];
907 1.1 jmcneill uint8_t cqe_version; /* 4 bits */
908 1.1 jmcneill #define MCX_CAP_DEVICE_CQE_VERSION 0x0f
909 1.1 jmcneill
910 1.1 jmcneill uint32_t flags5;
911 1.1 jmcneill #define MCX_CAP_DEVICE_COMPACT_ADDRESS_VECTOR \
912 1.1 jmcneill 0x80000000
913 1.1 jmcneill #define MCX_CAP_DEVICE_STRIDING_RQ 0x40000000
914 1.1 jmcneill #define MCX_CAP_DEVICE_IPOIP_ENHANCED_OFFLOADS \
915 1.1 jmcneill 0x10000000
916 1.1 jmcneill #define MCX_CAP_DEVICE_IPOIP_IPOIP_OFFLOADS \
917 1.1 jmcneill 0x08000000
918 1.1 jmcneill #define MCX_CAP_DEVICE_DC_CONNECT_CP 0x00040000
919 1.1 jmcneill #define MCX_CAP_DEVICE_DC_CNAK_DRACE 0x00020000
920 1.1 jmcneill #define MCX_CAP_DEVICE_DRAIN_SIGERR 0x00010000
921 1.1 jmcneill #define MCX_CAP_DEVICE_DRAIN_SIGERR 0x00010000
922 1.1 jmcneill #define MCX_CAP_DEVICE_CMDIF_CHECKSUM 0x0000c000
923 1.1 jmcneill #define MCX_CAP_DEVICE_SIGERR_QCE 0x00002000
924 1.1 jmcneill #define MCX_CAP_DEVICE_WQ_SIGNATURE 0x00000800
925 1.1 jmcneill #define MCX_CAP_DEVICE_SCTR_DATA_CQE 0x00000400
926 1.1 jmcneill #define MCX_CAP_DEVICE_SHO 0x00000100
927 1.1 jmcneill #define MCX_CAP_DEVICE_TPH 0x00000080
928 1.1 jmcneill #define MCX_CAP_DEVICE_RF 0x00000040
929 1.1 jmcneill #define MCX_CAP_DEVICE_DCT 0x00000020
930 1.1 jmcneill #define MCX_CAP_DEVICE_QOS 0x00000010
931 1.1 jmcneill #define MCX_CAP_DEVICe_ETH_NET_OFFLOADS 0x00000008
932 1.1 jmcneill #define MCX_CAP_DEVICE_ROCE 0x00000004
933 1.1 jmcneill #define MCX_CAP_DEVICE_ATOMIC 0x00000002
934 1.1 jmcneill
935 1.1 jmcneill uint32_t flags6;
936 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_OI 0x80000000
937 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_RESIZE 0x40000000
938 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_MODERATION 0x20000000
939 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_PERIOD_MODE_MODIFY \
940 1.1 jmcneill 0x10000000
941 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_INVALIDATE 0x08000000
942 1.1 jmcneill #define MCX_CAP_DEVICE_RESERVED_AT_255 0x04000000
943 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_EQ_REMAP 0x02000000
944 1.1 jmcneill #define MCX_CAP_DEVICE_PG 0x01000000
945 1.1 jmcneill #define MCX_CAP_DEVICE_BLOCK_LB_MC 0x00800000
946 1.1 jmcneill #define MCX_CAP_DEVICE_EXPONENTIAL_BACKOFF \
947 1.1 jmcneill 0x00400000
948 1.1 jmcneill #define MCX_CAP_DEVICE_SCQE_BREAK_MODERATION \
949 1.1 jmcneill 0x00200000
950 1.1 jmcneill #define MCX_CAP_DEVICE_CQ_PERIOD_START_FROM_CQE \
951 1.1 jmcneill 0x00100000
952 1.1 jmcneill #define MCX_CAP_DEVICE_CD 0x00080000
953 1.1 jmcneill #define MCX_CAP_DEVICE_ATM 0x00040000
954 1.1 jmcneill #define MCX_CAP_DEVICE_APM 0x00020000
955 1.1 jmcneill #define MCX_CAP_DEVICE_IMAICL 0x00010000
956 1.1 jmcneill #define MCX_CAP_DEVICE_QKV 0x00000200
957 1.1 jmcneill #define MCX_CAP_DEVICE_PKV 0x00000100
958 1.1 jmcneill #define MCX_CAP_DEVICE_SET_DETH_SQPN 0x00000080
959 1.1 jmcneill #define MCX_CAP_DEVICE_XRC 0x00000008
960 1.1 jmcneill #define MCX_CAP_DEVICE_UD 0x00000004
961 1.1 jmcneill #define MCX_CAP_DEVICE_UC 0x00000002
962 1.1 jmcneill #define MCX_CAP_DEVICE_RC 0x00000001
963 1.1 jmcneill
964 1.1 jmcneill uint8_t uar_flags;
965 1.1 jmcneill #define MCX_CAP_DEVICE_UAR_4K 0x80
966 1.1 jmcneill uint8_t uar_sz; /* 6 bits */
967 1.1 jmcneill #define MCX_CAP_DEVICE_UAR_SZ 0x3f
968 1.1 jmcneill uint8_t __reserved__[1];
969 1.1 jmcneill uint8_t log_pg_sz;
970 1.1 jmcneill
971 1.1 jmcneill uint8_t flags7;
972 1.1 jmcneill #define MCX_CAP_DEVICE_BF 0x80
973 1.1 jmcneill #define MCX_CAP_DEVICE_DRIVER_VERSION 0x40
974 1.1 jmcneill #define MCX_CAP_DEVICE_PAD_TX_ETH_PACKET \
975 1.1 jmcneill 0x20
976 1.1 jmcneill uint8_t log_bf_reg_size; /* 5 bits */
977 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_BF_REG_SIZE 0x1f
978 1.1 jmcneill uint8_t __reserved__[2];
979 1.1 jmcneill
980 1.1 jmcneill uint16_t num_of_diagnostic_counters;
981 1.1 jmcneill uint16_t max_wqe_sz_sq;
982 1.1 jmcneill
983 1.1 jmcneill uint8_t __reserved__[2];
984 1.1 jmcneill uint16_t max_wqe_sz_rq;
985 1.1 jmcneill
986 1.1 jmcneill uint8_t __reserved__[2];
987 1.1 jmcneill uint16_t max_wqe_sz_sq_dc;
988 1.1 jmcneill
989 1.1 jmcneill uint32_t max_qp_mcg; /* 25 bits */
990 1.1 jmcneill #define MCX_CAP_DEVICE_MAX_QP_MCG 0x1ffffff
991 1.1 jmcneill
992 1.1 jmcneill uint8_t __reserved__[3];
993 1.1 jmcneill uint8_t log_max_mcq;
994 1.1 jmcneill
995 1.1 jmcneill uint8_t log_max_transport_domain; /* 5 bits */
996 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_TRANSORT_DOMAIN \
997 1.1 jmcneill 0x1f
998 1.1 jmcneill uint8_t log_max_pd; /* 5 bits */
999 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_PD 0x1f
1000 1.1 jmcneill uint8_t __reserved__[1];
1001 1.1 jmcneill uint8_t log_max_xrcd; /* 5 bits */
1002 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_XRCD 0x1f
1003 1.1 jmcneill
1004 1.1 jmcneill uint8_t __reserved__[2];
1005 1.1 jmcneill uint16_t max_flow_counter;
1006 1.1 jmcneill
1007 1.1 jmcneill uint8_t log_max_rq; /* 5 bits */
1008 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RQ 0x1f
1009 1.1 jmcneill uint8_t log_max_sq; /* 5 bits */
1010 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_SQ 0x1f
1011 1.1 jmcneill uint8_t log_max_tir; /* 5 bits */
1012 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_TIR 0x1f
1013 1.1 jmcneill uint8_t log_max_tis; /* 5 bits */
1014 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_TIS 0x1f
1015 1.1 jmcneill
1016 1.1 jmcneill uint8_t flags8;
1017 1.1 jmcneill #define MCX_CAP_DEVICE_BASIC_CYCLIC_RCV_WQE \
1018 1.1 jmcneill 0x80
1019 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RMP 0x1f
1020 1.1 jmcneill uint8_t log_max_rqt; /* 5 bits */
1021 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RQT 0x1f
1022 1.1 jmcneill uint8_t log_max_rqt_size; /* 5 bits */
1023 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_RQT_SIZE 0x1f
1024 1.1 jmcneill uint8_t log_max_tis_per_sq; /* 5 bits */
1025 1.1 jmcneill #define MCX_CAP_DEVICE_LOG_MAX_TIS_PER_SQ \
1026 1.1 jmcneill 0x1f
1027 1.15 jmcneill
1028 1.15 jmcneill uint8_t flags9;
1029 1.15 jmcneill #define MXC_CAP_DEVICE_EXT_STRIDE_NUM_RANGES \
1030 1.15 jmcneill 0x80
1031 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_STRIDE_SZ_RQ \
1032 1.15 jmcneill 0x1f
1033 1.15 jmcneill uint8_t log_min_stride_sz_rq; /* 5 bits */
1034 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MIN_STRIDE_SZ_RQ \
1035 1.15 jmcneill 0x1f
1036 1.15 jmcneill uint8_t log_max_stride_sz_sq; /* 5 bits */
1037 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_STRIDE_SZ_SQ \
1038 1.15 jmcneill 0x1f
1039 1.15 jmcneill uint8_t log_min_stride_sz_sq; /* 5 bits */
1040 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MIN_STRIDE_SZ_SQ \
1041 1.15 jmcneill 0x1f
1042 1.15 jmcneill
1043 1.15 jmcneill uint8_t log_max_hairpin_queues;
1044 1.15 jmcneill #define MXC_CAP_DEVICE_HAIRPIN 0x80
1045 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_HAIRPIN_QUEUES \
1046 1.15 jmcneill 0x1f
1047 1.15 jmcneill uint8_t log_min_hairpin_queues;
1048 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MIN_HAIRPIN_QUEUES \
1049 1.15 jmcneill 0x1f
1050 1.15 jmcneill uint8_t log_max_hairpin_num_packets;
1051 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_HAIRPIN_NUM_PACKETS \
1052 1.15 jmcneill 0x1f
1053 1.15 jmcneill uint8_t log_max_mq_sz;
1054 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_WQ_SZ \
1055 1.15 jmcneill 0x1f
1056 1.15 jmcneill
1057 1.15 jmcneill uint8_t log_min_hairpin_wq_data_sz;
1058 1.15 jmcneill #define MXC_CAP_DEVICE_NIC_VPORT_CHANGE_EVENT \
1059 1.15 jmcneill 0x80
1060 1.15 jmcneill #define MXC_CAP_DEVICE_DISABLE_LOCAL_LB_UC \
1061 1.15 jmcneill 0x40
1062 1.15 jmcneill #define MXC_CAP_DEVICE_DISABLE_LOCAL_LB_MC \
1063 1.15 jmcneill 0x20
1064 1.15 jmcneill #define MCX_CAP_DEVICE_LOG_MIN_HAIRPIN_WQ_DATA_SZ \
1065 1.15 jmcneill 0x1f
1066 1.15 jmcneill uint8_t log_max_vlan_list;
1067 1.15 jmcneill #define MXC_CAP_DEVICE_SYSTEM_IMAGE_GUID_MODIFIABLE \
1068 1.15 jmcneill 0x80
1069 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_VLAN_LIST \
1070 1.15 jmcneill 0x1f
1071 1.15 jmcneill uint8_t log_max_current_mc_list;
1072 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_CURRENT_MC_LIST \
1073 1.15 jmcneill 0x1f
1074 1.15 jmcneill uint8_t log_max_current_uc_list;
1075 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_CURRENT_UC_LIST \
1076 1.15 jmcneill 0x1f
1077 1.15 jmcneill
1078 1.15 jmcneill uint8_t __reserved__[4];
1079 1.15 jmcneill
1080 1.15 jmcneill uint32_t create_qp_start_hint; /* 24 bits */
1081 1.15 jmcneill
1082 1.15 jmcneill uint8_t log_max_uctx; /* 5 bits */
1083 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_UCTX 0x1f
1084 1.15 jmcneill uint8_t log_max_umem; /* 5 bits */
1085 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_UMEM 0x1f
1086 1.15 jmcneill uint16_t max_num_eqs;
1087 1.15 jmcneill
1088 1.15 jmcneill uint8_t log_max_l2_table; /* 5 bits */
1089 1.15 jmcneill #define MXC_CAP_DEVICE_LOG_MAX_L2_TABLE 0x1f
1090 1.15 jmcneill uint8_t __reserved__[1];
1091 1.15 jmcneill uint16_t log_uar_page_sz;
1092 1.15 jmcneill
1093 1.15 jmcneill uint8_t __reserved__[8];
1094 1.15 jmcneill
1095 1.15 jmcneill uint32_t device_frequency_mhz;
1096 1.15 jmcneill uint32_t device_frequency_khz;
1097 1.1 jmcneill } __packed __aligned(8);
1098 1.1 jmcneill
1099 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, max_indirection) == 0x20);
1100 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, flags1) == 0x2c);
1101 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, flags2) == 0x30);
1102 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, snapshot_log_max_msg) == 0x38);
1103 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, flags5) == 0x40);
1104 1.1 jmcneill CTASSERT(offsetof(struct mcx_cap_device, flags7) == 0x4c);
1105 1.15 jmcneill CTASSERT(offsetof(struct mcx_cap_device, device_frequency_mhz) == 0x98);
1106 1.15 jmcneill CTASSERT(offsetof(struct mcx_cap_device, device_frequency_khz) == 0x9c);
1107 1.1 jmcneill CTASSERT(sizeof(struct mcx_cap_device) <= MCX_CMDQ_MAILBOX_DATASIZE);
1108 1.1 jmcneill
1109 1.1 jmcneill struct mcx_cmd_set_driver_version_in {
1110 1.1 jmcneill uint16_t cmd_opcode;
1111 1.1 jmcneill uint8_t cmd_reserved0[4];
1112 1.1 jmcneill uint16_t cmd_op_mod;
1113 1.1 jmcneill uint8_t cmd_reserved1[8];
1114 1.1 jmcneill } __packed __aligned(4);
1115 1.1 jmcneill
1116 1.1 jmcneill struct mcx_cmd_set_driver_version_out {
1117 1.1 jmcneill uint8_t cmd_status;
1118 1.1 jmcneill uint8_t cmd_reserved0[3];
1119 1.1 jmcneill uint32_t cmd_syndrome;
1120 1.1 jmcneill uint8_t cmd_reserved1[8];
1121 1.1 jmcneill } __packed __aligned(4);
1122 1.1 jmcneill
1123 1.1 jmcneill struct mcx_cmd_set_driver_version {
1124 1.1 jmcneill uint8_t cmd_driver_version[64];
1125 1.1 jmcneill } __packed __aligned(8);
1126 1.1 jmcneill
1127 1.1 jmcneill struct mcx_cmd_modify_nic_vport_context_in {
1128 1.1 jmcneill uint16_t cmd_opcode;
1129 1.1 jmcneill uint8_t cmd_reserved0[4];
1130 1.1 jmcneill uint16_t cmd_op_mod;
1131 1.1 jmcneill uint8_t cmd_reserved1[4];
1132 1.1 jmcneill uint32_t cmd_field_select;
1133 1.1 jmcneill #define MCX_CMD_MODIFY_NIC_VPORT_CONTEXT_FIELD_ADDR 0x04
1134 1.1 jmcneill #define MCX_CMD_MODIFY_NIC_VPORT_CONTEXT_FIELD_PROMISC 0x10
1135 1.1 jmcneill #define MCX_CMD_MODIFY_NIC_VPORT_CONTEXT_FIELD_MTU 0x40
1136 1.1 jmcneill } __packed __aligned(4);
1137 1.1 jmcneill
1138 1.1 jmcneill struct mcx_cmd_modify_nic_vport_context_out {
1139 1.1 jmcneill uint8_t cmd_status;
1140 1.1 jmcneill uint8_t cmd_reserved0[3];
1141 1.1 jmcneill uint32_t cmd_syndrome;
1142 1.1 jmcneill uint8_t cmd_reserved1[8];
1143 1.1 jmcneill } __packed __aligned(4);
1144 1.1 jmcneill
1145 1.1 jmcneill struct mcx_cmd_query_nic_vport_context_in {
1146 1.1 jmcneill uint16_t cmd_opcode;
1147 1.1 jmcneill uint8_t cmd_reserved0[4];
1148 1.1 jmcneill uint16_t cmd_op_mod;
1149 1.1 jmcneill uint8_t cmd_reserved1[4];
1150 1.1 jmcneill uint8_t cmd_allowed_list_type;
1151 1.1 jmcneill uint8_t cmd_reserved2[3];
1152 1.1 jmcneill } __packed __aligned(4);
1153 1.1 jmcneill
1154 1.1 jmcneill struct mcx_cmd_query_nic_vport_context_out {
1155 1.1 jmcneill uint8_t cmd_status;
1156 1.1 jmcneill uint8_t cmd_reserved0[3];
1157 1.1 jmcneill uint32_t cmd_syndrome;
1158 1.1 jmcneill uint8_t cmd_reserved1[8];
1159 1.1 jmcneill } __packed __aligned(4);
1160 1.1 jmcneill
1161 1.1 jmcneill struct mcx_nic_vport_ctx {
1162 1.1 jmcneill uint32_t vp_min_wqe_inline_mode;
1163 1.1 jmcneill uint8_t vp_reserved0[32];
1164 1.1 jmcneill uint32_t vp_mtu;
1165 1.1 jmcneill uint8_t vp_reserved1[200];
1166 1.1 jmcneill uint16_t vp_flags;
1167 1.1 jmcneill #define MCX_NIC_VPORT_CTX_LIST_UC_MAC (0)
1168 1.1 jmcneill #define MCX_NIC_VPORT_CTX_LIST_MC_MAC (1 << 24)
1169 1.1 jmcneill #define MCX_NIC_VPORT_CTX_LIST_VLAN (2 << 24)
1170 1.1 jmcneill #define MCX_NIC_VPORT_CTX_PROMISC_ALL (1 << 13)
1171 1.1 jmcneill #define MCX_NIC_VPORT_CTX_PROMISC_MCAST (1 << 14)
1172 1.1 jmcneill #define MCX_NIC_VPORT_CTX_PROMISC_UCAST (1 << 15)
1173 1.1 jmcneill uint16_t vp_allowed_list_size;
1174 1.1 jmcneill uint64_t vp_perm_addr;
1175 1.1 jmcneill uint8_t vp_reserved2[4];
1176 1.1 jmcneill /* allowed list follows */
1177 1.1 jmcneill } __packed __aligned(4);
1178 1.1 jmcneill
1179 1.1 jmcneill struct mcx_counter {
1180 1.1 jmcneill uint64_t packets;
1181 1.1 jmcneill uint64_t octets;
1182 1.1 jmcneill } __packed __aligned(4);
1183 1.1 jmcneill
1184 1.1 jmcneill struct mcx_nic_vport_counters {
1185 1.1 jmcneill struct mcx_counter rx_err;
1186 1.1 jmcneill struct mcx_counter tx_err;
1187 1.1 jmcneill uint8_t reserved0[64]; /* 0x30 */
1188 1.1 jmcneill struct mcx_counter rx_bcast;
1189 1.1 jmcneill struct mcx_counter tx_bcast;
1190 1.1 jmcneill struct mcx_counter rx_ucast;
1191 1.1 jmcneill struct mcx_counter tx_ucast;
1192 1.1 jmcneill struct mcx_counter rx_mcast;
1193 1.1 jmcneill struct mcx_counter tx_mcast;
1194 1.1 jmcneill uint8_t reserved1[0x210 - 0xd0];
1195 1.1 jmcneill } __packed __aligned(4);
1196 1.1 jmcneill
1197 1.1 jmcneill struct mcx_cmd_query_vport_counters_in {
1198 1.1 jmcneill uint16_t cmd_opcode;
1199 1.1 jmcneill uint8_t cmd_reserved0[4];
1200 1.1 jmcneill uint16_t cmd_op_mod;
1201 1.1 jmcneill uint8_t cmd_reserved1[8];
1202 1.1 jmcneill } __packed __aligned(4);
1203 1.1 jmcneill
1204 1.1 jmcneill struct mcx_cmd_query_vport_counters_mb_in {
1205 1.1 jmcneill uint8_t cmd_reserved0[8];
1206 1.1 jmcneill uint8_t cmd_clear;
1207 1.1 jmcneill uint8_t cmd_reserved1[7];
1208 1.1 jmcneill } __packed __aligned(4);
1209 1.1 jmcneill
1210 1.1 jmcneill struct mcx_cmd_query_vport_counters_out {
1211 1.1 jmcneill uint8_t cmd_status;
1212 1.1 jmcneill uint8_t cmd_reserved0[3];
1213 1.1 jmcneill uint32_t cmd_syndrome;
1214 1.1 jmcneill uint8_t cmd_reserved1[8];
1215 1.1 jmcneill } __packed __aligned(4);
1216 1.1 jmcneill
1217 1.1 jmcneill struct mcx_cmd_query_flow_counter_in {
1218 1.1 jmcneill uint16_t cmd_opcode;
1219 1.1 jmcneill uint8_t cmd_reserved0[4];
1220 1.1 jmcneill uint16_t cmd_op_mod;
1221 1.1 jmcneill uint8_t cmd_reserved1[8];
1222 1.1 jmcneill } __packed __aligned(4);
1223 1.1 jmcneill
1224 1.1 jmcneill struct mcx_cmd_query_flow_counter_mb_in {
1225 1.1 jmcneill uint8_t cmd_reserved0[8];
1226 1.1 jmcneill uint8_t cmd_clear;
1227 1.1 jmcneill uint8_t cmd_reserved1[5];
1228 1.1 jmcneill uint16_t cmd_flow_counter_id;
1229 1.1 jmcneill } __packed __aligned(4);
1230 1.1 jmcneill
1231 1.1 jmcneill struct mcx_cmd_query_flow_counter_out {
1232 1.1 jmcneill uint8_t cmd_status;
1233 1.1 jmcneill uint8_t cmd_reserved0[3];
1234 1.1 jmcneill uint32_t cmd_syndrome;
1235 1.1 jmcneill uint8_t cmd_reserved1[8];
1236 1.1 jmcneill } __packed __aligned(4);
1237 1.1 jmcneill
1238 1.1 jmcneill struct mcx_cmd_alloc_uar_in {
1239 1.1 jmcneill uint16_t cmd_opcode;
1240 1.1 jmcneill uint8_t cmd_reserved0[4];
1241 1.1 jmcneill uint16_t cmd_op_mod;
1242 1.1 jmcneill uint8_t cmd_reserved1[8];
1243 1.1 jmcneill } __packed __aligned(4);
1244 1.1 jmcneill
1245 1.1 jmcneill struct mcx_cmd_alloc_uar_out {
1246 1.1 jmcneill uint8_t cmd_status;
1247 1.1 jmcneill uint8_t cmd_reserved0[3];
1248 1.1 jmcneill uint32_t cmd_syndrome;
1249 1.1 jmcneill uint32_t cmd_uar;
1250 1.1 jmcneill uint8_t cmd_reserved1[4];
1251 1.1 jmcneill } __packed __aligned(4);
1252 1.1 jmcneill
1253 1.1 jmcneill struct mcx_cmd_query_special_ctx_in {
1254 1.1 jmcneill uint16_t cmd_opcode;
1255 1.1 jmcneill uint8_t cmd_reserved0[4];
1256 1.1 jmcneill uint16_t cmd_op_mod;
1257 1.1 jmcneill uint8_t cmd_reserved1[8];
1258 1.1 jmcneill } __packed __aligned(4);
1259 1.1 jmcneill
1260 1.1 jmcneill struct mcx_cmd_query_special_ctx_out {
1261 1.1 jmcneill uint8_t cmd_status;
1262 1.1 jmcneill uint8_t cmd_reserved0[3];
1263 1.1 jmcneill uint32_t cmd_syndrome;
1264 1.1 jmcneill uint8_t cmd_reserved1[4];
1265 1.1 jmcneill uint32_t cmd_resd_lkey;
1266 1.1 jmcneill } __packed __aligned(4);
1267 1.1 jmcneill
1268 1.1 jmcneill struct mcx_eq_ctx {
1269 1.1 jmcneill uint32_t eq_status;
1270 1.15 jmcneill #define MCX_EQ_CTX_STATE_SHIFT 8
1271 1.15 jmcneill #define MCX_EQ_CTX_STATE_MASK (0xf << MCX_EQ_CTX_STATE_SHIFT)
1272 1.15 jmcneill #define MCX_EQ_CTX_STATE_ARMED 0x9
1273 1.15 jmcneill #define MCX_EQ_CTX_STATE_FIRED 0xa
1274 1.1 jmcneill #define MCX_EQ_CTX_OI_SHIFT 17
1275 1.1 jmcneill #define MCX_EQ_CTX_OI (1 << MCX_EQ_CTX_OI_SHIFT)
1276 1.1 jmcneill #define MCX_EQ_CTX_EC_SHIFT 18
1277 1.1 jmcneill #define MCX_EQ_CTX_EC (1 << MCX_EQ_CTX_EC_SHIFT)
1278 1.1 jmcneill #define MCX_EQ_CTX_STATUS_SHIFT 28
1279 1.1 jmcneill #define MCX_EQ_CTX_STATUS_MASK (0xf << MCX_EQ_CTX_STATUS_SHIFT)
1280 1.15 jmcneill #define MCX_EQ_CTX_STATUS_OK 0x0
1281 1.15 jmcneill #define MCX_EQ_CTX_STATUS_EQ_WRITE_FAILURE 0xa
1282 1.1 jmcneill uint32_t eq_reserved1;
1283 1.1 jmcneill uint32_t eq_page_offset;
1284 1.1 jmcneill #define MCX_EQ_CTX_PAGE_OFFSET_SHIFT 5
1285 1.1 jmcneill uint32_t eq_uar_size;
1286 1.1 jmcneill #define MCX_EQ_CTX_UAR_PAGE_MASK 0xffffff
1287 1.1 jmcneill #define MCX_EQ_CTX_LOG_EQ_SIZE_SHIFT 24
1288 1.1 jmcneill uint32_t eq_reserved2;
1289 1.1 jmcneill uint8_t eq_reserved3[3];
1290 1.1 jmcneill uint8_t eq_intr;
1291 1.1 jmcneill uint32_t eq_log_page_size;
1292 1.1 jmcneill #define MCX_EQ_CTX_LOG_PAGE_SIZE_SHIFT 24
1293 1.1 jmcneill uint32_t eq_reserved4[3];
1294 1.1 jmcneill uint32_t eq_consumer_counter;
1295 1.1 jmcneill uint32_t eq_producer_counter;
1296 1.1 jmcneill #define MCX_EQ_CTX_COUNTER_MASK 0xffffff
1297 1.1 jmcneill uint32_t eq_reserved5[4];
1298 1.1 jmcneill } __packed __aligned(4);
1299 1.1 jmcneill
1300 1.1 jmcneill CTASSERT(sizeof(struct mcx_eq_ctx) == 64);
1301 1.1 jmcneill
1302 1.1 jmcneill struct mcx_cmd_create_eq_in {
1303 1.1 jmcneill uint16_t cmd_opcode;
1304 1.1 jmcneill uint8_t cmd_reserved0[4];
1305 1.1 jmcneill uint16_t cmd_op_mod;
1306 1.1 jmcneill uint8_t cmd_reserved1[8];
1307 1.1 jmcneill } __packed __aligned(4);
1308 1.1 jmcneill
1309 1.1 jmcneill struct mcx_cmd_create_eq_mb_in {
1310 1.1 jmcneill struct mcx_eq_ctx cmd_eq_ctx;
1311 1.1 jmcneill uint8_t cmd_reserved0[8];
1312 1.1 jmcneill uint64_t cmd_event_bitmask;
1313 1.1 jmcneill #define MCX_EVENT_TYPE_COMPLETION 0x00
1314 1.1 jmcneill #define MCX_EVENT_TYPE_CQ_ERROR 0x04
1315 1.1 jmcneill #define MCX_EVENT_TYPE_INTERNAL_ERROR 0x08
1316 1.1 jmcneill #define MCX_EVENT_TYPE_PORT_CHANGE 0x09
1317 1.1 jmcneill #define MCX_EVENT_TYPE_CMD_COMPLETION 0x0a
1318 1.1 jmcneill #define MCX_EVENT_TYPE_PAGE_REQUEST 0x0b
1319 1.1 jmcneill #define MCX_EVENT_TYPE_LAST_WQE 0x13
1320 1.1 jmcneill uint8_t cmd_reserved1[176];
1321 1.1 jmcneill } __packed __aligned(4);
1322 1.1 jmcneill
1323 1.1 jmcneill struct mcx_cmd_create_eq_out {
1324 1.1 jmcneill uint8_t cmd_status;
1325 1.1 jmcneill uint8_t cmd_reserved0[3];
1326 1.1 jmcneill uint32_t cmd_syndrome;
1327 1.1 jmcneill uint32_t cmd_eqn;
1328 1.1 jmcneill uint8_t cmd_reserved1[4];
1329 1.1 jmcneill } __packed __aligned(4);
1330 1.1 jmcneill
1331 1.15 jmcneill struct mcx_cmd_query_eq_in {
1332 1.15 jmcneill uint16_t cmd_opcode;
1333 1.15 jmcneill uint8_t cmd_reserved0[4];
1334 1.15 jmcneill uint16_t cmd_op_mod;
1335 1.15 jmcneill uint32_t cmd_eqn;
1336 1.15 jmcneill uint8_t cmd_reserved1[4];
1337 1.15 jmcneill } __packed __aligned(4);
1338 1.15 jmcneill
1339 1.15 jmcneill struct mcx_cmd_query_eq_out {
1340 1.15 jmcneill uint8_t cmd_status;
1341 1.15 jmcneill uint8_t cmd_reserved0[3];
1342 1.15 jmcneill uint32_t cmd_syndrome;
1343 1.15 jmcneill uint8_t cmd_reserved1[8];
1344 1.15 jmcneill } __packed __aligned(4);
1345 1.15 jmcneill
1346 1.1 jmcneill struct mcx_eq_entry {
1347 1.1 jmcneill uint8_t eq_reserved1;
1348 1.1 jmcneill uint8_t eq_event_type;
1349 1.1 jmcneill uint8_t eq_reserved2;
1350 1.1 jmcneill uint8_t eq_event_sub_type;
1351 1.1 jmcneill
1352 1.1 jmcneill uint8_t eq_reserved3[28];
1353 1.1 jmcneill uint32_t eq_event_data[7];
1354 1.1 jmcneill uint8_t eq_reserved4[2];
1355 1.1 jmcneill uint8_t eq_signature;
1356 1.1 jmcneill uint8_t eq_owner;
1357 1.1 jmcneill #define MCX_EQ_ENTRY_OWNER_INIT 1
1358 1.1 jmcneill } __packed __aligned(4);
1359 1.1 jmcneill
1360 1.1 jmcneill CTASSERT(sizeof(struct mcx_eq_entry) == 64);
1361 1.1 jmcneill
1362 1.1 jmcneill struct mcx_cmd_alloc_pd_in {
1363 1.1 jmcneill uint16_t cmd_opcode;
1364 1.1 jmcneill uint8_t cmd_reserved0[4];
1365 1.1 jmcneill uint16_t cmd_op_mod;
1366 1.1 jmcneill uint8_t cmd_reserved1[8];
1367 1.1 jmcneill } __packed __aligned(4);
1368 1.1 jmcneill
1369 1.1 jmcneill struct mcx_cmd_alloc_pd_out {
1370 1.1 jmcneill uint8_t cmd_status;
1371 1.1 jmcneill uint8_t cmd_reserved0[3];
1372 1.1 jmcneill uint32_t cmd_syndrome;
1373 1.1 jmcneill uint32_t cmd_pd;
1374 1.1 jmcneill uint8_t cmd_reserved1[4];
1375 1.1 jmcneill } __packed __aligned(4);
1376 1.1 jmcneill
1377 1.1 jmcneill struct mcx_cmd_alloc_td_in {
1378 1.1 jmcneill uint16_t cmd_opcode;
1379 1.1 jmcneill uint8_t cmd_reserved0[4];
1380 1.1 jmcneill uint16_t cmd_op_mod;
1381 1.1 jmcneill uint8_t cmd_reserved1[8];
1382 1.1 jmcneill } __packed __aligned(4);
1383 1.1 jmcneill
1384 1.1 jmcneill struct mcx_cmd_alloc_td_out {
1385 1.1 jmcneill uint8_t cmd_status;
1386 1.1 jmcneill uint8_t cmd_reserved0[3];
1387 1.1 jmcneill uint32_t cmd_syndrome;
1388 1.1 jmcneill uint32_t cmd_tdomain;
1389 1.1 jmcneill uint8_t cmd_reserved1[4];
1390 1.1 jmcneill } __packed __aligned(4);
1391 1.1 jmcneill
1392 1.1 jmcneill struct mcx_cmd_create_tir_in {
1393 1.1 jmcneill uint16_t cmd_opcode;
1394 1.1 jmcneill uint8_t cmd_reserved0[4];
1395 1.1 jmcneill uint16_t cmd_op_mod;
1396 1.1 jmcneill uint8_t cmd_reserved1[8];
1397 1.1 jmcneill } __packed __aligned(4);
1398 1.1 jmcneill
1399 1.1 jmcneill struct mcx_cmd_create_tir_mb_in {
1400 1.1 jmcneill uint8_t cmd_reserved0[20];
1401 1.1 jmcneill uint32_t cmd_disp_type;
1402 1.15 jmcneill #define MCX_TIR_CTX_DISP_TYPE_DIRECT 0
1403 1.15 jmcneill #define MCX_TIR_CTX_DISP_TYPE_INDIRECT 1
1404 1.1 jmcneill #define MCX_TIR_CTX_DISP_TYPE_SHIFT 28
1405 1.1 jmcneill uint8_t cmd_reserved1[8];
1406 1.1 jmcneill uint32_t cmd_lro;
1407 1.1 jmcneill uint8_t cmd_reserved2[8];
1408 1.1 jmcneill uint32_t cmd_inline_rqn;
1409 1.1 jmcneill uint32_t cmd_indir_table;
1410 1.1 jmcneill uint32_t cmd_tdomain;
1411 1.15 jmcneill #define MCX_TIR_CTX_HASH_TOEPLITZ 2
1412 1.15 jmcneill #define MCX_TIR_CTX_HASH_SHIFT 28
1413 1.1 jmcneill uint8_t cmd_rx_hash_key[40];
1414 1.1 jmcneill uint32_t cmd_rx_hash_sel_outer;
1415 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_SRC_IP (1 << 0)
1416 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_DST_IP (1 << 1)
1417 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_SPORT (1 << 2)
1418 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_DPORT (1 << 3)
1419 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_IPV4 (0 << 31)
1420 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_IPV6 (1 << 31)
1421 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_TCP (0 << 30)
1422 1.15 jmcneill #define MCX_TIR_CTX_HASH_SEL_UDP (1 << 30)
1423 1.1 jmcneill uint32_t cmd_rx_hash_sel_inner;
1424 1.1 jmcneill uint8_t cmd_reserved3[152];
1425 1.1 jmcneill } __packed __aligned(4);
1426 1.1 jmcneill
1427 1.1 jmcneill struct mcx_cmd_create_tir_out {
1428 1.1 jmcneill uint8_t cmd_status;
1429 1.1 jmcneill uint8_t cmd_reserved0[3];
1430 1.1 jmcneill uint32_t cmd_syndrome;
1431 1.1 jmcneill uint32_t cmd_tirn;
1432 1.1 jmcneill uint8_t cmd_reserved1[4];
1433 1.1 jmcneill } __packed __aligned(4);
1434 1.1 jmcneill
1435 1.1 jmcneill struct mcx_cmd_destroy_tir_in {
1436 1.1 jmcneill uint16_t cmd_opcode;
1437 1.1 jmcneill uint8_t cmd_reserved0[4];
1438 1.1 jmcneill uint16_t cmd_op_mod;
1439 1.1 jmcneill uint32_t cmd_tirn;
1440 1.1 jmcneill uint8_t cmd_reserved1[4];
1441 1.1 jmcneill } __packed __aligned(4);
1442 1.1 jmcneill
1443 1.1 jmcneill struct mcx_cmd_destroy_tir_out {
1444 1.1 jmcneill uint8_t cmd_status;
1445 1.1 jmcneill uint8_t cmd_reserved0[3];
1446 1.1 jmcneill uint32_t cmd_syndrome;
1447 1.1 jmcneill uint8_t cmd_reserved1[8];
1448 1.1 jmcneill } __packed __aligned(4);
1449 1.1 jmcneill
1450 1.1 jmcneill struct mcx_cmd_create_tis_in {
1451 1.1 jmcneill uint16_t cmd_opcode;
1452 1.1 jmcneill uint8_t cmd_reserved0[4];
1453 1.1 jmcneill uint16_t cmd_op_mod;
1454 1.1 jmcneill uint8_t cmd_reserved1[8];
1455 1.1 jmcneill } __packed __aligned(4);
1456 1.1 jmcneill
1457 1.1 jmcneill struct mcx_cmd_create_tis_mb_in {
1458 1.1 jmcneill uint8_t cmd_reserved[16];
1459 1.1 jmcneill uint32_t cmd_prio;
1460 1.1 jmcneill uint8_t cmd_reserved1[32];
1461 1.1 jmcneill uint32_t cmd_tdomain;
1462 1.1 jmcneill uint8_t cmd_reserved2[120];
1463 1.1 jmcneill } __packed __aligned(4);
1464 1.1 jmcneill
1465 1.1 jmcneill struct mcx_cmd_create_tis_out {
1466 1.1 jmcneill uint8_t cmd_status;
1467 1.1 jmcneill uint8_t cmd_reserved0[3];
1468 1.1 jmcneill uint32_t cmd_syndrome;
1469 1.1 jmcneill uint32_t cmd_tisn;
1470 1.1 jmcneill uint8_t cmd_reserved1[4];
1471 1.1 jmcneill } __packed __aligned(4);
1472 1.1 jmcneill
1473 1.1 jmcneill struct mcx_cmd_destroy_tis_in {
1474 1.1 jmcneill uint16_t cmd_opcode;
1475 1.1 jmcneill uint8_t cmd_reserved0[4];
1476 1.1 jmcneill uint16_t cmd_op_mod;
1477 1.1 jmcneill uint32_t cmd_tisn;
1478 1.1 jmcneill uint8_t cmd_reserved1[4];
1479 1.1 jmcneill } __packed __aligned(4);
1480 1.1 jmcneill
1481 1.1 jmcneill struct mcx_cmd_destroy_tis_out {
1482 1.1 jmcneill uint8_t cmd_status;
1483 1.1 jmcneill uint8_t cmd_reserved0[3];
1484 1.1 jmcneill uint32_t cmd_syndrome;
1485 1.1 jmcneill uint8_t cmd_reserved1[8];
1486 1.1 jmcneill } __packed __aligned(4);
1487 1.1 jmcneill
1488 1.15 jmcneill struct mcx_cmd_create_rqt_in {
1489 1.15 jmcneill uint16_t cmd_opcode;
1490 1.15 jmcneill uint8_t cmd_reserved0[4];
1491 1.15 jmcneill uint16_t cmd_op_mod;
1492 1.15 jmcneill uint8_t cmd_reserved1[8];
1493 1.15 jmcneill } __packed __aligned(4);
1494 1.15 jmcneill
1495 1.15 jmcneill struct mcx_rqt_ctx {
1496 1.15 jmcneill uint8_t cmd_reserved0[20];
1497 1.15 jmcneill uint16_t cmd_reserved1;
1498 1.15 jmcneill uint16_t cmd_rqt_max_size;
1499 1.15 jmcneill uint16_t cmd_reserved2;
1500 1.15 jmcneill uint16_t cmd_rqt_actual_size;
1501 1.15 jmcneill uint8_t cmd_reserved3[212];
1502 1.15 jmcneill } __packed __aligned(4);
1503 1.15 jmcneill
1504 1.15 jmcneill struct mcx_cmd_create_rqt_mb_in {
1505 1.15 jmcneill uint8_t cmd_reserved0[16];
1506 1.15 jmcneill struct mcx_rqt_ctx cmd_rqt;
1507 1.15 jmcneill } __packed __aligned(4);
1508 1.15 jmcneill
1509 1.15 jmcneill struct mcx_cmd_create_rqt_out {
1510 1.15 jmcneill uint8_t cmd_status;
1511 1.15 jmcneill uint8_t cmd_reserved0[3];
1512 1.15 jmcneill uint32_t cmd_syndrome;
1513 1.15 jmcneill uint32_t cmd_rqtn;
1514 1.15 jmcneill uint8_t cmd_reserved1[4];
1515 1.15 jmcneill } __packed __aligned(4);
1516 1.15 jmcneill
1517 1.15 jmcneill struct mcx_cmd_destroy_rqt_in {
1518 1.15 jmcneill uint16_t cmd_opcode;
1519 1.15 jmcneill uint8_t cmd_reserved0[4];
1520 1.15 jmcneill uint16_t cmd_op_mod;
1521 1.15 jmcneill uint32_t cmd_rqtn;
1522 1.15 jmcneill uint8_t cmd_reserved1[4];
1523 1.15 jmcneill } __packed __aligned(4);
1524 1.15 jmcneill
1525 1.15 jmcneill struct mcx_cmd_destroy_rqt_out {
1526 1.15 jmcneill uint8_t cmd_status;
1527 1.15 jmcneill uint8_t cmd_reserved0[3];
1528 1.15 jmcneill uint32_t cmd_syndrome;
1529 1.15 jmcneill uint8_t cmd_reserved1[8];
1530 1.15 jmcneill } __packed __aligned(4);
1531 1.15 jmcneill
1532 1.1 jmcneill struct mcx_cq_ctx {
1533 1.1 jmcneill uint32_t cq_status;
1534 1.15 jmcneill #define MCX_CQ_CTX_STATUS_SHIFT 28
1535 1.15 jmcneill #define MCX_CQ_CTX_STATUS_MASK (0xf << MCX_CQ_CTX_STATUS_SHIFT)
1536 1.15 jmcneill #define MCX_CQ_CTX_STATUS_OK 0x0
1537 1.15 jmcneill #define MCX_CQ_CTX_STATUS_OVERFLOW 0x9
1538 1.15 jmcneill #define MCX_CQ_CTX_STATUS_WRITE_FAIL 0xa
1539 1.15 jmcneill #define MCX_CQ_CTX_STATE_SHIFT 8
1540 1.15 jmcneill #define MCX_CQ_CTX_STATE_MASK (0xf << MCX_CQ_CTX_STATE_SHIFT)
1541 1.15 jmcneill #define MCX_CQ_CTX_STATE_SOLICITED 0x6
1542 1.15 jmcneill #define MCX_CQ_CTX_STATE_ARMED 0x9
1543 1.15 jmcneill #define MCX_CQ_CTX_STATE_FIRED 0xa
1544 1.1 jmcneill uint32_t cq_reserved1;
1545 1.1 jmcneill uint32_t cq_page_offset;
1546 1.1 jmcneill uint32_t cq_uar_size;
1547 1.1 jmcneill #define MCX_CQ_CTX_UAR_PAGE_MASK 0xffffff
1548 1.1 jmcneill #define MCX_CQ_CTX_LOG_CQ_SIZE_SHIFT 24
1549 1.1 jmcneill uint32_t cq_period_max_count;
1550 1.1 jmcneill #define MCX_CQ_CTX_PERIOD_SHIFT 16
1551 1.1 jmcneill uint32_t cq_eqn;
1552 1.1 jmcneill uint32_t cq_log_page_size;
1553 1.1 jmcneill #define MCX_CQ_CTX_LOG_PAGE_SIZE_SHIFT 24
1554 1.1 jmcneill uint32_t cq_reserved2;
1555 1.1 jmcneill uint32_t cq_last_notified;
1556 1.1 jmcneill uint32_t cq_last_solicit;
1557 1.1 jmcneill uint32_t cq_consumer_counter;
1558 1.1 jmcneill uint32_t cq_producer_counter;
1559 1.1 jmcneill uint8_t cq_reserved3[8];
1560 1.1 jmcneill uint64_t cq_doorbell;
1561 1.1 jmcneill } __packed __aligned(4);
1562 1.1 jmcneill
1563 1.1 jmcneill CTASSERT(sizeof(struct mcx_cq_ctx) == 64);
1564 1.1 jmcneill
1565 1.1 jmcneill struct mcx_cmd_create_cq_in {
1566 1.1 jmcneill uint16_t cmd_opcode;
1567 1.1 jmcneill uint8_t cmd_reserved0[4];
1568 1.1 jmcneill uint16_t cmd_op_mod;
1569 1.1 jmcneill uint8_t cmd_reserved1[8];
1570 1.1 jmcneill } __packed __aligned(4);
1571 1.1 jmcneill
1572 1.1 jmcneill struct mcx_cmd_create_cq_mb_in {
1573 1.1 jmcneill struct mcx_cq_ctx cmd_cq_ctx;
1574 1.1 jmcneill uint8_t cmd_reserved1[192];
1575 1.1 jmcneill } __packed __aligned(4);
1576 1.1 jmcneill
1577 1.1 jmcneill struct mcx_cmd_create_cq_out {
1578 1.1 jmcneill uint8_t cmd_status;
1579 1.1 jmcneill uint8_t cmd_reserved0[3];
1580 1.1 jmcneill uint32_t cmd_syndrome;
1581 1.1 jmcneill uint32_t cmd_cqn;
1582 1.1 jmcneill uint8_t cmd_reserved1[4];
1583 1.1 jmcneill } __packed __aligned(4);
1584 1.1 jmcneill
1585 1.1 jmcneill struct mcx_cmd_destroy_cq_in {
1586 1.1 jmcneill uint16_t cmd_opcode;
1587 1.1 jmcneill uint8_t cmd_reserved0[4];
1588 1.1 jmcneill uint16_t cmd_op_mod;
1589 1.1 jmcneill uint32_t cmd_cqn;
1590 1.1 jmcneill uint8_t cmd_reserved1[4];
1591 1.1 jmcneill } __packed __aligned(4);
1592 1.1 jmcneill
1593 1.1 jmcneill struct mcx_cmd_destroy_cq_out {
1594 1.1 jmcneill uint8_t cmd_status;
1595 1.1 jmcneill uint8_t cmd_reserved0[3];
1596 1.1 jmcneill uint32_t cmd_syndrome;
1597 1.1 jmcneill uint8_t cmd_reserved1[8];
1598 1.1 jmcneill } __packed __aligned(4);
1599 1.1 jmcneill
1600 1.15 jmcneill struct mcx_cmd_query_cq_in {
1601 1.15 jmcneill uint16_t cmd_opcode;
1602 1.15 jmcneill uint8_t cmd_reserved0[4];
1603 1.15 jmcneill uint16_t cmd_op_mod;
1604 1.15 jmcneill uint32_t cmd_cqn;
1605 1.15 jmcneill uint8_t cmd_reserved1[4];
1606 1.15 jmcneill } __packed __aligned(4);
1607 1.15 jmcneill
1608 1.15 jmcneill struct mcx_cmd_query_cq_out {
1609 1.15 jmcneill uint8_t cmd_status;
1610 1.15 jmcneill uint8_t cmd_reserved0[3];
1611 1.15 jmcneill uint32_t cmd_syndrome;
1612 1.15 jmcneill uint8_t cmd_reserved1[8];
1613 1.15 jmcneill } __packed __aligned(4);
1614 1.15 jmcneill
1615 1.1 jmcneill struct mcx_cq_entry {
1616 1.1 jmcneill uint32_t __reserved__;
1617 1.1 jmcneill uint32_t cq_lro;
1618 1.1 jmcneill uint32_t cq_lro_ack_seq_num;
1619 1.1 jmcneill uint32_t cq_rx_hash;
1620 1.1 jmcneill uint8_t cq_rx_hash_type;
1621 1.1 jmcneill uint8_t cq_ml_path;
1622 1.1 jmcneill uint16_t __reserved__;
1623 1.1 jmcneill uint32_t cq_checksum;
1624 1.1 jmcneill uint32_t __reserved__;
1625 1.1 jmcneill uint32_t cq_flags;
1626 1.15 jmcneill #define MCX_CQ_ENTRY_FLAGS_L4_OK (1 << 26)
1627 1.15 jmcneill #define MCX_CQ_ENTRY_FLAGS_L3_OK (1 << 25)
1628 1.15 jmcneill #define MCX_CQ_ENTRY_FLAGS_L2_OK (1 << 24)
1629 1.15 jmcneill #define MCX_CQ_ENTRY_FLAGS_CV (1 << 16)
1630 1.15 jmcneill #define MCX_CQ_ENTRY_FLAGS_VLAN_MASK (0xffff)
1631 1.15 jmcneill
1632 1.1 jmcneill uint32_t cq_lro_srqn;
1633 1.1 jmcneill uint32_t __reserved__[2];
1634 1.1 jmcneill uint32_t cq_byte_cnt;
1635 1.1 jmcneill uint64_t cq_timestamp;
1636 1.1 jmcneill uint8_t cq_rx_drops;
1637 1.1 jmcneill uint8_t cq_flow_tag[3];
1638 1.1 jmcneill uint16_t cq_wqe_count;
1639 1.1 jmcneill uint8_t cq_signature;
1640 1.1 jmcneill uint8_t cq_opcode_owner;
1641 1.1 jmcneill #define MCX_CQ_ENTRY_FLAG_OWNER (1 << 0)
1642 1.1 jmcneill #define MCX_CQ_ENTRY_FLAG_SE (1 << 1)
1643 1.1 jmcneill #define MCX_CQ_ENTRY_FORMAT_SHIFT 2
1644 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_SHIFT 4
1645 1.1 jmcneill
1646 1.1 jmcneill #define MCX_CQ_ENTRY_FORMAT_NO_INLINE 0
1647 1.1 jmcneill #define MCX_CQ_ENTRY_FORMAT_INLINE_32 1
1648 1.1 jmcneill #define MCX_CQ_ENTRY_FORMAT_INLINE_64 2
1649 1.1 jmcneill #define MCX_CQ_ENTRY_FORMAT_COMPRESSED 3
1650 1.1 jmcneill
1651 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_REQ 0
1652 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_SEND 2
1653 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_REQ_ERR 13
1654 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_SEND_ERR 14
1655 1.1 jmcneill #define MCX_CQ_ENTRY_OPCODE_INVALID 15
1656 1.1 jmcneill
1657 1.1 jmcneill } __packed __aligned(4);
1658 1.1 jmcneill
1659 1.1 jmcneill CTASSERT(sizeof(struct mcx_cq_entry) == 64);
1660 1.1 jmcneill
1661 1.1 jmcneill struct mcx_cq_doorbell {
1662 1.1 jmcneill uint32_t db_update_ci;
1663 1.1 jmcneill uint32_t db_arm_ci;
1664 1.1 jmcneill #define MCX_CQ_DOORBELL_ARM_CMD_SN_SHIFT 28
1665 1.1 jmcneill #define MCX_CQ_DOORBELL_ARM_CMD (1 << 24)
1666 1.1 jmcneill #define MCX_CQ_DOORBELL_ARM_CI_MASK (0xffffff)
1667 1.1 jmcneill } __packed __aligned(8);
1668 1.1 jmcneill
1669 1.1 jmcneill struct mcx_wq_ctx {
1670 1.1 jmcneill uint8_t wq_type;
1671 1.1 jmcneill #define MCX_WQ_CTX_TYPE_CYCLIC (1 << 4)
1672 1.1 jmcneill #define MCX_WQ_CTX_TYPE_SIGNATURE (1 << 3)
1673 1.1 jmcneill uint8_t wq_reserved0[5];
1674 1.1 jmcneill uint16_t wq_lwm;
1675 1.1 jmcneill uint32_t wq_pd;
1676 1.1 jmcneill uint32_t wq_uar_page;
1677 1.1 jmcneill uint64_t wq_doorbell;
1678 1.1 jmcneill uint32_t wq_hw_counter;
1679 1.1 jmcneill uint32_t wq_sw_counter;
1680 1.1 jmcneill uint16_t wq_log_stride;
1681 1.1 jmcneill uint8_t wq_log_page_sz;
1682 1.1 jmcneill uint8_t wq_log_size;
1683 1.1 jmcneill uint8_t wq_reserved1[156];
1684 1.1 jmcneill } __packed __aligned(4);
1685 1.1 jmcneill
1686 1.1 jmcneill CTASSERT(sizeof(struct mcx_wq_ctx) == 0xC0);
1687 1.1 jmcneill
1688 1.1 jmcneill struct mcx_sq_ctx {
1689 1.1 jmcneill uint32_t sq_flags;
1690 1.5 msaitoh #define MCX_SQ_CTX_RLKEY (1U << 31)
1691 1.1 jmcneill #define MCX_SQ_CTX_FRE_SHIFT (1 << 29)
1692 1.1 jmcneill #define MCX_SQ_CTX_FLUSH_IN_ERROR (1 << 28)
1693 1.1 jmcneill #define MCX_SQ_CTX_MIN_WQE_INLINE_SHIFT 24
1694 1.1 jmcneill #define MCX_SQ_CTX_STATE_SHIFT 20
1695 1.15 jmcneill #define MCX_SQ_CTX_STATE_MASK (0xf << 20)
1696 1.15 jmcneill #define MCX_SQ_CTX_STATE_RST 0
1697 1.15 jmcneill #define MCX_SQ_CTX_STATE_RDY 1
1698 1.15 jmcneill #define MCX_SQ_CTX_STATE_ERR 3
1699 1.1 jmcneill uint32_t sq_user_index;
1700 1.1 jmcneill uint32_t sq_cqn;
1701 1.1 jmcneill uint32_t sq_reserved1[5];
1702 1.1 jmcneill uint32_t sq_tis_lst_sz;
1703 1.1 jmcneill #define MCX_SQ_CTX_TIS_LST_SZ_SHIFT 16
1704 1.1 jmcneill uint32_t sq_reserved2[2];
1705 1.1 jmcneill uint32_t sq_tis_num;
1706 1.1 jmcneill struct mcx_wq_ctx sq_wq;
1707 1.1 jmcneill } __packed __aligned(4);
1708 1.1 jmcneill
1709 1.1 jmcneill struct mcx_sq_entry_seg {
1710 1.1 jmcneill uint32_t sqs_byte_count;
1711 1.1 jmcneill uint32_t sqs_lkey;
1712 1.1 jmcneill uint64_t sqs_addr;
1713 1.1 jmcneill } __packed __aligned(4);
1714 1.1 jmcneill
1715 1.1 jmcneill struct mcx_sq_entry {
1716 1.1 jmcneill /* control segment */
1717 1.1 jmcneill uint32_t sqe_opcode_index;
1718 1.1 jmcneill #define MCX_SQE_WQE_INDEX_SHIFT 8
1719 1.1 jmcneill #define MCX_SQE_WQE_OPCODE_NOP 0x00
1720 1.1 jmcneill #define MCX_SQE_WQE_OPCODE_SEND 0x0a
1721 1.1 jmcneill uint32_t sqe_ds_sq_num;
1722 1.1 jmcneill #define MCX_SQE_SQ_NUM_SHIFT 8
1723 1.1 jmcneill uint32_t sqe_signature;
1724 1.1 jmcneill #define MCX_SQE_SIGNATURE_SHIFT 24
1725 1.1 jmcneill #define MCX_SQE_SOLICITED_EVENT 0x02
1726 1.1 jmcneill #define MCX_SQE_CE_CQE_ON_ERR 0x00
1727 1.1 jmcneill #define MCX_SQE_CE_CQE_FIRST_ERR 0x04
1728 1.1 jmcneill #define MCX_SQE_CE_CQE_ALWAYS 0x08
1729 1.1 jmcneill #define MCX_SQE_CE_CQE_SOLICIT 0x0C
1730 1.1 jmcneill #define MCX_SQE_FM_NO_FENCE 0x00
1731 1.1 jmcneill #define MCX_SQE_FM_SMALL_FENCE 0x40
1732 1.1 jmcneill uint32_t sqe_mkey;
1733 1.1 jmcneill
1734 1.1 jmcneill /* ethernet segment */
1735 1.1 jmcneill uint32_t sqe_reserved1;
1736 1.1 jmcneill uint32_t sqe_mss_csum;
1737 1.1 jmcneill #define MCX_SQE_L4_CSUM (1 << 31)
1738 1.1 jmcneill #define MCX_SQE_L3_CSUM (1 << 30)
1739 1.1 jmcneill uint32_t sqe_reserved2;
1740 1.1 jmcneill uint16_t sqe_inline_header_size;
1741 1.1 jmcneill uint16_t sqe_inline_headers[9];
1742 1.1 jmcneill
1743 1.1 jmcneill /* data segment */
1744 1.1 jmcneill struct mcx_sq_entry_seg sqe_segs[1];
1745 1.1 jmcneill } __packed __aligned(64);
1746 1.1 jmcneill
1747 1.1 jmcneill CTASSERT(sizeof(struct mcx_sq_entry) == 64);
1748 1.1 jmcneill
1749 1.1 jmcneill struct mcx_cmd_create_sq_in {
1750 1.1 jmcneill uint16_t cmd_opcode;
1751 1.1 jmcneill uint8_t cmd_reserved0[4];
1752 1.1 jmcneill uint16_t cmd_op_mod;
1753 1.1 jmcneill uint8_t cmd_reserved1[8];
1754 1.1 jmcneill } __packed __aligned(4);
1755 1.1 jmcneill
1756 1.1 jmcneill struct mcx_cmd_create_sq_out {
1757 1.1 jmcneill uint8_t cmd_status;
1758 1.1 jmcneill uint8_t cmd_reserved0[3];
1759 1.1 jmcneill uint32_t cmd_syndrome;
1760 1.1 jmcneill uint32_t cmd_sqn;
1761 1.1 jmcneill uint8_t cmd_reserved1[4];
1762 1.1 jmcneill } __packed __aligned(4);
1763 1.1 jmcneill
1764 1.1 jmcneill struct mcx_cmd_modify_sq_in {
1765 1.1 jmcneill uint16_t cmd_opcode;
1766 1.1 jmcneill uint8_t cmd_reserved0[4];
1767 1.1 jmcneill uint16_t cmd_op_mod;
1768 1.1 jmcneill uint32_t cmd_sq_state;
1769 1.1 jmcneill uint8_t cmd_reserved1[4];
1770 1.1 jmcneill } __packed __aligned(4);
1771 1.1 jmcneill
1772 1.1 jmcneill struct mcx_cmd_modify_sq_mb_in {
1773 1.1 jmcneill uint32_t cmd_modify_hi;
1774 1.1 jmcneill uint32_t cmd_modify_lo;
1775 1.1 jmcneill uint8_t cmd_reserved0[8];
1776 1.1 jmcneill struct mcx_sq_ctx cmd_sq_ctx;
1777 1.1 jmcneill } __packed __aligned(4);
1778 1.1 jmcneill
1779 1.1 jmcneill struct mcx_cmd_modify_sq_out {
1780 1.1 jmcneill uint8_t cmd_status;
1781 1.1 jmcneill uint8_t cmd_reserved0[3];
1782 1.1 jmcneill uint32_t cmd_syndrome;
1783 1.1 jmcneill uint8_t cmd_reserved1[8];
1784 1.1 jmcneill } __packed __aligned(4);
1785 1.1 jmcneill
1786 1.1 jmcneill struct mcx_cmd_destroy_sq_in {
1787 1.1 jmcneill uint16_t cmd_opcode;
1788 1.1 jmcneill uint8_t cmd_reserved0[4];
1789 1.1 jmcneill uint16_t cmd_op_mod;
1790 1.1 jmcneill uint32_t cmd_sqn;
1791 1.1 jmcneill uint8_t cmd_reserved1[4];
1792 1.1 jmcneill } __packed __aligned(4);
1793 1.1 jmcneill
1794 1.1 jmcneill struct mcx_cmd_destroy_sq_out {
1795 1.1 jmcneill uint8_t cmd_status;
1796 1.1 jmcneill uint8_t cmd_reserved0[3];
1797 1.1 jmcneill uint32_t cmd_syndrome;
1798 1.1 jmcneill uint8_t cmd_reserved1[8];
1799 1.1 jmcneill } __packed __aligned(4);
1800 1.1 jmcneill
1801 1.1 jmcneill
1802 1.1 jmcneill struct mcx_rq_ctx {
1803 1.1 jmcneill uint32_t rq_flags;
1804 1.5 msaitoh #define MCX_RQ_CTX_RLKEY (1U << 31)
1805 1.1 jmcneill #define MCX_RQ_CTX_VLAN_STRIP_DIS (1 << 28)
1806 1.1 jmcneill #define MCX_RQ_CTX_MEM_RQ_TYPE_SHIFT 24
1807 1.1 jmcneill #define MCX_RQ_CTX_STATE_SHIFT 20
1808 1.15 jmcneill #define MCX_RQ_CTX_STATE_MASK (0xf << 20)
1809 1.15 jmcneill #define MCX_RQ_CTX_STATE_RST 0
1810 1.15 jmcneill #define MCX_RQ_CTX_STATE_RDY 1
1811 1.15 jmcneill #define MCX_RQ_CTX_STATE_ERR 3
1812 1.1 jmcneill #define MCX_RQ_CTX_FLUSH_IN_ERROR (1 << 18)
1813 1.1 jmcneill uint32_t rq_user_index;
1814 1.1 jmcneill uint32_t rq_cqn;
1815 1.1 jmcneill uint32_t rq_reserved1;
1816 1.1 jmcneill uint32_t rq_rmpn;
1817 1.1 jmcneill uint32_t rq_reserved2[7];
1818 1.1 jmcneill struct mcx_wq_ctx rq_wq;
1819 1.1 jmcneill } __packed __aligned(4);
1820 1.1 jmcneill
1821 1.1 jmcneill struct mcx_rq_entry {
1822 1.1 jmcneill uint32_t rqe_byte_count;
1823 1.1 jmcneill uint32_t rqe_lkey;
1824 1.1 jmcneill uint64_t rqe_addr;
1825 1.1 jmcneill } __packed __aligned(16);
1826 1.1 jmcneill
1827 1.1 jmcneill struct mcx_cmd_create_rq_in {
1828 1.1 jmcneill uint16_t cmd_opcode;
1829 1.1 jmcneill uint8_t cmd_reserved0[4];
1830 1.1 jmcneill uint16_t cmd_op_mod;
1831 1.1 jmcneill uint8_t cmd_reserved1[8];
1832 1.1 jmcneill } __packed __aligned(4);
1833 1.1 jmcneill
1834 1.1 jmcneill struct mcx_cmd_create_rq_out {
1835 1.1 jmcneill uint8_t cmd_status;
1836 1.1 jmcneill uint8_t cmd_reserved0[3];
1837 1.1 jmcneill uint32_t cmd_syndrome;
1838 1.1 jmcneill uint32_t cmd_rqn;
1839 1.1 jmcneill uint8_t cmd_reserved1[4];
1840 1.1 jmcneill } __packed __aligned(4);
1841 1.1 jmcneill
1842 1.1 jmcneill struct mcx_cmd_modify_rq_in {
1843 1.1 jmcneill uint16_t cmd_opcode;
1844 1.1 jmcneill uint8_t cmd_reserved0[4];
1845 1.1 jmcneill uint16_t cmd_op_mod;
1846 1.1 jmcneill uint32_t cmd_rq_state;
1847 1.1 jmcneill uint8_t cmd_reserved1[4];
1848 1.1 jmcneill } __packed __aligned(4);
1849 1.1 jmcneill
1850 1.1 jmcneill struct mcx_cmd_modify_rq_mb_in {
1851 1.1 jmcneill uint32_t cmd_modify_hi;
1852 1.1 jmcneill uint32_t cmd_modify_lo;
1853 1.1 jmcneill uint8_t cmd_reserved0[8];
1854 1.1 jmcneill struct mcx_rq_ctx cmd_rq_ctx;
1855 1.1 jmcneill } __packed __aligned(4);
1856 1.1 jmcneill
1857 1.1 jmcneill struct mcx_cmd_modify_rq_out {
1858 1.1 jmcneill uint8_t cmd_status;
1859 1.1 jmcneill uint8_t cmd_reserved0[3];
1860 1.1 jmcneill uint32_t cmd_syndrome;
1861 1.1 jmcneill uint8_t cmd_reserved1[8];
1862 1.1 jmcneill } __packed __aligned(4);
1863 1.1 jmcneill
1864 1.1 jmcneill struct mcx_cmd_destroy_rq_in {
1865 1.1 jmcneill uint16_t cmd_opcode;
1866 1.1 jmcneill uint8_t cmd_reserved0[4];
1867 1.1 jmcneill uint16_t cmd_op_mod;
1868 1.1 jmcneill uint32_t cmd_rqn;
1869 1.1 jmcneill uint8_t cmd_reserved1[4];
1870 1.1 jmcneill } __packed __aligned(4);
1871 1.1 jmcneill
1872 1.1 jmcneill struct mcx_cmd_destroy_rq_out {
1873 1.1 jmcneill uint8_t cmd_status;
1874 1.1 jmcneill uint8_t cmd_reserved0[3];
1875 1.1 jmcneill uint32_t cmd_syndrome;
1876 1.1 jmcneill uint8_t cmd_reserved1[8];
1877 1.1 jmcneill } __packed __aligned(4);
1878 1.1 jmcneill
1879 1.1 jmcneill struct mcx_cmd_create_flow_table_in {
1880 1.1 jmcneill uint16_t cmd_opcode;
1881 1.1 jmcneill uint8_t cmd_reserved0[4];
1882 1.1 jmcneill uint16_t cmd_op_mod;
1883 1.1 jmcneill uint8_t cmd_reserved1[8];
1884 1.1 jmcneill } __packed __aligned(4);
1885 1.1 jmcneill
1886 1.1 jmcneill struct mcx_flow_table_ctx {
1887 1.1 jmcneill uint8_t ft_miss_action;
1888 1.1 jmcneill uint8_t ft_level;
1889 1.1 jmcneill uint8_t ft_reserved0;
1890 1.1 jmcneill uint8_t ft_log_size;
1891 1.1 jmcneill uint32_t ft_table_miss_id;
1892 1.1 jmcneill uint8_t ft_reserved1[28];
1893 1.1 jmcneill } __packed __aligned(4);
1894 1.1 jmcneill
1895 1.1 jmcneill struct mcx_cmd_create_flow_table_mb_in {
1896 1.1 jmcneill uint8_t cmd_table_type;
1897 1.1 jmcneill uint8_t cmd_reserved0[7];
1898 1.1 jmcneill struct mcx_flow_table_ctx cmd_ctx;
1899 1.1 jmcneill } __packed __aligned(4);
1900 1.1 jmcneill
1901 1.1 jmcneill struct mcx_cmd_create_flow_table_out {
1902 1.1 jmcneill uint8_t cmd_status;
1903 1.1 jmcneill uint8_t cmd_reserved0[3];
1904 1.1 jmcneill uint32_t cmd_syndrome;
1905 1.1 jmcneill uint32_t cmd_table_id;
1906 1.1 jmcneill uint8_t cmd_reserved1[4];
1907 1.1 jmcneill } __packed __aligned(4);
1908 1.1 jmcneill
1909 1.1 jmcneill struct mcx_cmd_destroy_flow_table_in {
1910 1.1 jmcneill uint16_t cmd_opcode;
1911 1.1 jmcneill uint8_t cmd_reserved0[4];
1912 1.1 jmcneill uint16_t cmd_op_mod;
1913 1.1 jmcneill uint8_t cmd_reserved1[8];
1914 1.1 jmcneill } __packed __aligned(4);
1915 1.1 jmcneill
1916 1.1 jmcneill struct mcx_cmd_destroy_flow_table_mb_in {
1917 1.1 jmcneill uint8_t cmd_table_type;
1918 1.1 jmcneill uint8_t cmd_reserved0[3];
1919 1.1 jmcneill uint32_t cmd_table_id;
1920 1.1 jmcneill uint8_t cmd_reserved1[40];
1921 1.1 jmcneill } __packed __aligned(4);
1922 1.1 jmcneill
1923 1.1 jmcneill struct mcx_cmd_destroy_flow_table_out {
1924 1.1 jmcneill uint8_t cmd_status;
1925 1.1 jmcneill uint8_t cmd_reserved0[3];
1926 1.1 jmcneill uint32_t cmd_syndrome;
1927 1.1 jmcneill uint8_t cmd_reserved1[8];
1928 1.1 jmcneill } __packed __aligned(4);
1929 1.1 jmcneill
1930 1.1 jmcneill struct mcx_cmd_set_flow_table_root_in {
1931 1.1 jmcneill uint16_t cmd_opcode;
1932 1.1 jmcneill uint8_t cmd_reserved0[4];
1933 1.1 jmcneill uint16_t cmd_op_mod;
1934 1.1 jmcneill uint8_t cmd_reserved1[8];
1935 1.1 jmcneill } __packed __aligned(4);
1936 1.1 jmcneill
1937 1.1 jmcneill struct mcx_cmd_set_flow_table_root_mb_in {
1938 1.1 jmcneill uint8_t cmd_table_type;
1939 1.1 jmcneill uint8_t cmd_reserved0[3];
1940 1.1 jmcneill uint32_t cmd_table_id;
1941 1.1 jmcneill uint8_t cmd_reserved1[56];
1942 1.1 jmcneill } __packed __aligned(4);
1943 1.1 jmcneill
1944 1.1 jmcneill struct mcx_cmd_set_flow_table_root_out {
1945 1.1 jmcneill uint8_t cmd_status;
1946 1.1 jmcneill uint8_t cmd_reserved0[3];
1947 1.1 jmcneill uint32_t cmd_syndrome;
1948 1.1 jmcneill uint8_t cmd_reserved1[8];
1949 1.1 jmcneill } __packed __aligned(4);
1950 1.1 jmcneill
1951 1.1 jmcneill struct mcx_flow_match {
1952 1.1 jmcneill /* outer headers */
1953 1.1 jmcneill uint8_t mc_src_mac[6];
1954 1.1 jmcneill uint16_t mc_ethertype;
1955 1.1 jmcneill uint8_t mc_dest_mac[6];
1956 1.1 jmcneill uint16_t mc_first_vlan;
1957 1.1 jmcneill uint8_t mc_ip_proto;
1958 1.1 jmcneill uint8_t mc_ip_dscp_ecn;
1959 1.1 jmcneill uint8_t mc_vlan_flags;
1960 1.15 jmcneill #define MCX_FLOW_MATCH_IP_FRAG (1 << 5)
1961 1.1 jmcneill uint8_t mc_tcp_flags;
1962 1.1 jmcneill uint16_t mc_tcp_sport;
1963 1.1 jmcneill uint16_t mc_tcp_dport;
1964 1.1 jmcneill uint32_t mc_reserved0;
1965 1.1 jmcneill uint16_t mc_udp_sport;
1966 1.1 jmcneill uint16_t mc_udp_dport;
1967 1.1 jmcneill uint8_t mc_src_ip[16];
1968 1.1 jmcneill uint8_t mc_dest_ip[16];
1969 1.1 jmcneill
1970 1.1 jmcneill /* misc parameters */
1971 1.1 jmcneill uint8_t mc_reserved1[8];
1972 1.1 jmcneill uint16_t mc_second_vlan;
1973 1.1 jmcneill uint8_t mc_reserved2[2];
1974 1.1 jmcneill uint8_t mc_second_vlan_flags;
1975 1.1 jmcneill uint8_t mc_reserved3[15];
1976 1.1 jmcneill uint32_t mc_outer_ipv6_flow_label;
1977 1.1 jmcneill uint8_t mc_reserved4[32];
1978 1.1 jmcneill
1979 1.1 jmcneill uint8_t mc_reserved[384];
1980 1.1 jmcneill } __packed __aligned(4);
1981 1.1 jmcneill
1982 1.1 jmcneill CTASSERT(sizeof(struct mcx_flow_match) == 512);
1983 1.1 jmcneill
1984 1.1 jmcneill struct mcx_cmd_create_flow_group_in {
1985 1.1 jmcneill uint16_t cmd_opcode;
1986 1.1 jmcneill uint8_t cmd_reserved0[4];
1987 1.1 jmcneill uint16_t cmd_op_mod;
1988 1.1 jmcneill uint8_t cmd_reserved1[8];
1989 1.1 jmcneill } __packed __aligned(4);
1990 1.1 jmcneill
1991 1.1 jmcneill struct mcx_cmd_create_flow_group_mb_in {
1992 1.1 jmcneill uint8_t cmd_table_type;
1993 1.1 jmcneill uint8_t cmd_reserved0[3];
1994 1.1 jmcneill uint32_t cmd_table_id;
1995 1.1 jmcneill uint8_t cmd_reserved1[4];
1996 1.1 jmcneill uint32_t cmd_start_flow_index;
1997 1.1 jmcneill uint8_t cmd_reserved2[4];
1998 1.1 jmcneill uint32_t cmd_end_flow_index;
1999 1.1 jmcneill uint8_t cmd_reserved3[23];
2000 1.1 jmcneill uint8_t cmd_match_criteria_enable;
2001 1.1 jmcneill #define MCX_CREATE_FLOW_GROUP_CRIT_OUTER (1 << 0)
2002 1.1 jmcneill #define MCX_CREATE_FLOW_GROUP_CRIT_MISC (1 << 1)
2003 1.1 jmcneill #define MCX_CREATE_FLOW_GROUP_CRIT_INNER (1 << 2)
2004 1.1 jmcneill struct mcx_flow_match cmd_match_criteria;
2005 1.1 jmcneill uint8_t cmd_reserved4[448];
2006 1.1 jmcneill } __packed __aligned(4);
2007 1.1 jmcneill
2008 1.1 jmcneill struct mcx_cmd_create_flow_group_out {
2009 1.1 jmcneill uint8_t cmd_status;
2010 1.1 jmcneill uint8_t cmd_reserved0[3];
2011 1.1 jmcneill uint32_t cmd_syndrome;
2012 1.1 jmcneill uint32_t cmd_group_id;
2013 1.1 jmcneill uint8_t cmd_reserved1[4];
2014 1.1 jmcneill } __packed __aligned(4);
2015 1.1 jmcneill
2016 1.1 jmcneill struct mcx_flow_ctx {
2017 1.1 jmcneill uint8_t fc_reserved0[4];
2018 1.1 jmcneill uint32_t fc_group_id;
2019 1.1 jmcneill uint32_t fc_flow_tag;
2020 1.1 jmcneill uint32_t fc_action;
2021 1.1 jmcneill #define MCX_FLOW_CONTEXT_ACTION_ALLOW (1 << 0)
2022 1.1 jmcneill #define MCX_FLOW_CONTEXT_ACTION_DROP (1 << 1)
2023 1.1 jmcneill #define MCX_FLOW_CONTEXT_ACTION_FORWARD (1 << 2)
2024 1.1 jmcneill #define MCX_FLOW_CONTEXT_ACTION_COUNT (1 << 3)
2025 1.1 jmcneill uint32_t fc_dest_list_size;
2026 1.1 jmcneill uint32_t fc_counter_list_size;
2027 1.1 jmcneill uint8_t fc_reserved1[40];
2028 1.1 jmcneill struct mcx_flow_match fc_match_value;
2029 1.1 jmcneill uint8_t fc_reserved2[192];
2030 1.1 jmcneill } __packed __aligned(4);
2031 1.1 jmcneill
2032 1.1 jmcneill #define MCX_FLOW_CONTEXT_DEST_TYPE_TABLE (1 << 24)
2033 1.1 jmcneill #define MCX_FLOW_CONTEXT_DEST_TYPE_TIR (2 << 24)
2034 1.1 jmcneill
2035 1.1 jmcneill struct mcx_cmd_destroy_flow_group_in {
2036 1.1 jmcneill uint16_t cmd_opcode;
2037 1.1 jmcneill uint8_t cmd_reserved0[4];
2038 1.1 jmcneill uint16_t cmd_op_mod;
2039 1.1 jmcneill uint8_t cmd_reserved1[8];
2040 1.1 jmcneill } __packed __aligned(4);
2041 1.1 jmcneill
2042 1.1 jmcneill struct mcx_cmd_destroy_flow_group_mb_in {
2043 1.1 jmcneill uint8_t cmd_table_type;
2044 1.1 jmcneill uint8_t cmd_reserved0[3];
2045 1.1 jmcneill uint32_t cmd_table_id;
2046 1.1 jmcneill uint32_t cmd_group_id;
2047 1.1 jmcneill uint8_t cmd_reserved1[36];
2048 1.1 jmcneill } __packed __aligned(4);
2049 1.1 jmcneill
2050 1.1 jmcneill struct mcx_cmd_destroy_flow_group_out {
2051 1.1 jmcneill uint8_t cmd_status;
2052 1.1 jmcneill uint8_t cmd_reserved0[3];
2053 1.1 jmcneill uint32_t cmd_syndrome;
2054 1.1 jmcneill uint8_t cmd_reserved1[8];
2055 1.1 jmcneill } __packed __aligned(4);
2056 1.1 jmcneill
2057 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_in {
2058 1.1 jmcneill uint16_t cmd_opcode;
2059 1.1 jmcneill uint8_t cmd_reserved0[4];
2060 1.1 jmcneill uint16_t cmd_op_mod;
2061 1.1 jmcneill uint8_t cmd_reserved1[8];
2062 1.1 jmcneill } __packed __aligned(4);
2063 1.1 jmcneill
2064 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_mb_in {
2065 1.1 jmcneill uint8_t cmd_table_type;
2066 1.1 jmcneill uint8_t cmd_reserved0[3];
2067 1.1 jmcneill uint32_t cmd_table_id;
2068 1.1 jmcneill uint32_t cmd_modify_enable_mask;
2069 1.1 jmcneill uint8_t cmd_reserved1[4];
2070 1.1 jmcneill uint32_t cmd_flow_index;
2071 1.1 jmcneill uint8_t cmd_reserved2[28];
2072 1.1 jmcneill struct mcx_flow_ctx cmd_flow_ctx;
2073 1.1 jmcneill } __packed __aligned(4);
2074 1.1 jmcneill
2075 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_out {
2076 1.1 jmcneill uint8_t cmd_status;
2077 1.1 jmcneill uint8_t cmd_reserved0[3];
2078 1.1 jmcneill uint32_t cmd_syndrome;
2079 1.1 jmcneill uint8_t cmd_reserved1[8];
2080 1.1 jmcneill } __packed __aligned(4);
2081 1.1 jmcneill
2082 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_in {
2083 1.1 jmcneill uint16_t cmd_opcode;
2084 1.1 jmcneill uint8_t cmd_reserved0[4];
2085 1.1 jmcneill uint16_t cmd_op_mod;
2086 1.1 jmcneill uint8_t cmd_reserved1[8];
2087 1.1 jmcneill } __packed __aligned(4);
2088 1.1 jmcneill
2089 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_mb_in {
2090 1.1 jmcneill uint8_t cmd_table_type;
2091 1.1 jmcneill uint8_t cmd_reserved0[3];
2092 1.1 jmcneill uint32_t cmd_table_id;
2093 1.1 jmcneill uint8_t cmd_reserved1[8];
2094 1.1 jmcneill uint32_t cmd_flow_index;
2095 1.1 jmcneill uint8_t cmd_reserved2[28];
2096 1.1 jmcneill } __packed __aligned(4);
2097 1.1 jmcneill
2098 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_out {
2099 1.1 jmcneill uint8_t cmd_status;
2100 1.1 jmcneill uint8_t cmd_reserved0[3];
2101 1.1 jmcneill uint32_t cmd_syndrome;
2102 1.1 jmcneill uint8_t cmd_reserved1[8];
2103 1.1 jmcneill } __packed __aligned(4);
2104 1.1 jmcneill
2105 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_mb_out {
2106 1.1 jmcneill uint8_t cmd_reserved0[48];
2107 1.1 jmcneill struct mcx_flow_ctx cmd_flow_ctx;
2108 1.1 jmcneill } __packed __aligned(4);
2109 1.1 jmcneill
2110 1.1 jmcneill struct mcx_cmd_delete_flow_table_entry_in {
2111 1.1 jmcneill uint16_t cmd_opcode;
2112 1.1 jmcneill uint8_t cmd_reserved0[4];
2113 1.1 jmcneill uint16_t cmd_op_mod;
2114 1.1 jmcneill uint8_t cmd_reserved1[8];
2115 1.1 jmcneill } __packed __aligned(4);
2116 1.1 jmcneill
2117 1.1 jmcneill struct mcx_cmd_delete_flow_table_entry_mb_in {
2118 1.1 jmcneill uint8_t cmd_table_type;
2119 1.1 jmcneill uint8_t cmd_reserved0[3];
2120 1.1 jmcneill uint32_t cmd_table_id;
2121 1.1 jmcneill uint8_t cmd_reserved1[8];
2122 1.1 jmcneill uint32_t cmd_flow_index;
2123 1.1 jmcneill uint8_t cmd_reserved2[28];
2124 1.1 jmcneill } __packed __aligned(4);
2125 1.1 jmcneill
2126 1.1 jmcneill struct mcx_cmd_delete_flow_table_entry_out {
2127 1.1 jmcneill uint8_t cmd_status;
2128 1.1 jmcneill uint8_t cmd_reserved0[3];
2129 1.1 jmcneill uint32_t cmd_syndrome;
2130 1.1 jmcneill uint8_t cmd_reserved1[8];
2131 1.1 jmcneill } __packed __aligned(4);
2132 1.1 jmcneill
2133 1.1 jmcneill struct mcx_cmd_query_flow_group_in {
2134 1.1 jmcneill uint16_t cmd_opcode;
2135 1.1 jmcneill uint8_t cmd_reserved0[4];
2136 1.1 jmcneill uint16_t cmd_op_mod;
2137 1.1 jmcneill uint8_t cmd_reserved1[8];
2138 1.1 jmcneill } __packed __aligned(4);
2139 1.1 jmcneill
2140 1.1 jmcneill struct mcx_cmd_query_flow_group_mb_in {
2141 1.1 jmcneill uint8_t cmd_table_type;
2142 1.1 jmcneill uint8_t cmd_reserved0[3];
2143 1.1 jmcneill uint32_t cmd_table_id;
2144 1.1 jmcneill uint32_t cmd_group_id;
2145 1.1 jmcneill uint8_t cmd_reserved1[36];
2146 1.1 jmcneill } __packed __aligned(4);
2147 1.1 jmcneill
2148 1.1 jmcneill struct mcx_cmd_query_flow_group_out {
2149 1.1 jmcneill uint8_t cmd_status;
2150 1.1 jmcneill uint8_t cmd_reserved0[3];
2151 1.1 jmcneill uint32_t cmd_syndrome;
2152 1.1 jmcneill uint8_t cmd_reserved1[8];
2153 1.1 jmcneill } __packed __aligned(4);
2154 1.1 jmcneill
2155 1.1 jmcneill struct mcx_cmd_query_flow_group_mb_out {
2156 1.1 jmcneill uint8_t cmd_reserved0[12];
2157 1.1 jmcneill uint32_t cmd_start_flow_index;
2158 1.1 jmcneill uint8_t cmd_reserved1[4];
2159 1.1 jmcneill uint32_t cmd_end_flow_index;
2160 1.1 jmcneill uint8_t cmd_reserved2[20];
2161 1.1 jmcneill uint32_t cmd_match_criteria_enable;
2162 1.1 jmcneill uint8_t cmd_match_criteria[512];
2163 1.1 jmcneill uint8_t cmd_reserved4[448];
2164 1.1 jmcneill } __packed __aligned(4);
2165 1.1 jmcneill
2166 1.1 jmcneill struct mcx_cmd_query_flow_table_in {
2167 1.1 jmcneill uint16_t cmd_opcode;
2168 1.1 jmcneill uint8_t cmd_reserved0[4];
2169 1.1 jmcneill uint16_t cmd_op_mod;
2170 1.1 jmcneill uint8_t cmd_reserved1[8];
2171 1.1 jmcneill } __packed __aligned(4);
2172 1.1 jmcneill
2173 1.1 jmcneill struct mcx_cmd_query_flow_table_mb_in {
2174 1.1 jmcneill uint8_t cmd_table_type;
2175 1.1 jmcneill uint8_t cmd_reserved0[3];
2176 1.1 jmcneill uint32_t cmd_table_id;
2177 1.1 jmcneill uint8_t cmd_reserved1[40];
2178 1.1 jmcneill } __packed __aligned(4);
2179 1.1 jmcneill
2180 1.1 jmcneill struct mcx_cmd_query_flow_table_out {
2181 1.1 jmcneill uint8_t cmd_status;
2182 1.1 jmcneill uint8_t cmd_reserved0[3];
2183 1.1 jmcneill uint32_t cmd_syndrome;
2184 1.1 jmcneill uint8_t cmd_reserved1[8];
2185 1.1 jmcneill } __packed __aligned(4);
2186 1.1 jmcneill
2187 1.1 jmcneill struct mcx_cmd_query_flow_table_mb_out {
2188 1.1 jmcneill uint8_t cmd_reserved0[4];
2189 1.1 jmcneill struct mcx_flow_table_ctx cmd_ctx;
2190 1.1 jmcneill } __packed __aligned(4);
2191 1.1 jmcneill
2192 1.1 jmcneill struct mcx_cmd_alloc_flow_counter_in {
2193 1.1 jmcneill uint16_t cmd_opcode;
2194 1.1 jmcneill uint8_t cmd_reserved0[4];
2195 1.1 jmcneill uint16_t cmd_op_mod;
2196 1.1 jmcneill uint8_t cmd_reserved1[8];
2197 1.1 jmcneill } __packed __aligned(4);
2198 1.1 jmcneill
2199 1.1 jmcneill struct mcx_cmd_query_rq_in {
2200 1.1 jmcneill uint16_t cmd_opcode;
2201 1.1 jmcneill uint8_t cmd_reserved0[4];
2202 1.1 jmcneill uint16_t cmd_op_mod;
2203 1.1 jmcneill uint32_t cmd_rqn;
2204 1.1 jmcneill uint8_t cmd_reserved1[4];
2205 1.1 jmcneill } __packed __aligned(4);
2206 1.1 jmcneill
2207 1.1 jmcneill struct mcx_cmd_query_rq_out {
2208 1.1 jmcneill uint8_t cmd_status;
2209 1.1 jmcneill uint8_t cmd_reserved0[3];
2210 1.1 jmcneill uint32_t cmd_syndrome;
2211 1.1 jmcneill uint8_t cmd_reserved1[8];
2212 1.1 jmcneill } __packed __aligned(4);
2213 1.1 jmcneill
2214 1.1 jmcneill struct mcx_cmd_query_rq_mb_out {
2215 1.1 jmcneill uint8_t cmd_reserved0[16];
2216 1.1 jmcneill struct mcx_rq_ctx cmd_ctx;
2217 1.1 jmcneill };
2218 1.1 jmcneill
2219 1.1 jmcneill struct mcx_cmd_query_sq_in {
2220 1.1 jmcneill uint16_t cmd_opcode;
2221 1.1 jmcneill uint8_t cmd_reserved0[4];
2222 1.1 jmcneill uint16_t cmd_op_mod;
2223 1.1 jmcneill uint32_t cmd_sqn;
2224 1.1 jmcneill uint8_t cmd_reserved1[4];
2225 1.1 jmcneill } __packed __aligned(4);
2226 1.1 jmcneill
2227 1.1 jmcneill struct mcx_cmd_query_sq_out {
2228 1.1 jmcneill uint8_t cmd_status;
2229 1.1 jmcneill uint8_t cmd_reserved0[3];
2230 1.1 jmcneill uint32_t cmd_syndrome;
2231 1.1 jmcneill uint8_t cmd_reserved1[8];
2232 1.1 jmcneill } __packed __aligned(4);
2233 1.1 jmcneill
2234 1.1 jmcneill struct mcx_cmd_query_sq_mb_out {
2235 1.1 jmcneill uint8_t cmd_reserved0[16];
2236 1.1 jmcneill struct mcx_sq_ctx cmd_ctx;
2237 1.1 jmcneill };
2238 1.1 jmcneill
2239 1.1 jmcneill struct mcx_cmd_alloc_flow_counter_out {
2240 1.1 jmcneill uint8_t cmd_status;
2241 1.1 jmcneill uint8_t cmd_reserved0[3];
2242 1.1 jmcneill uint32_t cmd_syndrome;
2243 1.1 jmcneill uint8_t cmd_reserved1[2];
2244 1.1 jmcneill uint16_t cmd_flow_counter_id;
2245 1.1 jmcneill uint8_t cmd_reserved2[4];
2246 1.1 jmcneill } __packed __aligned(4);
2247 1.1 jmcneill
2248 1.1 jmcneill struct mcx_wq_doorbell {
2249 1.1 jmcneill uint32_t db_recv_counter;
2250 1.1 jmcneill uint32_t db_send_counter;
2251 1.1 jmcneill } __packed __aligned(8);
2252 1.1 jmcneill
2253 1.1 jmcneill struct mcx_dmamem {
2254 1.1 jmcneill bus_dmamap_t mxm_map;
2255 1.1 jmcneill bus_dma_segment_t mxm_seg;
2256 1.1 jmcneill int mxm_nsegs;
2257 1.1 jmcneill size_t mxm_size;
2258 1.1 jmcneill void *mxm_kva;
2259 1.1 jmcneill };
2260 1.1 jmcneill #define MCX_DMA_MAP(_mxm) ((_mxm)->mxm_map)
2261 1.1 jmcneill #define MCX_DMA_DVA(_mxm) ((_mxm)->mxm_map->dm_segs[0].ds_addr)
2262 1.1 jmcneill #define MCX_DMA_KVA(_mxm) ((void *)(_mxm)->mxm_kva)
2263 1.15 jmcneill #define MCX_DMA_OFF(_mxm, _off) ((void *)((char *)(_mxm)->mxm_kva + (_off)))
2264 1.1 jmcneill #define MCX_DMA_LEN(_mxm) ((_mxm)->mxm_size)
2265 1.1 jmcneill
2266 1.1 jmcneill struct mcx_hwmem {
2267 1.1 jmcneill bus_dmamap_t mhm_map;
2268 1.1 jmcneill bus_dma_segment_t *mhm_segs;
2269 1.1 jmcneill unsigned int mhm_seg_count;
2270 1.1 jmcneill unsigned int mhm_npages;
2271 1.1 jmcneill };
2272 1.1 jmcneill
2273 1.1 jmcneill struct mcx_slot {
2274 1.1 jmcneill bus_dmamap_t ms_map;
2275 1.1 jmcneill struct mbuf *ms_m;
2276 1.1 jmcneill };
2277 1.1 jmcneill
2278 1.15 jmcneill struct mcx_eq {
2279 1.15 jmcneill int eq_n;
2280 1.15 jmcneill uint32_t eq_cons;
2281 1.15 jmcneill struct mcx_dmamem eq_mem;
2282 1.15 jmcneill };
2283 1.15 jmcneill
2284 1.1 jmcneill struct mcx_cq {
2285 1.1 jmcneill int cq_n;
2286 1.1 jmcneill struct mcx_dmamem cq_mem;
2287 1.15 jmcneill bus_addr_t cq_doorbell;
2288 1.1 jmcneill uint32_t cq_cons;
2289 1.1 jmcneill uint32_t cq_count;
2290 1.1 jmcneill };
2291 1.1 jmcneill
2292 1.1 jmcneill struct mcx_calibration {
2293 1.1 jmcneill uint64_t c_timestamp; /* previous mcx chip time */
2294 1.1 jmcneill uint64_t c_uptime; /* previous kernel nanouptime */
2295 1.1 jmcneill uint64_t c_tbase; /* mcx chip time */
2296 1.1 jmcneill uint64_t c_ubase; /* kernel nanouptime */
2297 1.15 jmcneill uint64_t c_ratio;
2298 1.1 jmcneill };
2299 1.1 jmcneill
2300 1.1 jmcneill #define MCX_CALIBRATE_FIRST 2
2301 1.15 jmcneill #define MCX_CALIBRATE_NORMAL 32
2302 1.1 jmcneill
2303 1.1 jmcneill struct mcx_rxring {
2304 1.1 jmcneill u_int rxr_total;
2305 1.1 jmcneill u_int rxr_inuse;
2306 1.1 jmcneill };
2307 1.1 jmcneill
2308 1.1 jmcneill MBUFQ_HEAD(mcx_mbufq);
2309 1.1 jmcneill
2310 1.15 jmcneill struct mcx_rx {
2311 1.15 jmcneill struct mcx_softc *rx_softc;
2312 1.15 jmcneill
2313 1.15 jmcneill int rx_rqn;
2314 1.15 jmcneill struct mcx_dmamem rx_rq_mem;
2315 1.15 jmcneill struct mcx_slot *rx_slots;
2316 1.15 jmcneill bus_addr_t rx_doorbell;
2317 1.15 jmcneill
2318 1.15 jmcneill uint32_t rx_prod;
2319 1.15 jmcneill callout_t rx_refill;
2320 1.15 jmcneill struct mcx_rxring rx_rxr;
2321 1.15 jmcneill } __aligned(64);
2322 1.15 jmcneill
2323 1.15 jmcneill struct mcx_tx {
2324 1.15 jmcneill struct mcx_softc *tx_softc;
2325 1.16 jmcneill kmutex_t tx_lock;
2326 1.16 jmcneill pcq_t *tx_pcq;
2327 1.16 jmcneill void *tx_softint;
2328 1.15 jmcneill
2329 1.15 jmcneill int tx_uar;
2330 1.15 jmcneill int tx_sqn;
2331 1.15 jmcneill struct mcx_dmamem tx_sq_mem;
2332 1.15 jmcneill struct mcx_slot *tx_slots;
2333 1.15 jmcneill bus_addr_t tx_doorbell;
2334 1.15 jmcneill int tx_bf_offset;
2335 1.15 jmcneill
2336 1.15 jmcneill uint32_t tx_cons;
2337 1.15 jmcneill uint32_t tx_prod;
2338 1.15 jmcneill } __aligned(64);
2339 1.15 jmcneill
2340 1.15 jmcneill struct mcx_queues {
2341 1.15 jmcneill void *q_ihc;
2342 1.15 jmcneill struct mcx_softc *q_sc;
2343 1.15 jmcneill int q_uar;
2344 1.15 jmcneill int q_index;
2345 1.15 jmcneill struct mcx_rx q_rx;
2346 1.15 jmcneill struct mcx_tx q_tx;
2347 1.15 jmcneill struct mcx_cq q_cq;
2348 1.15 jmcneill struct mcx_eq q_eq;
2349 1.15 jmcneill #if NKSTAT > 0
2350 1.15 jmcneill struct kstat *q_kstat;
2351 1.15 jmcneill #endif
2352 1.15 jmcneill };
2353 1.15 jmcneill
2354 1.15 jmcneill struct mcx_flow_group {
2355 1.15 jmcneill int g_id;
2356 1.15 jmcneill int g_table;
2357 1.15 jmcneill int g_start;
2358 1.15 jmcneill int g_size;
2359 1.15 jmcneill };
2360 1.15 jmcneill
2361 1.15 jmcneill #define MCX_FLOW_GROUP_PROMISC 0
2362 1.15 jmcneill #define MCX_FLOW_GROUP_ALLMULTI 1
2363 1.15 jmcneill #define MCX_FLOW_GROUP_MAC 2
2364 1.15 jmcneill #define MCX_FLOW_GROUP_RSS_L4 3
2365 1.15 jmcneill #define MCX_FLOW_GROUP_RSS_L3 4
2366 1.15 jmcneill #define MCX_FLOW_GROUP_RSS_NONE 5
2367 1.15 jmcneill #define MCX_NUM_FLOW_GROUPS 6
2368 1.15 jmcneill
2369 1.15 jmcneill #define MCX_HASH_SEL_L3 MCX_TIR_CTX_HASH_SEL_SRC_IP | \
2370 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_DST_IP
2371 1.15 jmcneill #define MCX_HASH_SEL_L4 MCX_HASH_SEL_L3 | MCX_TIR_CTX_HASH_SEL_SPORT | \
2372 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_DPORT
2373 1.15 jmcneill
2374 1.15 jmcneill #define MCX_RSS_HASH_SEL_V4_TCP MCX_HASH_SEL_L4 | MCX_TIR_CTX_HASH_SEL_TCP |\
2375 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_IPV4
2376 1.15 jmcneill #define MCX_RSS_HASH_SEL_V6_TCP MCX_HASH_SEL_L4 | MCX_TIR_CTX_HASH_SEL_TCP | \
2377 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_IPV6
2378 1.15 jmcneill #define MCX_RSS_HASH_SEL_V4_UDP MCX_HASH_SEL_L4 | MCX_TIR_CTX_HASH_SEL_UDP | \
2379 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_IPV4
2380 1.15 jmcneill #define MCX_RSS_HASH_SEL_V6_UDP MCX_HASH_SEL_L4 | MCX_TIR_CTX_HASH_SEL_UDP | \
2381 1.15 jmcneill MCX_TIR_CTX_HASH_SEL_IPV6
2382 1.15 jmcneill #define MCX_RSS_HASH_SEL_V4 MCX_HASH_SEL_L3 | MCX_TIR_CTX_HASH_SEL_IPV4
2383 1.15 jmcneill #define MCX_RSS_HASH_SEL_V6 MCX_HASH_SEL_L3 | MCX_TIR_CTX_HASH_SEL_IPV6
2384 1.15 jmcneill
2385 1.15 jmcneill /*
2386 1.15 jmcneill * There are a few different pieces involved in configuring RSS.
2387 1.15 jmcneill * A Receive Queue Table (RQT) is the indirection table that maps packets to
2388 1.15 jmcneill * different rx queues based on a hash value. We only create one, because
2389 1.15 jmcneill * we want to scatter any traffic we can apply RSS to across all our rx
2390 1.15 jmcneill * queues. Anything else will only be delivered to the first rx queue,
2391 1.15 jmcneill * which doesn't require an RQT.
2392 1.15 jmcneill *
2393 1.15 jmcneill * A Transport Interface Receive (TIR) delivers packets to either a single rx
2394 1.15 jmcneill * queue or an RQT, and in the latter case, specifies the set of fields
2395 1.15 jmcneill * hashed, the hash function, and the hash key. We need one of these for each
2396 1.15 jmcneill * type of RSS traffic - v4 TCP, v6 TCP, v4 UDP, v6 UDP, other v4, other v6,
2397 1.15 jmcneill * and one for non-RSS traffic.
2398 1.15 jmcneill *
2399 1.15 jmcneill * Flow tables hold flow table entries in sequence. The first entry that
2400 1.15 jmcneill * matches a packet is applied, sending the packet to either another flow
2401 1.15 jmcneill * table or a TIR. We use one flow table to select packets based on
2402 1.15 jmcneill * destination MAC address, and a second to apply RSS. The entries in the
2403 1.15 jmcneill * first table send matching packets to the second, and the entries in the
2404 1.15 jmcneill * RSS table send packets to RSS TIRs if possible, or the non-RSS TIR.
2405 1.15 jmcneill *
2406 1.15 jmcneill * The flow table entry that delivers packets to an RSS TIR must include match
2407 1.15 jmcneill * criteria that ensure packets delivered to the TIR include all the fields
2408 1.15 jmcneill * that the TIR hashes on - so for a v4 TCP TIR, the flow table entry must
2409 1.15 jmcneill * only accept v4 TCP packets. Accordingly, we need flow table entries for
2410 1.15 jmcneill * each TIR.
2411 1.15 jmcneill *
2412 1.15 jmcneill * All of this is a lot more flexible than we need, and we can describe most
2413 1.15 jmcneill * of the stuff we need with a simple array.
2414 1.15 jmcneill *
2415 1.15 jmcneill * An RSS config creates a TIR with hashing enabled on a set of fields,
2416 1.15 jmcneill * pointing to either the first rx queue or the RQT containing all the rx
2417 1.15 jmcneill * queues, and a flow table entry that matches on an ether type and
2418 1.15 jmcneill * optionally an ip proto, that delivers packets to the TIR.
2419 1.15 jmcneill */
2420 1.15 jmcneill static struct mcx_rss_rule {
2421 1.15 jmcneill int hash_sel;
2422 1.15 jmcneill int flow_group;
2423 1.15 jmcneill int ethertype;
2424 1.15 jmcneill int ip_proto;
2425 1.15 jmcneill } mcx_rss_config[] = {
2426 1.15 jmcneill /* udp and tcp for v4/v6 */
2427 1.15 jmcneill { MCX_RSS_HASH_SEL_V4_TCP, MCX_FLOW_GROUP_RSS_L4,
2428 1.15 jmcneill ETHERTYPE_IP, IPPROTO_TCP },
2429 1.15 jmcneill { MCX_RSS_HASH_SEL_V6_TCP, MCX_FLOW_GROUP_RSS_L4,
2430 1.15 jmcneill ETHERTYPE_IPV6, IPPROTO_TCP },
2431 1.15 jmcneill { MCX_RSS_HASH_SEL_V4_UDP, MCX_FLOW_GROUP_RSS_L4,
2432 1.15 jmcneill ETHERTYPE_IP, IPPROTO_UDP },
2433 1.15 jmcneill { MCX_RSS_HASH_SEL_V6_UDP, MCX_FLOW_GROUP_RSS_L4,
2434 1.15 jmcneill ETHERTYPE_IPV6, IPPROTO_UDP },
2435 1.15 jmcneill
2436 1.15 jmcneill /* other v4/v6 */
2437 1.15 jmcneill { MCX_RSS_HASH_SEL_V4, MCX_FLOW_GROUP_RSS_L3,
2438 1.15 jmcneill ETHERTYPE_IP, 0 },
2439 1.15 jmcneill { MCX_RSS_HASH_SEL_V6, MCX_FLOW_GROUP_RSS_L3,
2440 1.15 jmcneill ETHERTYPE_IPV6, 0 },
2441 1.15 jmcneill
2442 1.15 jmcneill /* non v4/v6 */
2443 1.15 jmcneill { 0, MCX_FLOW_GROUP_RSS_NONE, 0, 0 }
2444 1.15 jmcneill };
2445 1.15 jmcneill
2446 1.1 jmcneill struct mcx_softc {
2447 1.1 jmcneill device_t sc_dev;
2448 1.1 jmcneill struct ethercom sc_ec;
2449 1.1 jmcneill struct ifmedia sc_media;
2450 1.1 jmcneill uint64_t sc_media_status;
2451 1.1 jmcneill uint64_t sc_media_active;
2452 1.12 thorpej kmutex_t sc_media_mutex;
2453 1.1 jmcneill
2454 1.1 jmcneill pci_chipset_tag_t sc_pc;
2455 1.1 jmcneill pci_intr_handle_t *sc_intrs;
2456 1.15 jmcneill void *sc_ihc;
2457 1.1 jmcneill pcitag_t sc_tag;
2458 1.1 jmcneill
2459 1.1 jmcneill bus_dma_tag_t sc_dmat;
2460 1.1 jmcneill bus_space_tag_t sc_memt;
2461 1.1 jmcneill bus_space_handle_t sc_memh;
2462 1.1 jmcneill bus_size_t sc_mems;
2463 1.1 jmcneill
2464 1.1 jmcneill struct mcx_dmamem sc_cmdq_mem;
2465 1.1 jmcneill unsigned int sc_cmdq_mask;
2466 1.1 jmcneill unsigned int sc_cmdq_size;
2467 1.1 jmcneill
2468 1.1 jmcneill unsigned int sc_cmdq_token;
2469 1.1 jmcneill
2470 1.1 jmcneill struct mcx_hwmem sc_boot_pages;
2471 1.1 jmcneill struct mcx_hwmem sc_init_pages;
2472 1.1 jmcneill struct mcx_hwmem sc_regular_pages;
2473 1.1 jmcneill
2474 1.1 jmcneill int sc_uar;
2475 1.1 jmcneill int sc_pd;
2476 1.1 jmcneill int sc_tdomain;
2477 1.1 jmcneill uint32_t sc_lkey;
2478 1.15 jmcneill int sc_tis;
2479 1.15 jmcneill int sc_tir[__arraycount(mcx_rss_config)];
2480 1.15 jmcneill int sc_rqt;
2481 1.1 jmcneill
2482 1.1 jmcneill struct mcx_dmamem sc_doorbell_mem;
2483 1.1 jmcneill
2484 1.15 jmcneill struct mcx_eq sc_admin_eq;
2485 1.15 jmcneill struct mcx_eq sc_queue_eq;
2486 1.15 jmcneill
2487 1.1 jmcneill int sc_hardmtu;
2488 1.15 jmcneill int sc_rxbufsz;
2489 1.15 jmcneill
2490 1.15 jmcneill int sc_bf_size;
2491 1.15 jmcneill int sc_max_rqt_size;
2492 1.1 jmcneill
2493 1.1 jmcneill struct workqueue *sc_workq;
2494 1.1 jmcneill struct work sc_port_change;
2495 1.1 jmcneill
2496 1.15 jmcneill int sc_mac_flow_table_id;
2497 1.15 jmcneill int sc_rss_flow_table_id;
2498 1.15 jmcneill struct mcx_flow_group sc_flow_group[MCX_NUM_FLOW_GROUPS];
2499 1.1 jmcneill int sc_promisc_flow_enabled;
2500 1.1 jmcneill int sc_allmulti_flow_enabled;
2501 1.1 jmcneill int sc_mcast_flow_base;
2502 1.1 jmcneill int sc_extra_mcast;
2503 1.1 jmcneill uint8_t sc_mcast_flows[MCX_NUM_MCAST_FLOWS][ETHER_ADDR_LEN];
2504 1.1 jmcneill
2505 1.1 jmcneill struct mcx_calibration sc_calibration[2];
2506 1.1 jmcneill unsigned int sc_calibration_gen;
2507 1.1 jmcneill callout_t sc_calibrate;
2508 1.15 jmcneill uint32_t sc_mhz;
2509 1.15 jmcneill uint32_t sc_khz;
2510 1.1 jmcneill
2511 1.15 jmcneill struct mcx_queues *sc_queues;
2512 1.15 jmcneill unsigned int sc_nqueues;
2513 1.1 jmcneill
2514 1.15 jmcneill int sc_mcam_reg;
2515 1.1 jmcneill
2516 1.15 jmcneill #if NKSTAT > 0
2517 1.15 jmcneill struct kstat *sc_kstat_ieee8023;
2518 1.15 jmcneill struct kstat *sc_kstat_rfc2863;
2519 1.15 jmcneill struct kstat *sc_kstat_rfc2819;
2520 1.15 jmcneill struct kstat *sc_kstat_rfc3635;
2521 1.15 jmcneill unsigned int sc_kstat_mtmp_count;
2522 1.15 jmcneill struct kstat **sc_kstat_mtmp;
2523 1.15 jmcneill #endif
2524 1.1 jmcneill
2525 1.15 jmcneill struct timecounter sc_timecounter;
2526 1.1 jmcneill };
2527 1.1 jmcneill #define DEVNAME(_sc) device_xname((_sc)->sc_dev)
2528 1.1 jmcneill
2529 1.1 jmcneill static int mcx_match(device_t, cfdata_t, void *);
2530 1.1 jmcneill static void mcx_attach(device_t, device_t, void *);
2531 1.1 jmcneill
2532 1.15 jmcneill static void * mcx_establish_intr(struct mcx_softc *, int, kcpuset_t *,
2533 1.15 jmcneill int (*)(void *), void *, const char *);
2534 1.15 jmcneill
2535 1.1 jmcneill static void mcx_rxr_init(struct mcx_rxring *, u_int, u_int);
2536 1.1 jmcneill static u_int mcx_rxr_get(struct mcx_rxring *, u_int);
2537 1.1 jmcneill static void mcx_rxr_put(struct mcx_rxring *, u_int);
2538 1.1 jmcneill static u_int mcx_rxr_inuse(struct mcx_rxring *);
2539 1.1 jmcneill
2540 1.15 jmcneill #if NKSTAT > 0
2541 1.15 jmcneill static void mcx_kstat_attach(struct mcx_softc *);
2542 1.15 jmcneill #endif
2543 1.15 jmcneill
2544 1.15 jmcneill static void mcx_timecounter_attach(struct mcx_softc *);
2545 1.15 jmcneill
2546 1.1 jmcneill static int mcx_version(struct mcx_softc *);
2547 1.1 jmcneill static int mcx_init_wait(struct mcx_softc *);
2548 1.1 jmcneill static int mcx_enable_hca(struct mcx_softc *);
2549 1.1 jmcneill static int mcx_teardown_hca(struct mcx_softc *, uint16_t);
2550 1.1 jmcneill static int mcx_access_hca_reg(struct mcx_softc *, uint16_t, int, void *,
2551 1.1 jmcneill int);
2552 1.1 jmcneill static int mcx_issi(struct mcx_softc *);
2553 1.1 jmcneill static int mcx_pages(struct mcx_softc *, struct mcx_hwmem *, uint16_t);
2554 1.1 jmcneill static int mcx_hca_max_caps(struct mcx_softc *);
2555 1.1 jmcneill static int mcx_hca_set_caps(struct mcx_softc *);
2556 1.1 jmcneill static int mcx_init_hca(struct mcx_softc *);
2557 1.1 jmcneill static int mcx_set_driver_version(struct mcx_softc *);
2558 1.1 jmcneill static int mcx_iff(struct mcx_softc *);
2559 1.15 jmcneill static int mcx_alloc_uar(struct mcx_softc *, int *);
2560 1.1 jmcneill static int mcx_alloc_pd(struct mcx_softc *);
2561 1.1 jmcneill static int mcx_alloc_tdomain(struct mcx_softc *);
2562 1.15 jmcneill static int mcx_create_eq(struct mcx_softc *, struct mcx_eq *, int,
2563 1.15 jmcneill uint64_t, int);
2564 1.1 jmcneill static int mcx_query_nic_vport_context(struct mcx_softc *, uint8_t *);
2565 1.1 jmcneill static int mcx_query_special_contexts(struct mcx_softc *);
2566 1.1 jmcneill static int mcx_set_port_mtu(struct mcx_softc *, int);
2567 1.15 jmcneill static int mcx_create_cq(struct mcx_softc *, struct mcx_cq *, int, int,
2568 1.15 jmcneill int);
2569 1.15 jmcneill static int mcx_destroy_cq(struct mcx_softc *, struct mcx_cq *);
2570 1.15 jmcneill static int mcx_create_sq(struct mcx_softc *, struct mcx_tx *, int, int,
2571 1.15 jmcneill int);
2572 1.15 jmcneill static int mcx_destroy_sq(struct mcx_softc *, struct mcx_tx *);
2573 1.15 jmcneill static int mcx_ready_sq(struct mcx_softc *, struct mcx_tx *);
2574 1.15 jmcneill static int mcx_create_rq(struct mcx_softc *, struct mcx_rx *, int, int);
2575 1.15 jmcneill static int mcx_destroy_rq(struct mcx_softc *, struct mcx_rx *);
2576 1.15 jmcneill static int mcx_ready_rq(struct mcx_softc *, struct mcx_rx *);
2577 1.15 jmcneill static int mcx_create_tir_direct(struct mcx_softc *, struct mcx_rx *,
2578 1.15 jmcneill int *);
2579 1.15 jmcneill static int mcx_create_tir_indirect(struct mcx_softc *, int, uint32_t,
2580 1.15 jmcneill int *);
2581 1.15 jmcneill static int mcx_destroy_tir(struct mcx_softc *, int);
2582 1.15 jmcneill static int mcx_create_tis(struct mcx_softc *, int *);
2583 1.15 jmcneill static int mcx_destroy_tis(struct mcx_softc *, int);
2584 1.15 jmcneill static int mcx_create_rqt(struct mcx_softc *, int, int *, int *);
2585 1.15 jmcneill static int mcx_destroy_rqt(struct mcx_softc *, int);
2586 1.15 jmcneill static int mcx_create_flow_table(struct mcx_softc *, int, int, int *);
2587 1.15 jmcneill static int mcx_set_flow_table_root(struct mcx_softc *, int);
2588 1.15 jmcneill static int mcx_destroy_flow_table(struct mcx_softc *, int);
2589 1.15 jmcneill static int mcx_create_flow_group(struct mcx_softc *, int, int, int,
2590 1.1 jmcneill int, int, struct mcx_flow_match *);
2591 1.1 jmcneill static int mcx_destroy_flow_group(struct mcx_softc *, int);
2592 1.15 jmcneill static int mcx_set_flow_table_entry_mac(struct mcx_softc *, int, int,
2593 1.15 jmcneill const uint8_t *, uint32_t);
2594 1.15 jmcneill static int mcx_set_flow_table_entry_proto(struct mcx_softc *, int, int,
2595 1.15 jmcneill int, int, uint32_t);
2596 1.1 jmcneill static int mcx_delete_flow_table_entry(struct mcx_softc *, int, int);
2597 1.1 jmcneill
2598 1.15 jmcneill #if NKSTAT > 0
2599 1.15 jmcneill static int mcx_query_rq(struct mcx_softc *, struct mcx_rx *, struct mcx_rq_ctx *);
2600 1.15 jmcneill static int mcx_query_sq(struct mcx_softc *, struct mcx_tx *, struct mcx_sq_ctx *);
2601 1.15 jmcneill static int mcx_query_cq(struct mcx_softc *, struct mcx_cq *, struct mcx_cq_ctx *);
2602 1.15 jmcneill static int mcx_query_eq(struct mcx_softc *, struct mcx_eq *, struct mcx_eq_ctx *);
2603 1.15 jmcneill #endif
2604 1.15 jmcneill
2605 1.1 jmcneill #if 0
2606 1.15 jmcneill static int mcx_dump_flow_table(struct mcx_softc *, int);
2607 1.15 jmcneill static int mcx_dump_flow_table_entry(struct mcx_softc *, int, int);
2608 1.15 jmcneill static int mcx_dump_flow_group(struct mcx_softc *, int);
2609 1.1 jmcneill #endif
2610 1.1 jmcneill
2611 1.1 jmcneill
2612 1.1 jmcneill /*
2613 1.1 jmcneill static void mcx_cmdq_dump(const struct mcx_cmdq_entry *);
2614 1.1 jmcneill static void mcx_cmdq_mbox_dump(struct mcx_dmamem *, int);
2615 1.1 jmcneill */
2616 1.1 jmcneill static void mcx_refill(void *);
2617 1.15 jmcneill static int mcx_process_rx(struct mcx_softc *, struct mcx_rx *,
2618 1.15 jmcneill struct mcx_cq_entry *, struct mcx_mbufq *,
2619 1.15 jmcneill const struct mcx_calibration *);
2620 1.15 jmcneill static int mcx_process_txeof(struct mcx_softc *, struct mcx_tx *,
2621 1.15 jmcneill struct mcx_cq_entry *);
2622 1.15 jmcneill static void mcx_process_cq(struct mcx_softc *, struct mcx_queues *,
2623 1.15 jmcneill struct mcx_cq *);
2624 1.15 jmcneill
2625 1.15 jmcneill static void mcx_arm_cq(struct mcx_softc *, struct mcx_cq *, int);
2626 1.15 jmcneill static void mcx_arm_eq(struct mcx_softc *, struct mcx_eq *, int);
2627 1.15 jmcneill static int mcx_admin_intr(void *);
2628 1.15 jmcneill static int mcx_cq_intr(void *);
2629 1.1 jmcneill
2630 1.1 jmcneill static int mcx_init(struct ifnet *);
2631 1.1 jmcneill static void mcx_stop(struct ifnet *, int);
2632 1.1 jmcneill static int mcx_ioctl(struct ifnet *, u_long, void *);
2633 1.1 jmcneill static void mcx_start(struct ifnet *);
2634 1.16 jmcneill static int mcx_transmit(struct ifnet *, struct mbuf *);
2635 1.16 jmcneill static void mcx_deferred_transmit(void *);
2636 1.1 jmcneill static void mcx_watchdog(struct ifnet *);
2637 1.1 jmcneill static void mcx_media_add_types(struct mcx_softc *);
2638 1.1 jmcneill static void mcx_media_status(struct ifnet *, struct ifmediareq *);
2639 1.1 jmcneill static int mcx_media_change(struct ifnet *);
2640 1.1 jmcneill #if 0
2641 1.1 jmcneill static int mcx_get_sffpage(struct ifnet *, struct if_sffpage *);
2642 1.1 jmcneill #endif
2643 1.1 jmcneill static void mcx_port_change(struct work *, void *);
2644 1.1 jmcneill
2645 1.1 jmcneill static void mcx_calibrate_first(struct mcx_softc *);
2646 1.1 jmcneill static void mcx_calibrate(void *);
2647 1.1 jmcneill
2648 1.1 jmcneill static inline uint32_t
2649 1.1 jmcneill mcx_rd(struct mcx_softc *, bus_size_t);
2650 1.1 jmcneill static inline void
2651 1.1 jmcneill mcx_wr(struct mcx_softc *, bus_size_t, uint32_t);
2652 1.1 jmcneill static inline void
2653 1.1 jmcneill mcx_bar(struct mcx_softc *, bus_size_t, bus_size_t, int);
2654 1.1 jmcneill
2655 1.1 jmcneill static uint64_t mcx_timer(struct mcx_softc *);
2656 1.1 jmcneill
2657 1.1 jmcneill static int mcx_dmamem_alloc(struct mcx_softc *, struct mcx_dmamem *,
2658 1.1 jmcneill bus_size_t, u_int align);
2659 1.1 jmcneill static void mcx_dmamem_zero(struct mcx_dmamem *);
2660 1.1 jmcneill static void mcx_dmamem_free(struct mcx_softc *, struct mcx_dmamem *);
2661 1.1 jmcneill
2662 1.1 jmcneill static int mcx_hwmem_alloc(struct mcx_softc *, struct mcx_hwmem *,
2663 1.1 jmcneill unsigned int);
2664 1.1 jmcneill static void mcx_hwmem_free(struct mcx_softc *, struct mcx_hwmem *);
2665 1.1 jmcneill
2666 1.1 jmcneill CFATTACH_DECL_NEW(mcx, sizeof(struct mcx_softc), mcx_match, mcx_attach, NULL, NULL);
2667 1.1 jmcneill
2668 1.1 jmcneill static const struct {
2669 1.1 jmcneill pci_vendor_id_t vendor;
2670 1.1 jmcneill pci_product_id_t product;
2671 1.1 jmcneill } mcx_devices[] = {
2672 1.1 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27700 },
2673 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27700VF },
2674 1.1 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27710 },
2675 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27710VF },
2676 1.1 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27800 },
2677 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT27800VF },
2678 1.1 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT28800 },
2679 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT28800VF },
2680 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT28908 },
2681 1.15 jmcneill { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT2892 },
2682 1.1 jmcneill };
2683 1.1 jmcneill
2684 1.13 jmcneill struct mcx_eth_proto_capability {
2685 1.13 jmcneill uint64_t cap_media;
2686 1.13 jmcneill uint64_t cap_baudrate;
2687 1.13 jmcneill };
2688 1.13 jmcneill
2689 1.13 jmcneill static const struct mcx_eth_proto_capability mcx_eth_cap_map[] = {
2690 1.13 jmcneill [MCX_ETHER_CAP_SGMII] = { IFM_1000_SGMII, IF_Gbps(1) },
2691 1.13 jmcneill [MCX_ETHER_CAP_1000_KX] = { IFM_1000_KX, IF_Gbps(1) },
2692 1.13 jmcneill [MCX_ETHER_CAP_10G_CX4] = { IFM_10G_CX4, IF_Gbps(10) },
2693 1.13 jmcneill [MCX_ETHER_CAP_10G_KX4] = { IFM_10G_KX4, IF_Gbps(10) },
2694 1.13 jmcneill [MCX_ETHER_CAP_10G_KR] = { IFM_10G_KR, IF_Gbps(10) },
2695 1.13 jmcneill [MCX_ETHER_CAP_20G_KR2] = { IFM_20G_KR2, IF_Gbps(20) },
2696 1.13 jmcneill [MCX_ETHER_CAP_40G_CR4] = { IFM_40G_CR4, IF_Gbps(40) },
2697 1.13 jmcneill [MCX_ETHER_CAP_40G_KR4] = { IFM_40G_KR4, IF_Gbps(40) },
2698 1.13 jmcneill [MCX_ETHER_CAP_56G_R4] = { IFM_56G_R4, IF_Gbps(56) },
2699 1.13 jmcneill [MCX_ETHER_CAP_10G_CR] = { IFM_10G_CR1, IF_Gbps(10) },
2700 1.13 jmcneill [MCX_ETHER_CAP_10G_SR] = { IFM_10G_SR, IF_Gbps(10) },
2701 1.13 jmcneill [MCX_ETHER_CAP_10G_LR] = { IFM_10G_LR, IF_Gbps(10) },
2702 1.13 jmcneill [MCX_ETHER_CAP_40G_SR4] = { IFM_40G_SR4, IF_Gbps(40) },
2703 1.13 jmcneill [MCX_ETHER_CAP_40G_LR4] = { IFM_40G_LR4, IF_Gbps(40) },
2704 1.13 jmcneill [MCX_ETHER_CAP_50G_SR2] = { IFM_50G_SR2, IF_Gbps(50) },
2705 1.13 jmcneill [MCX_ETHER_CAP_100G_CR4] = { IFM_100G_CR4, IF_Gbps(100) },
2706 1.13 jmcneill [MCX_ETHER_CAP_100G_SR4] = { IFM_100G_SR4, IF_Gbps(100) },
2707 1.13 jmcneill [MCX_ETHER_CAP_100G_KR4] = { IFM_100G_KR4, IF_Gbps(100) },
2708 1.13 jmcneill [MCX_ETHER_CAP_100G_LR4] = { IFM_100G_LR4, IF_Gbps(100) },
2709 1.13 jmcneill [MCX_ETHER_CAP_100_TX] = { IFM_100_TX, IF_Mbps(100) },
2710 1.13 jmcneill [MCX_ETHER_CAP_1000_T] = { IFM_1000_T, IF_Gbps(1) },
2711 1.13 jmcneill [MCX_ETHER_CAP_10G_T] = { IFM_10G_T, IF_Gbps(10) },
2712 1.13 jmcneill [MCX_ETHER_CAP_25G_CR] = { IFM_25G_CR, IF_Gbps(25) },
2713 1.13 jmcneill [MCX_ETHER_CAP_25G_KR] = { IFM_25G_KR, IF_Gbps(25) },
2714 1.13 jmcneill [MCX_ETHER_CAP_25G_SR] = { IFM_25G_SR, IF_Gbps(25) },
2715 1.13 jmcneill [MCX_ETHER_CAP_50G_CR2] = { IFM_50G_CR2, IF_Gbps(50) },
2716 1.13 jmcneill [MCX_ETHER_CAP_50G_KR2] = { IFM_50G_KR2, IF_Gbps(50) },
2717 1.1 jmcneill };
2718 1.1 jmcneill
2719 1.1 jmcneill static int
2720 1.13 jmcneill mcx_get_id(uint32_t val)
2721 1.13 jmcneill {
2722 1.13 jmcneill return be32toh(val) & 0x00ffffff;
2723 1.13 jmcneill }
2724 1.13 jmcneill
2725 1.13 jmcneill static int
2726 1.1 jmcneill mcx_match(device_t parent, cfdata_t cf, void *aux)
2727 1.1 jmcneill {
2728 1.1 jmcneill struct pci_attach_args *pa = aux;
2729 1.1 jmcneill int n;
2730 1.1 jmcneill
2731 1.1 jmcneill for (n = 0; n < __arraycount(mcx_devices); n++) {
2732 1.1 jmcneill if (PCI_VENDOR(pa->pa_id) == mcx_devices[n].vendor &&
2733 1.1 jmcneill PCI_PRODUCT(pa->pa_id) == mcx_devices[n].product)
2734 1.1 jmcneill return 1;
2735 1.1 jmcneill }
2736 1.1 jmcneill
2737 1.1 jmcneill return 0;
2738 1.1 jmcneill }
2739 1.1 jmcneill
2740 1.1 jmcneill void
2741 1.1 jmcneill mcx_attach(device_t parent, device_t self, void *aux)
2742 1.1 jmcneill {
2743 1.1 jmcneill struct mcx_softc *sc = device_private(self);
2744 1.1 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
2745 1.1 jmcneill struct pci_attach_args *pa = aux;
2746 1.22 jmcneill struct ifcapreq ifcr;
2747 1.1 jmcneill uint8_t enaddr[ETHER_ADDR_LEN];
2748 1.1 jmcneill int counts[PCI_INTR_TYPE_SIZE];
2749 1.15 jmcneill char intrxname[32];
2750 1.1 jmcneill pcireg_t memtype;
2751 1.1 jmcneill uint32_t r;
2752 1.1 jmcneill unsigned int cq_stride;
2753 1.1 jmcneill unsigned int cq_size;
2754 1.15 jmcneill int i, msix;
2755 1.15 jmcneill kcpuset_t *affinity;
2756 1.1 jmcneill
2757 1.1 jmcneill sc->sc_dev = self;
2758 1.1 jmcneill sc->sc_pc = pa->pa_pc;
2759 1.1 jmcneill sc->sc_tag = pa->pa_tag;
2760 1.11 thorpej if (pci_dma64_available(pa))
2761 1.11 thorpej sc->sc_dmat = pa->pa_dmat64;
2762 1.11 thorpej else
2763 1.11 thorpej sc->sc_dmat = pa->pa_dmat;
2764 1.1 jmcneill
2765 1.1 jmcneill /* Map the PCI memory space */
2766 1.1 jmcneill memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MCX_HCA_BAR);
2767 1.1 jmcneill if (pci_mapreg_map(pa, MCX_HCA_BAR, memtype,
2768 1.21 jmcneill #ifdef __NetBSD__
2769 1.21 jmcneill 0,
2770 1.21 jmcneill #else
2771 1.21 jmcneill BUS_SPACE_MAP_PREFETCHABLE,
2772 1.21 jmcneill #endif
2773 1.21 jmcneill &sc->sc_memt, &sc->sc_memh,
2774 1.1 jmcneill NULL, &sc->sc_mems)) {
2775 1.1 jmcneill aprint_error(": unable to map register memory\n");
2776 1.1 jmcneill return;
2777 1.1 jmcneill }
2778 1.1 jmcneill
2779 1.1 jmcneill pci_aprint_devinfo(pa, "Ethernet controller");
2780 1.1 jmcneill
2781 1.12 thorpej mutex_init(&sc->sc_media_mutex, MUTEX_DEFAULT, IPL_SOFTNET);
2782 1.12 thorpej
2783 1.1 jmcneill if (mcx_version(sc) != 0) {
2784 1.1 jmcneill /* error printed by mcx_version */
2785 1.1 jmcneill goto unmap;
2786 1.1 jmcneill }
2787 1.1 jmcneill
2788 1.1 jmcneill r = mcx_rd(sc, MCX_CMDQ_ADDR_LO);
2789 1.1 jmcneill cq_stride = 1 << MCX_CMDQ_LOG_STRIDE(r); /* size of the entries */
2790 1.1 jmcneill cq_size = 1 << MCX_CMDQ_LOG_SIZE(r); /* number of entries */
2791 1.1 jmcneill if (cq_size > MCX_MAX_CQE) {
2792 1.1 jmcneill aprint_error_dev(self,
2793 1.1 jmcneill "command queue size overflow %u\n", cq_size);
2794 1.1 jmcneill goto unmap;
2795 1.1 jmcneill }
2796 1.1 jmcneill if (cq_stride < sizeof(struct mcx_cmdq_entry)) {
2797 1.1 jmcneill aprint_error_dev(self,
2798 1.1 jmcneill "command queue entry size underflow %u\n", cq_stride);
2799 1.1 jmcneill goto unmap;
2800 1.1 jmcneill }
2801 1.1 jmcneill if (cq_stride * cq_size > MCX_PAGE_SIZE) {
2802 1.1 jmcneill aprint_error_dev(self, "command queue page overflow\n");
2803 1.1 jmcneill goto unmap;
2804 1.1 jmcneill }
2805 1.1 jmcneill
2806 1.15 jmcneill if (mcx_dmamem_alloc(sc, &sc->sc_doorbell_mem, MCX_DOORBELL_AREA_SIZE,
2807 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
2808 1.1 jmcneill aprint_error_dev(self, "unable to allocate doorbell memory\n");
2809 1.1 jmcneill goto unmap;
2810 1.1 jmcneill }
2811 1.1 jmcneill
2812 1.1 jmcneill if (mcx_dmamem_alloc(sc, &sc->sc_cmdq_mem, MCX_PAGE_SIZE,
2813 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
2814 1.1 jmcneill aprint_error_dev(self, "unable to allocate command queue\n");
2815 1.1 jmcneill goto dbfree;
2816 1.1 jmcneill }
2817 1.1 jmcneill
2818 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_HI, MCX_DMA_DVA(&sc->sc_cmdq_mem) >> 32);
2819 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_ADDR_HI, sizeof(uint32_t),
2820 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
2821 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_LO, MCX_DMA_DVA(&sc->sc_cmdq_mem));
2822 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_ADDR_LO, sizeof(uint32_t),
2823 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
2824 1.1 jmcneill
2825 1.1 jmcneill if (mcx_init_wait(sc) != 0) {
2826 1.1 jmcneill aprint_error_dev(self, "timeout waiting for init\n");
2827 1.1 jmcneill goto cqfree;
2828 1.1 jmcneill }
2829 1.1 jmcneill
2830 1.1 jmcneill sc->sc_cmdq_mask = cq_size - 1;
2831 1.1 jmcneill sc->sc_cmdq_size = cq_stride;
2832 1.1 jmcneill
2833 1.1 jmcneill if (mcx_enable_hca(sc) != 0) {
2834 1.1 jmcneill /* error printed by mcx_enable_hca */
2835 1.1 jmcneill goto cqfree;
2836 1.1 jmcneill }
2837 1.1 jmcneill
2838 1.1 jmcneill if (mcx_issi(sc) != 0) {
2839 1.1 jmcneill /* error printed by mcx_issi */
2840 1.1 jmcneill goto teardown;
2841 1.1 jmcneill }
2842 1.1 jmcneill
2843 1.1 jmcneill if (mcx_pages(sc, &sc->sc_boot_pages,
2844 1.1 jmcneill htobe16(MCX_CMD_QUERY_PAGES_BOOT)) != 0) {
2845 1.1 jmcneill /* error printed by mcx_pages */
2846 1.1 jmcneill goto teardown;
2847 1.1 jmcneill }
2848 1.1 jmcneill
2849 1.1 jmcneill if (mcx_hca_max_caps(sc) != 0) {
2850 1.1 jmcneill /* error printed by mcx_hca_max_caps */
2851 1.1 jmcneill goto teardown;
2852 1.1 jmcneill }
2853 1.1 jmcneill
2854 1.1 jmcneill if (mcx_hca_set_caps(sc) != 0) {
2855 1.1 jmcneill /* error printed by mcx_hca_set_caps */
2856 1.1 jmcneill goto teardown;
2857 1.1 jmcneill }
2858 1.1 jmcneill
2859 1.1 jmcneill if (mcx_pages(sc, &sc->sc_init_pages,
2860 1.1 jmcneill htobe16(MCX_CMD_QUERY_PAGES_INIT)) != 0) {
2861 1.1 jmcneill /* error printed by mcx_pages */
2862 1.1 jmcneill goto teardown;
2863 1.1 jmcneill }
2864 1.1 jmcneill
2865 1.1 jmcneill if (mcx_init_hca(sc) != 0) {
2866 1.1 jmcneill /* error printed by mcx_init_hca */
2867 1.1 jmcneill goto teardown;
2868 1.1 jmcneill }
2869 1.1 jmcneill
2870 1.1 jmcneill if (mcx_pages(sc, &sc->sc_regular_pages,
2871 1.1 jmcneill htobe16(MCX_CMD_QUERY_PAGES_REGULAR)) != 0) {
2872 1.1 jmcneill /* error printed by mcx_pages */
2873 1.1 jmcneill goto teardown;
2874 1.1 jmcneill }
2875 1.1 jmcneill
2876 1.1 jmcneill /* apparently not necessary? */
2877 1.1 jmcneill if (mcx_set_driver_version(sc) != 0) {
2878 1.1 jmcneill /* error printed by mcx_set_driver_version */
2879 1.1 jmcneill goto teardown;
2880 1.1 jmcneill }
2881 1.1 jmcneill
2882 1.1 jmcneill if (mcx_iff(sc) != 0) { /* modify nic vport context */
2883 1.1 jmcneill /* error printed by mcx_iff? */
2884 1.1 jmcneill goto teardown;
2885 1.1 jmcneill }
2886 1.1 jmcneill
2887 1.15 jmcneill if (mcx_alloc_uar(sc, &sc->sc_uar) != 0) {
2888 1.1 jmcneill /* error printed by mcx_alloc_uar */
2889 1.1 jmcneill goto teardown;
2890 1.1 jmcneill }
2891 1.1 jmcneill
2892 1.1 jmcneill if (mcx_alloc_pd(sc) != 0) {
2893 1.1 jmcneill /* error printed by mcx_alloc_pd */
2894 1.1 jmcneill goto teardown;
2895 1.1 jmcneill }
2896 1.1 jmcneill
2897 1.1 jmcneill if (mcx_alloc_tdomain(sc) != 0) {
2898 1.1 jmcneill /* error printed by mcx_alloc_tdomain */
2899 1.1 jmcneill goto teardown;
2900 1.1 jmcneill }
2901 1.1 jmcneill
2902 1.1 jmcneill /*
2903 1.1 jmcneill * PRM makes no mention of msi interrupts, just legacy and msi-x.
2904 1.1 jmcneill * mellanox support tells me legacy interrupts are not supported,
2905 1.1 jmcneill * so we're stuck with just msi-x.
2906 1.1 jmcneill */
2907 1.15 jmcneill counts[PCI_INTR_TYPE_MSIX] = -1;
2908 1.1 jmcneill counts[PCI_INTR_TYPE_MSI] = 0;
2909 1.1 jmcneill counts[PCI_INTR_TYPE_INTX] = 0;
2910 1.1 jmcneill if (pci_intr_alloc(pa, &sc->sc_intrs, counts, PCI_INTR_TYPE_MSIX) != 0) {
2911 1.1 jmcneill aprint_error_dev(self, "unable to allocate interrupt\n");
2912 1.1 jmcneill goto teardown;
2913 1.1 jmcneill }
2914 1.15 jmcneill if (counts[PCI_INTR_TYPE_MSIX] < 2) {
2915 1.15 jmcneill aprint_error_dev(self, "not enough MSI-X vectors\n");
2916 1.15 jmcneill goto teardown;
2917 1.15 jmcneill }
2918 1.1 jmcneill KASSERT(pci_intr_type(sc->sc_pc, sc->sc_intrs[0]) == PCI_INTR_TYPE_MSIX);
2919 1.15 jmcneill snprintf(intrxname, sizeof(intrxname), "%s adminq", DEVNAME(sc));
2920 1.15 jmcneill sc->sc_ihc = mcx_establish_intr(sc, 0, NULL, mcx_admin_intr, sc,
2921 1.15 jmcneill intrxname);
2922 1.15 jmcneill if (sc->sc_ihc == NULL) {
2923 1.15 jmcneill aprint_error_dev(self, "couldn't establish adminq interrupt\n");
2924 1.1 jmcneill goto teardown;
2925 1.1 jmcneill }
2926 1.1 jmcneill
2927 1.15 jmcneill if (mcx_create_eq(sc, &sc->sc_admin_eq, sc->sc_uar,
2928 1.15 jmcneill (1ull << MCX_EVENT_TYPE_INTERNAL_ERROR) |
2929 1.15 jmcneill (1ull << MCX_EVENT_TYPE_PORT_CHANGE) |
2930 1.15 jmcneill (1ull << MCX_EVENT_TYPE_CMD_COMPLETION) |
2931 1.15 jmcneill (1ull << MCX_EVENT_TYPE_PAGE_REQUEST), 0) != 0) {
2932 1.1 jmcneill /* error printed by mcx_create_eq */
2933 1.1 jmcneill goto teardown;
2934 1.1 jmcneill }
2935 1.1 jmcneill
2936 1.1 jmcneill if (mcx_query_nic_vport_context(sc, enaddr) != 0) {
2937 1.1 jmcneill /* error printed by mcx_query_nic_vport_context */
2938 1.1 jmcneill goto teardown;
2939 1.1 jmcneill }
2940 1.1 jmcneill
2941 1.1 jmcneill if (mcx_query_special_contexts(sc) != 0) {
2942 1.1 jmcneill /* error printed by mcx_query_special_contexts */
2943 1.1 jmcneill goto teardown;
2944 1.1 jmcneill }
2945 1.1 jmcneill
2946 1.1 jmcneill if (mcx_set_port_mtu(sc, MCX_HARDMTU) != 0) {
2947 1.1 jmcneill /* error printed by mcx_set_port_mtu */
2948 1.1 jmcneill goto teardown;
2949 1.1 jmcneill }
2950 1.1 jmcneill
2951 1.1 jmcneill aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
2952 1.1 jmcneill ether_sprintf(enaddr));
2953 1.1 jmcneill
2954 1.15 jmcneill msix = counts[PCI_INTR_TYPE_MSIX];
2955 1.15 jmcneill msix--; /* admin ops took one */
2956 1.15 jmcneill
2957 1.15 jmcneill sc->sc_nqueues = uimin(MCX_MAX_QUEUES, msix);
2958 1.15 jmcneill sc->sc_nqueues = uimin(sc->sc_nqueues, ncpu);
2959 1.15 jmcneill sc->sc_queues = kmem_zalloc(sc->sc_nqueues * sizeof(*sc->sc_queues),
2960 1.15 jmcneill KM_SLEEP);
2961 1.15 jmcneill
2962 1.1 jmcneill strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
2963 1.1 jmcneill ifp->if_softc = sc;
2964 1.1 jmcneill ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
2965 1.1 jmcneill #ifdef MCX_MPSAFE
2966 1.1 jmcneill ifp->if_extflags = IFEF_MPSAFE;
2967 1.1 jmcneill #endif
2968 1.1 jmcneill ifp->if_init = mcx_init;
2969 1.1 jmcneill ifp->if_stop = mcx_stop;
2970 1.1 jmcneill ifp->if_ioctl = mcx_ioctl;
2971 1.1 jmcneill ifp->if_start = mcx_start;
2972 1.16 jmcneill if (sc->sc_nqueues > 1) {
2973 1.16 jmcneill ifp->if_transmit = mcx_transmit;
2974 1.16 jmcneill }
2975 1.1 jmcneill ifp->if_watchdog = mcx_watchdog;
2976 1.1 jmcneill ifp->if_mtu = sc->sc_hardmtu;
2977 1.15 jmcneill ifp->if_capabilities = IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx |
2978 1.15 jmcneill IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx |
2979 1.15 jmcneill IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx |
2980 1.15 jmcneill IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx |
2981 1.15 jmcneill IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx;
2982 1.1 jmcneill IFQ_SET_MAXLEN(&ifp->if_snd, 1024);
2983 1.1 jmcneill IFQ_SET_READY(&ifp->if_snd);
2984 1.1 jmcneill
2985 1.15 jmcneill sc->sc_ec.ec_capabilities = ETHERCAP_JUMBO_MTU |
2986 1.15 jmcneill ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING;
2987 1.15 jmcneill sc->sc_ec.ec_capenable |= ETHERCAP_VLAN_HWTAGGING;
2988 1.1 jmcneill
2989 1.1 jmcneill sc->sc_ec.ec_ifmedia = &sc->sc_media;
2990 1.12 thorpej ifmedia_init_with_lock(&sc->sc_media, IFM_IMASK, mcx_media_change,
2991 1.12 thorpej mcx_media_status, &sc->sc_media_mutex);
2992 1.1 jmcneill mcx_media_add_types(sc);
2993 1.1 jmcneill ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
2994 1.1 jmcneill ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
2995 1.1 jmcneill
2996 1.1 jmcneill if_attach(ifp);
2997 1.22 jmcneill
2998 1.22 jmcneill /* Enable hardware offload by default */
2999 1.22 jmcneill memset(&ifcr, 0, sizeof(ifcr));
3000 1.22 jmcneill ifcr.ifcr_capenable = ifp->if_capabilities;
3001 1.22 jmcneill ifioctl_common(ifp, SIOCSIFCAP, &ifcr);
3002 1.22 jmcneill
3003 1.1 jmcneill if_deferred_start_init(ifp, NULL);
3004 1.1 jmcneill
3005 1.1 jmcneill ether_ifattach(ifp, enaddr);
3006 1.1 jmcneill
3007 1.15 jmcneill kcpuset_create(&affinity, false);
3008 1.15 jmcneill kcpuset_set(affinity, 0);
3009 1.15 jmcneill
3010 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++) {
3011 1.15 jmcneill struct mcx_queues *q = &sc->sc_queues[i];
3012 1.15 jmcneill struct mcx_rx *rx = &q->q_rx;
3013 1.15 jmcneill struct mcx_tx *tx = &q->q_tx;
3014 1.15 jmcneill int vec;
3015 1.15 jmcneill
3016 1.15 jmcneill vec = i + 1;
3017 1.15 jmcneill q->q_sc = sc;
3018 1.15 jmcneill q->q_index = i;
3019 1.15 jmcneill
3020 1.15 jmcneill if (mcx_alloc_uar(sc, &q->q_uar) != 0) {
3021 1.15 jmcneill aprint_error_dev(self, "unable to alloc uar %d\n", i);
3022 1.15 jmcneill goto teardown;
3023 1.15 jmcneill }
3024 1.15 jmcneill
3025 1.15 jmcneill if (mcx_create_eq(sc, &q->q_eq, q->q_uar, 0, vec) != 0) {
3026 1.15 jmcneill aprint_error_dev(self,
3027 1.15 jmcneill "unable to create event queue %d\n", i);
3028 1.15 jmcneill goto teardown;
3029 1.15 jmcneill }
3030 1.15 jmcneill
3031 1.15 jmcneill rx->rx_softc = sc;
3032 1.15 jmcneill callout_init(&rx->rx_refill, CALLOUT_FLAGS);
3033 1.15 jmcneill callout_setfunc(&rx->rx_refill, mcx_refill, rx);
3034 1.15 jmcneill
3035 1.15 jmcneill tx->tx_softc = sc;
3036 1.16 jmcneill mutex_init(&tx->tx_lock, MUTEX_DEFAULT, IPL_NET);
3037 1.16 jmcneill tx->tx_pcq = pcq_create(MCX_TXQ_NUM, KM_SLEEP);
3038 1.16 jmcneill tx->tx_softint = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE,
3039 1.16 jmcneill mcx_deferred_transmit, tx);
3040 1.15 jmcneill
3041 1.15 jmcneill snprintf(intrxname, sizeof(intrxname), "%s queue %d",
3042 1.15 jmcneill DEVNAME(sc), i);
3043 1.15 jmcneill q->q_ihc = mcx_establish_intr(sc, vec, affinity, mcx_cq_intr,
3044 1.15 jmcneill q, intrxname);
3045 1.15 jmcneill }
3046 1.15 jmcneill
3047 1.1 jmcneill callout_init(&sc->sc_calibrate, CALLOUT_FLAGS);
3048 1.1 jmcneill callout_setfunc(&sc->sc_calibrate, mcx_calibrate, sc);
3049 1.1 jmcneill
3050 1.1 jmcneill if (workqueue_create(&sc->sc_workq, "mcxportchg", mcx_port_change, sc,
3051 1.1 jmcneill PRI_NONE, IPL_NET, 0) != 0) {
3052 1.1 jmcneill aprint_error_dev(self, "couldn't create port change workq\n");
3053 1.1 jmcneill goto teardown;
3054 1.1 jmcneill }
3055 1.1 jmcneill
3056 1.1 jmcneill mcx_port_change(&sc->sc_port_change, sc);
3057 1.1 jmcneill
3058 1.15 jmcneill sc->sc_mac_flow_table_id = -1;
3059 1.15 jmcneill sc->sc_rss_flow_table_id = -1;
3060 1.15 jmcneill sc->sc_rqt = -1;
3061 1.1 jmcneill for (i = 0; i < MCX_NUM_FLOW_GROUPS; i++) {
3062 1.15 jmcneill struct mcx_flow_group *mfg = &sc->sc_flow_group[i];
3063 1.15 jmcneill mfg->g_id = -1;
3064 1.15 jmcneill mfg->g_table = -1;
3065 1.15 jmcneill mfg->g_size = 0;
3066 1.15 jmcneill mfg->g_start = 0;
3067 1.1 jmcneill }
3068 1.1 jmcneill sc->sc_extra_mcast = 0;
3069 1.1 jmcneill memset(sc->sc_mcast_flows, 0, sizeof(sc->sc_mcast_flows));
3070 1.15 jmcneill
3071 1.15 jmcneill #if NKSTAT > 0
3072 1.15 jmcneill mcx_kstat_attach(sc);
3073 1.15 jmcneill #endif
3074 1.15 jmcneill mcx_timecounter_attach(sc);
3075 1.1 jmcneill return;
3076 1.1 jmcneill
3077 1.1 jmcneill teardown:
3078 1.1 jmcneill mcx_teardown_hca(sc, htobe16(MCX_CMD_TEARDOWN_HCA_GRACEFUL));
3079 1.1 jmcneill /* error printed by mcx_teardown_hca, and we're already unwinding */
3080 1.1 jmcneill cqfree:
3081 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_HI, MCX_DMA_DVA(&sc->sc_cmdq_mem) >> 32);
3082 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_ADDR_HI, sizeof(uint64_t),
3083 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
3084 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_LO, MCX_DMA_DVA(&sc->sc_cmdq_mem) |
3085 1.1 jmcneill MCX_CMDQ_INTERFACE_DISABLED);
3086 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_ADDR_LO, sizeof(uint64_t),
3087 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
3088 1.1 jmcneill
3089 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_HI, 0);
3090 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_ADDR_HI, sizeof(uint64_t),
3091 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
3092 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_ADDR_LO, MCX_CMDQ_INTERFACE_DISABLED);
3093 1.1 jmcneill
3094 1.1 jmcneill mcx_dmamem_free(sc, &sc->sc_cmdq_mem);
3095 1.1 jmcneill dbfree:
3096 1.1 jmcneill mcx_dmamem_free(sc, &sc->sc_doorbell_mem);
3097 1.1 jmcneill unmap:
3098 1.1 jmcneill bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
3099 1.1 jmcneill sc->sc_mems = 0;
3100 1.1 jmcneill }
3101 1.1 jmcneill
3102 1.15 jmcneill static void *
3103 1.15 jmcneill mcx_establish_intr(struct mcx_softc *sc, int index, kcpuset_t *affinity,
3104 1.15 jmcneill int (*func)(void *), void *arg, const char *xname)
3105 1.15 jmcneill {
3106 1.15 jmcneill char intrbuf[PCI_INTRSTR_LEN];
3107 1.15 jmcneill const char *intrstr;
3108 1.15 jmcneill void *ih;
3109 1.15 jmcneill
3110 1.15 jmcneill pci_intr_setattr(sc->sc_pc, &sc->sc_intrs[index], PCI_INTR_MPSAFE,
3111 1.15 jmcneill true);
3112 1.15 jmcneill
3113 1.15 jmcneill intrstr = pci_intr_string(sc->sc_pc, sc->sc_intrs[index], intrbuf,
3114 1.15 jmcneill sizeof(intrbuf));
3115 1.15 jmcneill ih = pci_intr_establish_xname(sc->sc_pc, sc->sc_intrs[index], IPL_NET,
3116 1.15 jmcneill func, arg, xname);
3117 1.15 jmcneill if (ih == NULL) {
3118 1.15 jmcneill aprint_error_dev(sc->sc_dev,
3119 1.15 jmcneill "unable to establish interrupt%s%s\n",
3120 1.15 jmcneill intrstr ? " at " : "",
3121 1.15 jmcneill intrstr ? intrstr : "");
3122 1.15 jmcneill return NULL;
3123 1.15 jmcneill }
3124 1.15 jmcneill
3125 1.15 jmcneill if (affinity != NULL && index > 0) {
3126 1.15 jmcneill /* Round-robin affinity */
3127 1.15 jmcneill kcpuset_zero(affinity);
3128 1.15 jmcneill kcpuset_set(affinity, (index - 1) % ncpu);
3129 1.15 jmcneill interrupt_distribute(ih, affinity, NULL);
3130 1.15 jmcneill }
3131 1.15 jmcneill
3132 1.15 jmcneill return ih;
3133 1.15 jmcneill }
3134 1.15 jmcneill
3135 1.1 jmcneill static void
3136 1.1 jmcneill mcx_rxr_init(struct mcx_rxring *rxr, u_int lwm __unused, u_int hwm)
3137 1.1 jmcneill {
3138 1.1 jmcneill rxr->rxr_total = hwm;
3139 1.1 jmcneill rxr->rxr_inuse = 0;
3140 1.1 jmcneill }
3141 1.1 jmcneill
3142 1.1 jmcneill static u_int
3143 1.1 jmcneill mcx_rxr_get(struct mcx_rxring *rxr, u_int max)
3144 1.1 jmcneill {
3145 1.1 jmcneill const u_int taken = MIN(max, rxr->rxr_total - rxr->rxr_inuse);
3146 1.1 jmcneill
3147 1.1 jmcneill rxr->rxr_inuse += taken;
3148 1.1 jmcneill
3149 1.1 jmcneill return taken;
3150 1.1 jmcneill }
3151 1.1 jmcneill
3152 1.1 jmcneill static void
3153 1.1 jmcneill mcx_rxr_put(struct mcx_rxring *rxr, u_int n)
3154 1.1 jmcneill {
3155 1.1 jmcneill rxr->rxr_inuse -= n;
3156 1.1 jmcneill }
3157 1.1 jmcneill
3158 1.1 jmcneill static u_int
3159 1.1 jmcneill mcx_rxr_inuse(struct mcx_rxring *rxr)
3160 1.1 jmcneill {
3161 1.1 jmcneill return rxr->rxr_inuse;
3162 1.1 jmcneill }
3163 1.1 jmcneill
3164 1.1 jmcneill static int
3165 1.1 jmcneill mcx_version(struct mcx_softc *sc)
3166 1.1 jmcneill {
3167 1.1 jmcneill uint32_t fw0, fw1;
3168 1.1 jmcneill uint16_t cmdif;
3169 1.1 jmcneill
3170 1.1 jmcneill fw0 = mcx_rd(sc, MCX_FW_VER);
3171 1.1 jmcneill fw1 = mcx_rd(sc, MCX_CMDIF_FW_SUBVER);
3172 1.1 jmcneill
3173 1.1 jmcneill aprint_normal_dev(sc->sc_dev, "FW %u.%u.%04u\n", MCX_FW_VER_MAJOR(fw0),
3174 1.1 jmcneill MCX_FW_VER_MINOR(fw0), MCX_FW_VER_SUBMINOR(fw1));
3175 1.1 jmcneill
3176 1.1 jmcneill cmdif = MCX_CMDIF(fw1);
3177 1.1 jmcneill if (cmdif != MCX_CMD_IF_SUPPORTED) {
3178 1.1 jmcneill aprint_error_dev(sc->sc_dev,
3179 1.1 jmcneill "unsupported command interface %u\n", cmdif);
3180 1.1 jmcneill return (-1);
3181 1.1 jmcneill }
3182 1.1 jmcneill
3183 1.1 jmcneill return (0);
3184 1.1 jmcneill }
3185 1.1 jmcneill
3186 1.1 jmcneill static int
3187 1.1 jmcneill mcx_init_wait(struct mcx_softc *sc)
3188 1.1 jmcneill {
3189 1.1 jmcneill unsigned int i;
3190 1.1 jmcneill uint32_t r;
3191 1.1 jmcneill
3192 1.1 jmcneill for (i = 0; i < 2000; i++) {
3193 1.1 jmcneill r = mcx_rd(sc, MCX_STATE);
3194 1.1 jmcneill if ((r & MCX_STATE_MASK) == MCX_STATE_READY)
3195 1.1 jmcneill return (0);
3196 1.1 jmcneill
3197 1.1 jmcneill delay(1000);
3198 1.1 jmcneill mcx_bar(sc, MCX_STATE, sizeof(uint32_t),
3199 1.1 jmcneill BUS_SPACE_BARRIER_READ);
3200 1.1 jmcneill }
3201 1.1 jmcneill
3202 1.1 jmcneill return (-1);
3203 1.1 jmcneill }
3204 1.1 jmcneill
3205 1.1 jmcneill static uint8_t
3206 1.1 jmcneill mcx_cmdq_poll(struct mcx_softc *sc, struct mcx_cmdq_entry *cqe,
3207 1.1 jmcneill unsigned int msec)
3208 1.1 jmcneill {
3209 1.1 jmcneill unsigned int i;
3210 1.1 jmcneill
3211 1.1 jmcneill for (i = 0; i < msec; i++) {
3212 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_cmdq_mem),
3213 1.1 jmcneill 0, MCX_DMA_LEN(&sc->sc_cmdq_mem), BUS_DMASYNC_POSTRW);
3214 1.1 jmcneill
3215 1.1 jmcneill if ((cqe->cq_status & MCX_CQ_STATUS_OWN_MASK) ==
3216 1.13 jmcneill MCX_CQ_STATUS_OWN_SW)
3217 1.1 jmcneill return (0);
3218 1.1 jmcneill
3219 1.1 jmcneill delay(1000);
3220 1.1 jmcneill }
3221 1.1 jmcneill
3222 1.1 jmcneill return (ETIMEDOUT);
3223 1.1 jmcneill }
3224 1.1 jmcneill
3225 1.1 jmcneill static uint32_t
3226 1.1 jmcneill mcx_mix_u64(uint32_t xor, uint64_t u64)
3227 1.1 jmcneill {
3228 1.1 jmcneill xor ^= u64 >> 32;
3229 1.1 jmcneill xor ^= u64;
3230 1.1 jmcneill
3231 1.1 jmcneill return (xor);
3232 1.1 jmcneill }
3233 1.1 jmcneill
3234 1.1 jmcneill static uint32_t
3235 1.1 jmcneill mcx_mix_u32(uint32_t xor, uint32_t u32)
3236 1.1 jmcneill {
3237 1.1 jmcneill xor ^= u32;
3238 1.1 jmcneill
3239 1.1 jmcneill return (xor);
3240 1.1 jmcneill }
3241 1.1 jmcneill
3242 1.1 jmcneill static uint32_t
3243 1.1 jmcneill mcx_mix_u8(uint32_t xor, uint8_t u8)
3244 1.1 jmcneill {
3245 1.1 jmcneill xor ^= u8;
3246 1.1 jmcneill
3247 1.1 jmcneill return (xor);
3248 1.1 jmcneill }
3249 1.1 jmcneill
3250 1.1 jmcneill static uint8_t
3251 1.1 jmcneill mcx_mix_done(uint32_t xor)
3252 1.1 jmcneill {
3253 1.1 jmcneill xor ^= xor >> 16;
3254 1.1 jmcneill xor ^= xor >> 8;
3255 1.1 jmcneill
3256 1.1 jmcneill return (xor);
3257 1.1 jmcneill }
3258 1.1 jmcneill
3259 1.1 jmcneill static uint8_t
3260 1.1 jmcneill mcx_xor(const void *buf, size_t len)
3261 1.1 jmcneill {
3262 1.1 jmcneill const uint32_t *dwords = buf;
3263 1.1 jmcneill uint32_t xor = 0xff;
3264 1.1 jmcneill size_t i;
3265 1.1 jmcneill
3266 1.1 jmcneill len /= sizeof(*dwords);
3267 1.1 jmcneill
3268 1.1 jmcneill for (i = 0; i < len; i++)
3269 1.1 jmcneill xor ^= dwords[i];
3270 1.1 jmcneill
3271 1.1 jmcneill return (mcx_mix_done(xor));
3272 1.1 jmcneill }
3273 1.1 jmcneill
3274 1.1 jmcneill static uint8_t
3275 1.1 jmcneill mcx_cmdq_token(struct mcx_softc *sc)
3276 1.1 jmcneill {
3277 1.1 jmcneill uint8_t token;
3278 1.1 jmcneill
3279 1.1 jmcneill do {
3280 1.1 jmcneill token = ++sc->sc_cmdq_token;
3281 1.1 jmcneill } while (token == 0);
3282 1.1 jmcneill
3283 1.1 jmcneill return (token);
3284 1.1 jmcneill }
3285 1.1 jmcneill
3286 1.1 jmcneill static void
3287 1.1 jmcneill mcx_cmdq_init(struct mcx_softc *sc, struct mcx_cmdq_entry *cqe,
3288 1.1 jmcneill uint32_t ilen, uint32_t olen, uint8_t token)
3289 1.1 jmcneill {
3290 1.1 jmcneill memset(cqe, 0, sc->sc_cmdq_size);
3291 1.1 jmcneill
3292 1.1 jmcneill cqe->cq_type = MCX_CMDQ_TYPE_PCIE;
3293 1.1 jmcneill be32enc(&cqe->cq_input_length, ilen);
3294 1.1 jmcneill be32enc(&cqe->cq_output_length, olen);
3295 1.1 jmcneill cqe->cq_token = token;
3296 1.1 jmcneill cqe->cq_status = MCX_CQ_STATUS_OWN_HW;
3297 1.1 jmcneill }
3298 1.1 jmcneill
3299 1.1 jmcneill static void
3300 1.1 jmcneill mcx_cmdq_sign(struct mcx_cmdq_entry *cqe)
3301 1.1 jmcneill {
3302 1.1 jmcneill cqe->cq_signature = ~mcx_xor(cqe, sizeof(*cqe));
3303 1.1 jmcneill }
3304 1.1 jmcneill
3305 1.1 jmcneill static int
3306 1.1 jmcneill mcx_cmdq_verify(const struct mcx_cmdq_entry *cqe)
3307 1.1 jmcneill {
3308 1.1 jmcneill /* return (mcx_xor(cqe, sizeof(*cqe)) ? -1 : 0); */
3309 1.1 jmcneill return (0);
3310 1.1 jmcneill }
3311 1.1 jmcneill
3312 1.1 jmcneill static void *
3313 1.1 jmcneill mcx_cmdq_in(struct mcx_cmdq_entry *cqe)
3314 1.1 jmcneill {
3315 1.1 jmcneill return (&cqe->cq_input_data);
3316 1.1 jmcneill }
3317 1.1 jmcneill
3318 1.1 jmcneill static void *
3319 1.1 jmcneill mcx_cmdq_out(struct mcx_cmdq_entry *cqe)
3320 1.1 jmcneill {
3321 1.1 jmcneill return (&cqe->cq_output_data);
3322 1.1 jmcneill }
3323 1.1 jmcneill
3324 1.1 jmcneill static void
3325 1.1 jmcneill mcx_cmdq_post(struct mcx_softc *sc, struct mcx_cmdq_entry *cqe,
3326 1.1 jmcneill unsigned int slot)
3327 1.1 jmcneill {
3328 1.1 jmcneill mcx_cmdq_sign(cqe);
3329 1.1 jmcneill
3330 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_cmdq_mem),
3331 1.1 jmcneill 0, MCX_DMA_LEN(&sc->sc_cmdq_mem), BUS_DMASYNC_PRERW);
3332 1.1 jmcneill
3333 1.1 jmcneill mcx_wr(sc, MCX_CMDQ_DOORBELL, 1U << slot);
3334 1.15 jmcneill mcx_bar(sc, MCX_CMDQ_DOORBELL, sizeof(uint32_t),
3335 1.15 jmcneill BUS_SPACE_BARRIER_WRITE);
3336 1.1 jmcneill }
3337 1.1 jmcneill
3338 1.1 jmcneill static int
3339 1.1 jmcneill mcx_enable_hca(struct mcx_softc *sc)
3340 1.1 jmcneill {
3341 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3342 1.1 jmcneill struct mcx_cmd_enable_hca_in *in;
3343 1.1 jmcneill struct mcx_cmd_enable_hca_out *out;
3344 1.1 jmcneill int error;
3345 1.1 jmcneill uint8_t status;
3346 1.1 jmcneill
3347 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3348 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
3349 1.1 jmcneill
3350 1.1 jmcneill in = mcx_cmdq_in(cqe);
3351 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ENABLE_HCA);
3352 1.1 jmcneill in->cmd_op_mod = htobe16(0);
3353 1.1 jmcneill in->cmd_function_id = htobe16(0);
3354 1.1 jmcneill
3355 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3356 1.1 jmcneill
3357 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
3358 1.1 jmcneill if (error != 0) {
3359 1.1 jmcneill printf(", hca enable timeout\n");
3360 1.1 jmcneill return (-1);
3361 1.1 jmcneill }
3362 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
3363 1.1 jmcneill printf(", hca enable command corrupt\n");
3364 1.1 jmcneill return (-1);
3365 1.1 jmcneill }
3366 1.1 jmcneill
3367 1.1 jmcneill status = cqe->cq_output_data[0];
3368 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
3369 1.1 jmcneill printf(", hca enable failed (%x)\n", status);
3370 1.1 jmcneill return (-1);
3371 1.1 jmcneill }
3372 1.1 jmcneill
3373 1.1 jmcneill return (0);
3374 1.1 jmcneill }
3375 1.1 jmcneill
3376 1.1 jmcneill static int
3377 1.1 jmcneill mcx_teardown_hca(struct mcx_softc *sc, uint16_t profile)
3378 1.1 jmcneill {
3379 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3380 1.1 jmcneill struct mcx_cmd_teardown_hca_in *in;
3381 1.1 jmcneill struct mcx_cmd_teardown_hca_out *out;
3382 1.1 jmcneill int error;
3383 1.1 jmcneill uint8_t status;
3384 1.1 jmcneill
3385 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3386 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
3387 1.1 jmcneill
3388 1.1 jmcneill in = mcx_cmdq_in(cqe);
3389 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_TEARDOWN_HCA);
3390 1.1 jmcneill in->cmd_op_mod = htobe16(0);
3391 1.1 jmcneill in->cmd_profile = profile;
3392 1.1 jmcneill
3393 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3394 1.1 jmcneill
3395 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
3396 1.1 jmcneill if (error != 0) {
3397 1.1 jmcneill printf(", hca teardown timeout\n");
3398 1.1 jmcneill return (-1);
3399 1.1 jmcneill }
3400 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
3401 1.1 jmcneill printf(", hca teardown command corrupt\n");
3402 1.1 jmcneill return (-1);
3403 1.1 jmcneill }
3404 1.1 jmcneill
3405 1.1 jmcneill status = cqe->cq_output_data[0];
3406 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
3407 1.1 jmcneill printf(", hca teardown failed (%x)\n", status);
3408 1.1 jmcneill return (-1);
3409 1.1 jmcneill }
3410 1.1 jmcneill
3411 1.1 jmcneill return (0);
3412 1.1 jmcneill }
3413 1.1 jmcneill
3414 1.1 jmcneill static int
3415 1.1 jmcneill mcx_cmdq_mboxes_alloc(struct mcx_softc *sc, struct mcx_dmamem *mxm,
3416 1.1 jmcneill unsigned int nmb, uint64_t *ptr, uint8_t token)
3417 1.1 jmcneill {
3418 1.1 jmcneill uint8_t *kva;
3419 1.1 jmcneill uint64_t dva;
3420 1.1 jmcneill int i;
3421 1.1 jmcneill int error;
3422 1.1 jmcneill
3423 1.1 jmcneill error = mcx_dmamem_alloc(sc, mxm,
3424 1.1 jmcneill nmb * MCX_CMDQ_MAILBOX_SIZE, MCX_CMDQ_MAILBOX_ALIGN);
3425 1.1 jmcneill if (error != 0)
3426 1.1 jmcneill return (error);
3427 1.1 jmcneill
3428 1.1 jmcneill mcx_dmamem_zero(mxm);
3429 1.1 jmcneill
3430 1.1 jmcneill dva = MCX_DMA_DVA(mxm);
3431 1.1 jmcneill kva = MCX_DMA_KVA(mxm);
3432 1.1 jmcneill for (i = 0; i < nmb; i++) {
3433 1.1 jmcneill struct mcx_cmdq_mailbox *mbox = (struct mcx_cmdq_mailbox *)kva;
3434 1.1 jmcneill
3435 1.1 jmcneill /* patch the cqe or mbox pointing at this one */
3436 1.1 jmcneill be64enc(ptr, dva);
3437 1.1 jmcneill
3438 1.1 jmcneill /* fill in this mbox */
3439 1.1 jmcneill be32enc(&mbox->mb_block_number, i);
3440 1.1 jmcneill mbox->mb_token = token;
3441 1.1 jmcneill
3442 1.1 jmcneill /* move to the next one */
3443 1.1 jmcneill ptr = &mbox->mb_next_ptr;
3444 1.1 jmcneill
3445 1.1 jmcneill dva += MCX_CMDQ_MAILBOX_SIZE;
3446 1.1 jmcneill kva += MCX_CMDQ_MAILBOX_SIZE;
3447 1.1 jmcneill }
3448 1.1 jmcneill
3449 1.1 jmcneill return (0);
3450 1.1 jmcneill }
3451 1.1 jmcneill
3452 1.1 jmcneill static uint32_t
3453 1.1 jmcneill mcx_cmdq_mbox_ctrl_sig(const struct mcx_cmdq_mailbox *mb)
3454 1.1 jmcneill {
3455 1.1 jmcneill uint32_t xor = 0xff;
3456 1.1 jmcneill
3457 1.1 jmcneill /* only 3 fields get set, so mix them directly */
3458 1.1 jmcneill xor = mcx_mix_u64(xor, mb->mb_next_ptr);
3459 1.1 jmcneill xor = mcx_mix_u32(xor, mb->mb_block_number);
3460 1.1 jmcneill xor = mcx_mix_u8(xor, mb->mb_token);
3461 1.1 jmcneill
3462 1.1 jmcneill return (mcx_mix_done(xor));
3463 1.1 jmcneill }
3464 1.1 jmcneill
3465 1.1 jmcneill static void
3466 1.1 jmcneill mcx_cmdq_mboxes_sign(struct mcx_dmamem *mxm, unsigned int nmb)
3467 1.1 jmcneill {
3468 1.1 jmcneill uint8_t *kva;
3469 1.1 jmcneill int i;
3470 1.1 jmcneill
3471 1.1 jmcneill kva = MCX_DMA_KVA(mxm);
3472 1.1 jmcneill
3473 1.1 jmcneill for (i = 0; i < nmb; i++) {
3474 1.1 jmcneill struct mcx_cmdq_mailbox *mb = (struct mcx_cmdq_mailbox *)kva;
3475 1.1 jmcneill uint8_t sig = mcx_cmdq_mbox_ctrl_sig(mb);
3476 1.1 jmcneill mb->mb_ctrl_signature = sig;
3477 1.1 jmcneill mb->mb_signature = sig ^
3478 1.1 jmcneill mcx_xor(mb->mb_data, sizeof(mb->mb_data));
3479 1.1 jmcneill
3480 1.1 jmcneill kva += MCX_CMDQ_MAILBOX_SIZE;
3481 1.1 jmcneill }
3482 1.1 jmcneill }
3483 1.1 jmcneill
3484 1.1 jmcneill static void
3485 1.1 jmcneill mcx_cmdq_mboxes_sync(struct mcx_softc *sc, struct mcx_dmamem *mxm, int ops)
3486 1.1 jmcneill {
3487 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(mxm),
3488 1.1 jmcneill 0, MCX_DMA_LEN(mxm), ops);
3489 1.1 jmcneill }
3490 1.1 jmcneill
3491 1.1 jmcneill static struct mcx_cmdq_mailbox *
3492 1.1 jmcneill mcx_cq_mbox(struct mcx_dmamem *mxm, unsigned int i)
3493 1.1 jmcneill {
3494 1.1 jmcneill uint8_t *kva;
3495 1.1 jmcneill
3496 1.1 jmcneill kva = MCX_DMA_KVA(mxm);
3497 1.1 jmcneill kva += i * MCX_CMDQ_MAILBOX_SIZE;
3498 1.1 jmcneill
3499 1.1 jmcneill return ((struct mcx_cmdq_mailbox *)kva);
3500 1.1 jmcneill }
3501 1.1 jmcneill
3502 1.1 jmcneill static inline void *
3503 1.1 jmcneill mcx_cq_mbox_data(struct mcx_cmdq_mailbox *mb)
3504 1.1 jmcneill {
3505 1.1 jmcneill return (&mb->mb_data);
3506 1.1 jmcneill }
3507 1.1 jmcneill
3508 1.1 jmcneill static void
3509 1.1 jmcneill mcx_cmdq_mboxes_copyin(struct mcx_dmamem *mxm, unsigned int nmb,
3510 1.1 jmcneill void *b, size_t len)
3511 1.1 jmcneill {
3512 1.1 jmcneill uint8_t *buf = b;
3513 1.1 jmcneill struct mcx_cmdq_mailbox *mb;
3514 1.1 jmcneill int i;
3515 1.1 jmcneill
3516 1.1 jmcneill mb = (struct mcx_cmdq_mailbox *)MCX_DMA_KVA(mxm);
3517 1.1 jmcneill for (i = 0; i < nmb; i++) {
3518 1.1 jmcneill
3519 1.1 jmcneill memcpy(mb->mb_data, buf, uimin(sizeof(mb->mb_data), len));
3520 1.1 jmcneill
3521 1.1 jmcneill if (sizeof(mb->mb_data) >= len)
3522 1.1 jmcneill break;
3523 1.1 jmcneill
3524 1.1 jmcneill buf += sizeof(mb->mb_data);
3525 1.1 jmcneill len -= sizeof(mb->mb_data);
3526 1.1 jmcneill mb++;
3527 1.1 jmcneill }
3528 1.1 jmcneill }
3529 1.1 jmcneill
3530 1.1 jmcneill static void
3531 1.13 jmcneill mcx_cmdq_mboxes_pas(struct mcx_dmamem *mxm, int offset, int npages,
3532 1.13 jmcneill struct mcx_dmamem *buf)
3533 1.13 jmcneill {
3534 1.13 jmcneill uint64_t *pas;
3535 1.13 jmcneill int mbox, mbox_pages, i;
3536 1.13 jmcneill
3537 1.13 jmcneill mbox = offset / MCX_CMDQ_MAILBOX_DATASIZE;
3538 1.13 jmcneill offset %= MCX_CMDQ_MAILBOX_DATASIZE;
3539 1.13 jmcneill
3540 1.13 jmcneill pas = mcx_cq_mbox_data(mcx_cq_mbox(mxm, mbox));
3541 1.13 jmcneill pas += (offset / sizeof(*pas));
3542 1.13 jmcneill mbox_pages = (MCX_CMDQ_MAILBOX_DATASIZE - offset) / sizeof(*pas);
3543 1.13 jmcneill for (i = 0; i < npages; i++) {
3544 1.13 jmcneill if (i == mbox_pages) {
3545 1.13 jmcneill mbox++;
3546 1.13 jmcneill pas = mcx_cq_mbox_data(mcx_cq_mbox(mxm, mbox));
3547 1.13 jmcneill mbox_pages += MCX_CMDQ_MAILBOX_DATASIZE / sizeof(*pas);
3548 1.13 jmcneill }
3549 1.13 jmcneill *pas = htobe64(MCX_DMA_DVA(buf) + (i * MCX_PAGE_SIZE));
3550 1.13 jmcneill pas++;
3551 1.13 jmcneill }
3552 1.13 jmcneill }
3553 1.13 jmcneill
3554 1.13 jmcneill static void
3555 1.1 jmcneill mcx_cmdq_mboxes_copyout(struct mcx_dmamem *mxm, int nmb, void *b, size_t len)
3556 1.1 jmcneill {
3557 1.1 jmcneill uint8_t *buf = b;
3558 1.1 jmcneill struct mcx_cmdq_mailbox *mb;
3559 1.1 jmcneill int i;
3560 1.1 jmcneill
3561 1.1 jmcneill mb = (struct mcx_cmdq_mailbox *)MCX_DMA_KVA(mxm);
3562 1.1 jmcneill for (i = 0; i < nmb; i++) {
3563 1.1 jmcneill memcpy(buf, mb->mb_data, uimin(sizeof(mb->mb_data), len));
3564 1.1 jmcneill
3565 1.1 jmcneill if (sizeof(mb->mb_data) >= len)
3566 1.1 jmcneill break;
3567 1.1 jmcneill
3568 1.1 jmcneill buf += sizeof(mb->mb_data);
3569 1.1 jmcneill len -= sizeof(mb->mb_data);
3570 1.1 jmcneill mb++;
3571 1.1 jmcneill }
3572 1.1 jmcneill }
3573 1.1 jmcneill
3574 1.1 jmcneill static void
3575 1.1 jmcneill mcx_cq_mboxes_free(struct mcx_softc *sc, struct mcx_dmamem *mxm)
3576 1.1 jmcneill {
3577 1.1 jmcneill mcx_dmamem_free(sc, mxm);
3578 1.1 jmcneill }
3579 1.1 jmcneill
3580 1.1 jmcneill #if 0
3581 1.1 jmcneill static void
3582 1.1 jmcneill mcx_cmdq_dump(const struct mcx_cmdq_entry *cqe)
3583 1.1 jmcneill {
3584 1.1 jmcneill unsigned int i;
3585 1.1 jmcneill
3586 1.1 jmcneill printf(" type %02x, ilen %u, iptr %016llx", cqe->cq_type,
3587 1.1 jmcneill be32dec(&cqe->cq_input_length), be64dec(&cqe->cq_input_ptr));
3588 1.1 jmcneill
3589 1.1 jmcneill printf(", idata ");
3590 1.1 jmcneill for (i = 0; i < sizeof(cqe->cq_input_data); i++)
3591 1.1 jmcneill printf("%02x", cqe->cq_input_data[i]);
3592 1.1 jmcneill
3593 1.1 jmcneill printf(", odata ");
3594 1.1 jmcneill for (i = 0; i < sizeof(cqe->cq_output_data); i++)
3595 1.1 jmcneill printf("%02x", cqe->cq_output_data[i]);
3596 1.1 jmcneill
3597 1.1 jmcneill printf(", optr %016llx, olen %u, token %02x, sig %02x, status %02x",
3598 1.1 jmcneill be64dec(&cqe->cq_output_ptr), be32dec(&cqe->cq_output_length),
3599 1.1 jmcneill cqe->cq_token, cqe->cq_signature, cqe->cq_status);
3600 1.1 jmcneill }
3601 1.1 jmcneill
3602 1.1 jmcneill static void
3603 1.1 jmcneill mcx_cmdq_mbox_dump(struct mcx_dmamem *mboxes, int num)
3604 1.1 jmcneill {
3605 1.1 jmcneill int i, j;
3606 1.1 jmcneill uint8_t *d;
3607 1.1 jmcneill
3608 1.1 jmcneill for (i = 0; i < num; i++) {
3609 1.1 jmcneill struct mcx_cmdq_mailbox *mbox;
3610 1.1 jmcneill mbox = mcx_cq_mbox(mboxes, i);
3611 1.1 jmcneill
3612 1.1 jmcneill d = mcx_cq_mbox_data(mbox);
3613 1.1 jmcneill for (j = 0; j < MCX_CMDQ_MAILBOX_DATASIZE; j++) {
3614 1.1 jmcneill if (j != 0 && (j % 16 == 0))
3615 1.1 jmcneill printf("\n");
3616 1.1 jmcneill printf("%.2x ", d[j]);
3617 1.1 jmcneill }
3618 1.1 jmcneill }
3619 1.1 jmcneill }
3620 1.1 jmcneill #endif
3621 1.1 jmcneill
3622 1.1 jmcneill static int
3623 1.1 jmcneill mcx_access_hca_reg(struct mcx_softc *sc, uint16_t reg, int op, void *data,
3624 1.1 jmcneill int len)
3625 1.1 jmcneill {
3626 1.1 jmcneill struct mcx_dmamem mxm;
3627 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3628 1.1 jmcneill struct mcx_cmd_access_reg_in *in;
3629 1.1 jmcneill struct mcx_cmd_access_reg_out *out;
3630 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
3631 1.1 jmcneill int error, nmb;
3632 1.1 jmcneill
3633 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3634 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + len, sizeof(*out) + len,
3635 1.1 jmcneill token);
3636 1.1 jmcneill
3637 1.1 jmcneill in = mcx_cmdq_in(cqe);
3638 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ACCESS_REG);
3639 1.1 jmcneill in->cmd_op_mod = htobe16(op);
3640 1.1 jmcneill in->cmd_register_id = htobe16(reg);
3641 1.1 jmcneill
3642 1.1 jmcneill nmb = howmany(len, MCX_CMDQ_MAILBOX_DATASIZE);
3643 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, nmb,
3644 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
3645 1.1 jmcneill printf(", unable to allocate access reg mailboxen\n");
3646 1.1 jmcneill return (-1);
3647 1.1 jmcneill }
3648 1.1 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
3649 1.1 jmcneill mcx_cmdq_mboxes_copyin(&mxm, nmb, data, len);
3650 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, nmb);
3651 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_PRERW);
3652 1.1 jmcneill
3653 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3654 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
3655 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_POSTRW);
3656 1.1 jmcneill
3657 1.1 jmcneill if (error != 0) {
3658 1.1 jmcneill printf("%s: access reg (%s %x) timeout\n", DEVNAME(sc),
3659 1.1 jmcneill (op == MCX_REG_OP_WRITE ? "write" : "read"), reg);
3660 1.1 jmcneill goto free;
3661 1.1 jmcneill }
3662 1.1 jmcneill error = mcx_cmdq_verify(cqe);
3663 1.1 jmcneill if (error != 0) {
3664 1.1 jmcneill printf("%s: access reg (%s %x) reply corrupt\n",
3665 1.1 jmcneill (op == MCX_REG_OP_WRITE ? "write" : "read"), DEVNAME(sc),
3666 1.1 jmcneill reg);
3667 1.1 jmcneill goto free;
3668 1.1 jmcneill }
3669 1.1 jmcneill
3670 1.1 jmcneill out = mcx_cmdq_out(cqe);
3671 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
3672 1.1 jmcneill printf("%s: access reg (%s %x) failed (%x, %.6x)\n",
3673 1.1 jmcneill DEVNAME(sc), (op == MCX_REG_OP_WRITE ? "write" : "read"),
3674 1.15 jmcneill reg, out->cmd_status, be32toh(out->cmd_syndrome));
3675 1.1 jmcneill error = -1;
3676 1.1 jmcneill goto free;
3677 1.1 jmcneill }
3678 1.1 jmcneill
3679 1.1 jmcneill mcx_cmdq_mboxes_copyout(&mxm, nmb, data, len);
3680 1.1 jmcneill free:
3681 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
3682 1.1 jmcneill
3683 1.1 jmcneill return (error);
3684 1.1 jmcneill }
3685 1.1 jmcneill
3686 1.1 jmcneill static int
3687 1.15 jmcneill mcx_set_issi(struct mcx_softc *sc, struct mcx_cmdq_entry *cqe,
3688 1.15 jmcneill unsigned int slot)
3689 1.1 jmcneill {
3690 1.1 jmcneill struct mcx_cmd_set_issi_in *in;
3691 1.1 jmcneill struct mcx_cmd_set_issi_out *out;
3692 1.1 jmcneill uint8_t status;
3693 1.1 jmcneill
3694 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
3695 1.1 jmcneill
3696 1.1 jmcneill in = mcx_cmdq_in(cqe);
3697 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_SET_ISSI);
3698 1.1 jmcneill in->cmd_op_mod = htobe16(0);
3699 1.1 jmcneill in->cmd_current_issi = htobe16(MCX_ISSI);
3700 1.1 jmcneill
3701 1.1 jmcneill mcx_cmdq_post(sc, cqe, slot);
3702 1.1 jmcneill if (mcx_cmdq_poll(sc, cqe, 1000) != 0)
3703 1.1 jmcneill return (-1);
3704 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0)
3705 1.1 jmcneill return (-1);
3706 1.1 jmcneill
3707 1.1 jmcneill status = cqe->cq_output_data[0];
3708 1.1 jmcneill if (status != MCX_CQ_STATUS_OK)
3709 1.1 jmcneill return (-1);
3710 1.1 jmcneill
3711 1.1 jmcneill return (0);
3712 1.1 jmcneill }
3713 1.1 jmcneill
3714 1.1 jmcneill static int
3715 1.1 jmcneill mcx_issi(struct mcx_softc *sc)
3716 1.1 jmcneill {
3717 1.1 jmcneill struct mcx_dmamem mxm;
3718 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3719 1.1 jmcneill struct mcx_cmd_query_issi_in *in;
3720 1.1 jmcneill struct mcx_cmd_query_issi_il_out *out;
3721 1.1 jmcneill struct mcx_cmd_query_issi_mb_out *mb;
3722 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
3723 1.1 jmcneill uint8_t status;
3724 1.1 jmcneill int error;
3725 1.1 jmcneill
3726 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3727 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*mb), token);
3728 1.1 jmcneill
3729 1.1 jmcneill in = mcx_cmdq_in(cqe);
3730 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_ISSI);
3731 1.1 jmcneill in->cmd_op_mod = htobe16(0);
3732 1.1 jmcneill
3733 1.1 jmcneill CTASSERT(sizeof(*mb) <= MCX_CMDQ_MAILBOX_DATASIZE);
3734 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
3735 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
3736 1.1 jmcneill printf(", unable to allocate query issi mailbox\n");
3737 1.1 jmcneill return (-1);
3738 1.1 jmcneill }
3739 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
3740 1.1 jmcneill
3741 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3742 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
3743 1.1 jmcneill if (error != 0) {
3744 1.1 jmcneill printf(", query issi timeout\n");
3745 1.1 jmcneill goto free;
3746 1.1 jmcneill }
3747 1.1 jmcneill error = mcx_cmdq_verify(cqe);
3748 1.1 jmcneill if (error != 0) {
3749 1.1 jmcneill printf(", query issi reply corrupt\n");
3750 1.1 jmcneill goto free;
3751 1.1 jmcneill }
3752 1.1 jmcneill
3753 1.1 jmcneill status = cqe->cq_output_data[0];
3754 1.1 jmcneill switch (status) {
3755 1.1 jmcneill case MCX_CQ_STATUS_OK:
3756 1.1 jmcneill break;
3757 1.1 jmcneill case MCX_CQ_STATUS_BAD_OPCODE:
3758 1.1 jmcneill /* use ISSI 0 */
3759 1.1 jmcneill goto free;
3760 1.1 jmcneill default:
3761 1.1 jmcneill printf(", query issi failed (%x)\n", status);
3762 1.1 jmcneill error = -1;
3763 1.1 jmcneill goto free;
3764 1.1 jmcneill }
3765 1.1 jmcneill
3766 1.1 jmcneill out = mcx_cmdq_out(cqe);
3767 1.1 jmcneill if (out->cmd_current_issi == htobe16(MCX_ISSI)) {
3768 1.1 jmcneill /* use ISSI 1 */
3769 1.1 jmcneill goto free;
3770 1.1 jmcneill }
3771 1.1 jmcneill
3772 1.1 jmcneill /* don't need to read cqe anymore, can be used for SET ISSI */
3773 1.1 jmcneill
3774 1.1 jmcneill mb = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
3775 1.1 jmcneill CTASSERT(MCX_ISSI < NBBY);
3776 1.1 jmcneill /* XXX math is hard */
3777 1.1 jmcneill if (!ISSET(mb->cmd_supported_issi[79], 1 << MCX_ISSI)) {
3778 1.1 jmcneill /* use ISSI 0 */
3779 1.1 jmcneill goto free;
3780 1.1 jmcneill }
3781 1.1 jmcneill
3782 1.1 jmcneill if (mcx_set_issi(sc, cqe, 0) != 0) {
3783 1.1 jmcneill /* ignore the error, just use ISSI 0 */
3784 1.1 jmcneill } else {
3785 1.1 jmcneill /* use ISSI 1 */
3786 1.1 jmcneill }
3787 1.1 jmcneill
3788 1.1 jmcneill free:
3789 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
3790 1.1 jmcneill return (error);
3791 1.1 jmcneill }
3792 1.1 jmcneill
3793 1.1 jmcneill static int
3794 1.1 jmcneill mcx_query_pages(struct mcx_softc *sc, uint16_t type,
3795 1.15 jmcneill int32_t *npages, uint16_t *func_id)
3796 1.1 jmcneill {
3797 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3798 1.1 jmcneill struct mcx_cmd_query_pages_in *in;
3799 1.1 jmcneill struct mcx_cmd_query_pages_out *out;
3800 1.1 jmcneill
3801 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3802 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
3803 1.1 jmcneill
3804 1.1 jmcneill in = mcx_cmdq_in(cqe);
3805 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_PAGES);
3806 1.1 jmcneill in->cmd_op_mod = type;
3807 1.1 jmcneill
3808 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3809 1.1 jmcneill if (mcx_cmdq_poll(sc, cqe, 1000) != 0) {
3810 1.1 jmcneill printf(", query pages timeout\n");
3811 1.1 jmcneill return (-1);
3812 1.1 jmcneill }
3813 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
3814 1.1 jmcneill printf(", query pages reply corrupt\n");
3815 1.1 jmcneill return (-1);
3816 1.1 jmcneill }
3817 1.1 jmcneill
3818 1.1 jmcneill out = mcx_cmdq_out(cqe);
3819 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
3820 1.1 jmcneill printf(", query pages failed (%x)\n", out->cmd_status);
3821 1.1 jmcneill return (-1);
3822 1.1 jmcneill }
3823 1.1 jmcneill
3824 1.1 jmcneill *func_id = out->cmd_func_id;
3825 1.1 jmcneill *npages = be32dec(&out->cmd_num_pages);
3826 1.1 jmcneill
3827 1.1 jmcneill return (0);
3828 1.1 jmcneill }
3829 1.1 jmcneill
3830 1.1 jmcneill struct bus_dma_iter {
3831 1.1 jmcneill bus_dmamap_t i_map;
3832 1.1 jmcneill bus_size_t i_offset;
3833 1.1 jmcneill unsigned int i_index;
3834 1.1 jmcneill };
3835 1.1 jmcneill
3836 1.1 jmcneill static void
3837 1.1 jmcneill bus_dma_iter_init(struct bus_dma_iter *i, bus_dmamap_t map)
3838 1.1 jmcneill {
3839 1.1 jmcneill i->i_map = map;
3840 1.1 jmcneill i->i_offset = 0;
3841 1.1 jmcneill i->i_index = 0;
3842 1.1 jmcneill }
3843 1.1 jmcneill
3844 1.1 jmcneill static bus_addr_t
3845 1.1 jmcneill bus_dma_iter_addr(struct bus_dma_iter *i)
3846 1.1 jmcneill {
3847 1.1 jmcneill return (i->i_map->dm_segs[i->i_index].ds_addr + i->i_offset);
3848 1.1 jmcneill }
3849 1.1 jmcneill
3850 1.1 jmcneill static void
3851 1.1 jmcneill bus_dma_iter_add(struct bus_dma_iter *i, bus_size_t size)
3852 1.1 jmcneill {
3853 1.1 jmcneill bus_dma_segment_t *seg = i->i_map->dm_segs + i->i_index;
3854 1.1 jmcneill bus_size_t diff;
3855 1.1 jmcneill
3856 1.1 jmcneill do {
3857 1.1 jmcneill diff = seg->ds_len - i->i_offset;
3858 1.1 jmcneill if (size < diff)
3859 1.1 jmcneill break;
3860 1.1 jmcneill
3861 1.1 jmcneill size -= diff;
3862 1.1 jmcneill
3863 1.1 jmcneill seg++;
3864 1.1 jmcneill
3865 1.1 jmcneill i->i_offset = 0;
3866 1.1 jmcneill i->i_index++;
3867 1.1 jmcneill } while (size > 0);
3868 1.1 jmcneill
3869 1.1 jmcneill i->i_offset += size;
3870 1.1 jmcneill }
3871 1.1 jmcneill
3872 1.1 jmcneill static int
3873 1.1 jmcneill mcx_add_pages(struct mcx_softc *sc, struct mcx_hwmem *mhm, uint16_t func_id)
3874 1.1 jmcneill {
3875 1.1 jmcneill struct mcx_dmamem mxm;
3876 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3877 1.1 jmcneill struct mcx_cmd_manage_pages_in *in;
3878 1.1 jmcneill struct mcx_cmd_manage_pages_out *out;
3879 1.1 jmcneill unsigned int paslen, nmb, i, j, npages;
3880 1.1 jmcneill struct bus_dma_iter iter;
3881 1.1 jmcneill uint64_t *pas;
3882 1.1 jmcneill uint8_t status;
3883 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
3884 1.1 jmcneill int error;
3885 1.1 jmcneill
3886 1.1 jmcneill npages = mhm->mhm_npages;
3887 1.1 jmcneill
3888 1.1 jmcneill paslen = sizeof(*pas) * npages;
3889 1.1 jmcneill nmb = howmany(paslen, MCX_CMDQ_MAILBOX_DATASIZE);
3890 1.1 jmcneill
3891 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3892 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + paslen, sizeof(*out), token);
3893 1.1 jmcneill
3894 1.1 jmcneill in = mcx_cmdq_in(cqe);
3895 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_MANAGE_PAGES);
3896 1.1 jmcneill in->cmd_op_mod = htobe16(MCX_CMD_MANAGE_PAGES_ALLOC_SUCCESS);
3897 1.1 jmcneill in->cmd_func_id = func_id;
3898 1.1 jmcneill be32enc(&in->cmd_input_num_entries, npages);
3899 1.1 jmcneill
3900 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, nmb,
3901 1.1 jmcneill &cqe->cq_input_ptr, token) != 0) {
3902 1.1 jmcneill printf(", unable to allocate manage pages mailboxen\n");
3903 1.1 jmcneill return (-1);
3904 1.1 jmcneill }
3905 1.1 jmcneill
3906 1.1 jmcneill bus_dma_iter_init(&iter, mhm->mhm_map);
3907 1.1 jmcneill for (i = 0; i < nmb; i++) {
3908 1.1 jmcneill unsigned int lim;
3909 1.1 jmcneill
3910 1.1 jmcneill pas = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, i));
3911 1.1 jmcneill lim = uimin(MCX_CMDQ_MAILBOX_DATASIZE / sizeof(*pas), npages);
3912 1.1 jmcneill
3913 1.1 jmcneill for (j = 0; j < lim; j++) {
3914 1.1 jmcneill be64enc(&pas[j], bus_dma_iter_addr(&iter));
3915 1.1 jmcneill bus_dma_iter_add(&iter, MCX_PAGE_SIZE);
3916 1.1 jmcneill }
3917 1.1 jmcneill
3918 1.1 jmcneill npages -= lim;
3919 1.1 jmcneill }
3920 1.1 jmcneill
3921 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, nmb);
3922 1.1 jmcneill
3923 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
3924 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
3925 1.1 jmcneill if (error != 0) {
3926 1.1 jmcneill printf(", manage pages timeout\n");
3927 1.1 jmcneill goto free;
3928 1.1 jmcneill }
3929 1.1 jmcneill error = mcx_cmdq_verify(cqe);
3930 1.1 jmcneill if (error != 0) {
3931 1.1 jmcneill printf(", manage pages reply corrupt\n");
3932 1.1 jmcneill goto free;
3933 1.1 jmcneill }
3934 1.1 jmcneill
3935 1.1 jmcneill status = cqe->cq_output_data[0];
3936 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
3937 1.1 jmcneill printf(", manage pages failed (%x)\n", status);
3938 1.1 jmcneill error = -1;
3939 1.1 jmcneill goto free;
3940 1.1 jmcneill }
3941 1.1 jmcneill
3942 1.1 jmcneill free:
3943 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
3944 1.1 jmcneill
3945 1.1 jmcneill return (error);
3946 1.1 jmcneill }
3947 1.1 jmcneill
3948 1.1 jmcneill static int
3949 1.1 jmcneill mcx_pages(struct mcx_softc *sc, struct mcx_hwmem *mhm, uint16_t type)
3950 1.1 jmcneill {
3951 1.15 jmcneill int32_t npages;
3952 1.1 jmcneill uint16_t func_id;
3953 1.1 jmcneill
3954 1.1 jmcneill if (mcx_query_pages(sc, type, &npages, &func_id) != 0) {
3955 1.1 jmcneill /* error printed by mcx_query_pages */
3956 1.1 jmcneill return (-1);
3957 1.1 jmcneill }
3958 1.1 jmcneill
3959 1.15 jmcneill if (npages < 1)
3960 1.1 jmcneill return (0);
3961 1.1 jmcneill
3962 1.1 jmcneill if (mcx_hwmem_alloc(sc, mhm, npages) != 0) {
3963 1.1 jmcneill printf(", unable to allocate hwmem\n");
3964 1.1 jmcneill return (-1);
3965 1.1 jmcneill }
3966 1.1 jmcneill
3967 1.1 jmcneill if (mcx_add_pages(sc, mhm, func_id) != 0) {
3968 1.1 jmcneill printf(", unable to add hwmem\n");
3969 1.1 jmcneill goto free;
3970 1.1 jmcneill }
3971 1.1 jmcneill
3972 1.1 jmcneill return (0);
3973 1.1 jmcneill
3974 1.1 jmcneill free:
3975 1.1 jmcneill mcx_hwmem_free(sc, mhm);
3976 1.1 jmcneill
3977 1.1 jmcneill return (-1);
3978 1.1 jmcneill }
3979 1.1 jmcneill
3980 1.1 jmcneill static int
3981 1.1 jmcneill mcx_hca_max_caps(struct mcx_softc *sc)
3982 1.1 jmcneill {
3983 1.1 jmcneill struct mcx_dmamem mxm;
3984 1.1 jmcneill struct mcx_cmdq_entry *cqe;
3985 1.1 jmcneill struct mcx_cmd_query_hca_cap_in *in;
3986 1.1 jmcneill struct mcx_cmd_query_hca_cap_out *out;
3987 1.1 jmcneill struct mcx_cmdq_mailbox *mb;
3988 1.1 jmcneill struct mcx_cap_device *hca;
3989 1.1 jmcneill uint8_t status;
3990 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
3991 1.1 jmcneill int error;
3992 1.1 jmcneill
3993 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
3994 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + MCX_HCA_CAP_LEN,
3995 1.1 jmcneill token);
3996 1.1 jmcneill
3997 1.1 jmcneill in = mcx_cmdq_in(cqe);
3998 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_HCA_CAP);
3999 1.1 jmcneill in->cmd_op_mod = htobe16(MCX_CMD_QUERY_HCA_CAP_MAX |
4000 1.1 jmcneill MCX_CMD_QUERY_HCA_CAP_DEVICE);
4001 1.1 jmcneill
4002 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, MCX_HCA_CAP_NMAILBOXES,
4003 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
4004 1.1 jmcneill printf(", unable to allocate query hca caps mailboxen\n");
4005 1.1 jmcneill return (-1);
4006 1.1 jmcneill }
4007 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, MCX_HCA_CAP_NMAILBOXES);
4008 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_PRERW);
4009 1.1 jmcneill
4010 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4011 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4012 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_POSTRW);
4013 1.1 jmcneill
4014 1.1 jmcneill if (error != 0) {
4015 1.1 jmcneill printf(", query hca caps timeout\n");
4016 1.1 jmcneill goto free;
4017 1.1 jmcneill }
4018 1.1 jmcneill error = mcx_cmdq_verify(cqe);
4019 1.1 jmcneill if (error != 0) {
4020 1.1 jmcneill printf(", query hca caps reply corrupt\n");
4021 1.1 jmcneill goto free;
4022 1.1 jmcneill }
4023 1.1 jmcneill
4024 1.1 jmcneill status = cqe->cq_output_data[0];
4025 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
4026 1.1 jmcneill printf(", query hca caps failed (%x)\n", status);
4027 1.1 jmcneill error = -1;
4028 1.1 jmcneill goto free;
4029 1.1 jmcneill }
4030 1.1 jmcneill
4031 1.1 jmcneill mb = mcx_cq_mbox(&mxm, 0);
4032 1.1 jmcneill hca = mcx_cq_mbox_data(mb);
4033 1.1 jmcneill
4034 1.15 jmcneill if ((hca->port_type & MCX_CAP_DEVICE_PORT_TYPE)
4035 1.15 jmcneill != MCX_CAP_DEVICE_PORT_TYPE_ETH) {
4036 1.15 jmcneill printf(", not in ethernet mode\n");
4037 1.15 jmcneill error = -1;
4038 1.15 jmcneill goto free;
4039 1.15 jmcneill }
4040 1.1 jmcneill if (hca->log_pg_sz > PAGE_SHIFT) {
4041 1.1 jmcneill printf(", minimum system page shift %u is too large\n",
4042 1.1 jmcneill hca->log_pg_sz);
4043 1.1 jmcneill error = -1;
4044 1.1 jmcneill goto free;
4045 1.1 jmcneill }
4046 1.1 jmcneill /*
4047 1.1 jmcneill * blueflame register is split into two buffers, and we must alternate
4048 1.1 jmcneill * between the two of them.
4049 1.1 jmcneill */
4050 1.1 jmcneill sc->sc_bf_size = (1 << hca->log_bf_reg_size) / 2;
4051 1.15 jmcneill sc->sc_max_rqt_size = (1 << hca->log_max_rqt_size);
4052 1.15 jmcneill
4053 1.15 jmcneill if (hca->local_ca_ack_delay & MCX_CAP_DEVICE_MCAM_REG)
4054 1.15 jmcneill sc->sc_mcam_reg = 1;
4055 1.15 jmcneill
4056 1.15 jmcneill sc->sc_mhz = be32dec(&hca->device_frequency_mhz);
4057 1.15 jmcneill sc->sc_khz = be32dec(&hca->device_frequency_khz);
4058 1.1 jmcneill
4059 1.1 jmcneill free:
4060 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4061 1.1 jmcneill
4062 1.1 jmcneill return (error);
4063 1.1 jmcneill }
4064 1.1 jmcneill
4065 1.1 jmcneill static int
4066 1.1 jmcneill mcx_hca_set_caps(struct mcx_softc *sc)
4067 1.1 jmcneill {
4068 1.1 jmcneill struct mcx_dmamem mxm;
4069 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4070 1.1 jmcneill struct mcx_cmd_query_hca_cap_in *in;
4071 1.1 jmcneill struct mcx_cmd_query_hca_cap_out *out;
4072 1.1 jmcneill struct mcx_cmdq_mailbox *mb;
4073 1.1 jmcneill struct mcx_cap_device *hca;
4074 1.1 jmcneill uint8_t status;
4075 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
4076 1.1 jmcneill int error;
4077 1.1 jmcneill
4078 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4079 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + MCX_HCA_CAP_LEN,
4080 1.1 jmcneill token);
4081 1.1 jmcneill
4082 1.1 jmcneill in = mcx_cmdq_in(cqe);
4083 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_HCA_CAP);
4084 1.1 jmcneill in->cmd_op_mod = htobe16(MCX_CMD_QUERY_HCA_CAP_CURRENT |
4085 1.1 jmcneill MCX_CMD_QUERY_HCA_CAP_DEVICE);
4086 1.1 jmcneill
4087 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, MCX_HCA_CAP_NMAILBOXES,
4088 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
4089 1.1 jmcneill printf(", unable to allocate manage pages mailboxen\n");
4090 1.1 jmcneill return (-1);
4091 1.1 jmcneill }
4092 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, MCX_HCA_CAP_NMAILBOXES);
4093 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_PRERW);
4094 1.1 jmcneill
4095 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4096 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4097 1.1 jmcneill mcx_cmdq_mboxes_sync(sc, &mxm, BUS_DMASYNC_POSTRW);
4098 1.1 jmcneill
4099 1.1 jmcneill if (error != 0) {
4100 1.1 jmcneill printf(", query hca caps timeout\n");
4101 1.1 jmcneill goto free;
4102 1.1 jmcneill }
4103 1.1 jmcneill error = mcx_cmdq_verify(cqe);
4104 1.1 jmcneill if (error != 0) {
4105 1.1 jmcneill printf(", query hca caps reply corrupt\n");
4106 1.1 jmcneill goto free;
4107 1.1 jmcneill }
4108 1.1 jmcneill
4109 1.1 jmcneill status = cqe->cq_output_data[0];
4110 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
4111 1.1 jmcneill printf(", query hca caps failed (%x)\n", status);
4112 1.1 jmcneill error = -1;
4113 1.1 jmcneill goto free;
4114 1.1 jmcneill }
4115 1.1 jmcneill
4116 1.1 jmcneill mb = mcx_cq_mbox(&mxm, 0);
4117 1.1 jmcneill hca = mcx_cq_mbox_data(mb);
4118 1.1 jmcneill
4119 1.1 jmcneill hca->log_pg_sz = PAGE_SHIFT;
4120 1.1 jmcneill
4121 1.1 jmcneill free:
4122 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4123 1.1 jmcneill
4124 1.1 jmcneill return (error);
4125 1.1 jmcneill }
4126 1.1 jmcneill
4127 1.1 jmcneill
4128 1.1 jmcneill static int
4129 1.1 jmcneill mcx_init_hca(struct mcx_softc *sc)
4130 1.1 jmcneill {
4131 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4132 1.1 jmcneill struct mcx_cmd_init_hca_in *in;
4133 1.1 jmcneill struct mcx_cmd_init_hca_out *out;
4134 1.1 jmcneill int error;
4135 1.1 jmcneill uint8_t status;
4136 1.1 jmcneill
4137 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4138 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
4139 1.1 jmcneill
4140 1.1 jmcneill in = mcx_cmdq_in(cqe);
4141 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_INIT_HCA);
4142 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4143 1.1 jmcneill
4144 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4145 1.1 jmcneill
4146 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4147 1.1 jmcneill if (error != 0) {
4148 1.1 jmcneill printf(", hca init timeout\n");
4149 1.1 jmcneill return (-1);
4150 1.1 jmcneill }
4151 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4152 1.1 jmcneill printf(", hca init command corrupt\n");
4153 1.1 jmcneill return (-1);
4154 1.1 jmcneill }
4155 1.1 jmcneill
4156 1.1 jmcneill status = cqe->cq_output_data[0];
4157 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
4158 1.1 jmcneill printf(", hca init failed (%x)\n", status);
4159 1.1 jmcneill return (-1);
4160 1.1 jmcneill }
4161 1.1 jmcneill
4162 1.1 jmcneill return (0);
4163 1.1 jmcneill }
4164 1.1 jmcneill
4165 1.1 jmcneill static int
4166 1.1 jmcneill mcx_set_driver_version(struct mcx_softc *sc)
4167 1.1 jmcneill {
4168 1.1 jmcneill struct mcx_dmamem mxm;
4169 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4170 1.1 jmcneill struct mcx_cmd_set_driver_version_in *in;
4171 1.1 jmcneill struct mcx_cmd_set_driver_version_out *out;
4172 1.1 jmcneill int error;
4173 1.1 jmcneill int token;
4174 1.1 jmcneill uint8_t status;
4175 1.1 jmcneill
4176 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4177 1.1 jmcneill token = mcx_cmdq_token(sc);
4178 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) +
4179 1.1 jmcneill sizeof(struct mcx_cmd_set_driver_version), sizeof(*out), token);
4180 1.1 jmcneill
4181 1.1 jmcneill in = mcx_cmdq_in(cqe);
4182 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_SET_DRIVER_VERSION);
4183 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4184 1.1 jmcneill
4185 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
4186 1.1 jmcneill &cqe->cq_input_ptr, token) != 0) {
4187 1.1 jmcneill printf(", unable to allocate set driver version mailboxen\n");
4188 1.1 jmcneill return (-1);
4189 1.1 jmcneill }
4190 1.1 jmcneill strlcpy(mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)),
4191 1.1 jmcneill "OpenBSD,mcx,1.000.000000", MCX_CMDQ_MAILBOX_DATASIZE);
4192 1.1 jmcneill
4193 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
4194 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4195 1.1 jmcneill
4196 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4197 1.1 jmcneill if (error != 0) {
4198 1.1 jmcneill printf(", set driver version timeout\n");
4199 1.1 jmcneill goto free;
4200 1.1 jmcneill }
4201 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4202 1.1 jmcneill printf(", set driver version command corrupt\n");
4203 1.1 jmcneill goto free;
4204 1.1 jmcneill }
4205 1.1 jmcneill
4206 1.1 jmcneill status = cqe->cq_output_data[0];
4207 1.1 jmcneill if (status != MCX_CQ_STATUS_OK) {
4208 1.1 jmcneill printf(", set driver version failed (%x)\n", status);
4209 1.1 jmcneill error = -1;
4210 1.1 jmcneill goto free;
4211 1.1 jmcneill }
4212 1.1 jmcneill
4213 1.1 jmcneill free:
4214 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4215 1.1 jmcneill
4216 1.1 jmcneill return (error);
4217 1.1 jmcneill }
4218 1.1 jmcneill
4219 1.1 jmcneill static int
4220 1.1 jmcneill mcx_iff(struct mcx_softc *sc)
4221 1.1 jmcneill {
4222 1.1 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
4223 1.1 jmcneill struct mcx_dmamem mxm;
4224 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4225 1.1 jmcneill struct mcx_cmd_modify_nic_vport_context_in *in;
4226 1.1 jmcneill struct mcx_cmd_modify_nic_vport_context_out *out;
4227 1.1 jmcneill struct mcx_nic_vport_ctx *ctx;
4228 1.1 jmcneill int error;
4229 1.1 jmcneill int token;
4230 1.1 jmcneill int insize;
4231 1.15 jmcneill uint32_t dest;
4232 1.15 jmcneill
4233 1.15 jmcneill dest = MCX_FLOW_CONTEXT_DEST_TYPE_TABLE |
4234 1.15 jmcneill sc->sc_rss_flow_table_id;
4235 1.1 jmcneill
4236 1.1 jmcneill /* enable or disable the promisc flow */
4237 1.1 jmcneill if (ISSET(ifp->if_flags, IFF_PROMISC)) {
4238 1.1 jmcneill if (sc->sc_promisc_flow_enabled == 0) {
4239 1.15 jmcneill mcx_set_flow_table_entry_mac(sc,
4240 1.15 jmcneill MCX_FLOW_GROUP_PROMISC, 0, NULL, dest);
4241 1.1 jmcneill sc->sc_promisc_flow_enabled = 1;
4242 1.1 jmcneill }
4243 1.1 jmcneill } else if (sc->sc_promisc_flow_enabled != 0) {
4244 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_PROMISC, 0);
4245 1.1 jmcneill sc->sc_promisc_flow_enabled = 0;
4246 1.1 jmcneill }
4247 1.1 jmcneill
4248 1.1 jmcneill /* enable or disable the all-multicast flow */
4249 1.1 jmcneill if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
4250 1.1 jmcneill if (sc->sc_allmulti_flow_enabled == 0) {
4251 1.1 jmcneill uint8_t mcast[ETHER_ADDR_LEN];
4252 1.1 jmcneill
4253 1.1 jmcneill memset(mcast, 0, sizeof(mcast));
4254 1.1 jmcneill mcast[0] = 0x01;
4255 1.15 jmcneill mcx_set_flow_table_entry_mac(sc,
4256 1.15 jmcneill MCX_FLOW_GROUP_ALLMULTI, 0, mcast, dest);
4257 1.1 jmcneill sc->sc_allmulti_flow_enabled = 1;
4258 1.1 jmcneill }
4259 1.1 jmcneill } else if (sc->sc_allmulti_flow_enabled != 0) {
4260 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_ALLMULTI, 0);
4261 1.1 jmcneill sc->sc_allmulti_flow_enabled = 0;
4262 1.1 jmcneill }
4263 1.1 jmcneill
4264 1.1 jmcneill insize = sizeof(struct mcx_nic_vport_ctx) + 240;
4265 1.1 jmcneill
4266 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4267 1.1 jmcneill token = mcx_cmdq_token(sc);
4268 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + insize, sizeof(*out), token);
4269 1.1 jmcneill
4270 1.1 jmcneill in = mcx_cmdq_in(cqe);
4271 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_MODIFY_NIC_VPORT_CONTEXT);
4272 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4273 1.1 jmcneill in->cmd_field_select = htobe32(
4274 1.1 jmcneill MCX_CMD_MODIFY_NIC_VPORT_CONTEXT_FIELD_PROMISC |
4275 1.1 jmcneill MCX_CMD_MODIFY_NIC_VPORT_CONTEXT_FIELD_MTU);
4276 1.1 jmcneill
4277 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1, &cqe->cq_input_ptr, token) != 0) {
4278 1.15 jmcneill printf(", unable to allocate modify "
4279 1.15 jmcneill "nic vport context mailboxen\n");
4280 1.1 jmcneill return (-1);
4281 1.1 jmcneill }
4282 1.1 jmcneill ctx = (struct mcx_nic_vport_ctx *)
4283 1.1 jmcneill (((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0))) + 240);
4284 1.1 jmcneill ctx->vp_mtu = htobe32(sc->sc_hardmtu);
4285 1.1 jmcneill /*
4286 1.15 jmcneill * always leave promisc-all enabled on the vport since we
4287 1.15 jmcneill * can't give it a vlan list, and we're already doing multicast
4288 1.15 jmcneill * filtering in the flow table.
4289 1.1 jmcneill */
4290 1.1 jmcneill ctx->vp_flags = htobe16(MCX_NIC_VPORT_CTX_PROMISC_ALL);
4291 1.1 jmcneill
4292 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
4293 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4294 1.1 jmcneill
4295 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4296 1.1 jmcneill if (error != 0) {
4297 1.1 jmcneill printf(", modify nic vport context timeout\n");
4298 1.1 jmcneill goto free;
4299 1.1 jmcneill }
4300 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4301 1.1 jmcneill printf(", modify nic vport context command corrupt\n");
4302 1.1 jmcneill goto free;
4303 1.1 jmcneill }
4304 1.1 jmcneill
4305 1.1 jmcneill out = mcx_cmdq_out(cqe);
4306 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4307 1.1 jmcneill printf(", modify nic vport context failed (%x, %x)\n",
4308 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4309 1.1 jmcneill error = -1;
4310 1.1 jmcneill goto free;
4311 1.1 jmcneill }
4312 1.1 jmcneill
4313 1.1 jmcneill free:
4314 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4315 1.1 jmcneill
4316 1.1 jmcneill return (error);
4317 1.1 jmcneill }
4318 1.1 jmcneill
4319 1.1 jmcneill static int
4320 1.15 jmcneill mcx_alloc_uar(struct mcx_softc *sc, int *uar)
4321 1.1 jmcneill {
4322 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4323 1.1 jmcneill struct mcx_cmd_alloc_uar_in *in;
4324 1.1 jmcneill struct mcx_cmd_alloc_uar_out *out;
4325 1.1 jmcneill int error;
4326 1.1 jmcneill
4327 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4328 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
4329 1.1 jmcneill
4330 1.1 jmcneill in = mcx_cmdq_in(cqe);
4331 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ALLOC_UAR);
4332 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4333 1.1 jmcneill
4334 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4335 1.1 jmcneill
4336 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4337 1.1 jmcneill if (error != 0) {
4338 1.1 jmcneill printf(", alloc uar timeout\n");
4339 1.1 jmcneill return (-1);
4340 1.1 jmcneill }
4341 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4342 1.1 jmcneill printf(", alloc uar command corrupt\n");
4343 1.1 jmcneill return (-1);
4344 1.1 jmcneill }
4345 1.1 jmcneill
4346 1.1 jmcneill out = mcx_cmdq_out(cqe);
4347 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4348 1.1 jmcneill printf(", alloc uar failed (%x)\n", out->cmd_status);
4349 1.1 jmcneill return (-1);
4350 1.1 jmcneill }
4351 1.1 jmcneill
4352 1.15 jmcneill *uar = mcx_get_id(out->cmd_uar);
4353 1.1 jmcneill return (0);
4354 1.1 jmcneill }
4355 1.1 jmcneill
4356 1.1 jmcneill static int
4357 1.15 jmcneill mcx_create_eq(struct mcx_softc *sc, struct mcx_eq *eq, int uar,
4358 1.15 jmcneill uint64_t events, int vector)
4359 1.1 jmcneill {
4360 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4361 1.1 jmcneill struct mcx_dmamem mxm;
4362 1.1 jmcneill struct mcx_cmd_create_eq_in *in;
4363 1.1 jmcneill struct mcx_cmd_create_eq_mb_in *mbin;
4364 1.1 jmcneill struct mcx_cmd_create_eq_out *out;
4365 1.1 jmcneill struct mcx_eq_entry *eqe;
4366 1.1 jmcneill int error;
4367 1.1 jmcneill uint64_t *pas;
4368 1.1 jmcneill int insize, npages, paslen, i, token;
4369 1.1 jmcneill
4370 1.15 jmcneill eq->eq_cons = 0;
4371 1.1 jmcneill
4372 1.1 jmcneill npages = howmany((1 << MCX_LOG_EQ_SIZE) * sizeof(struct mcx_eq_entry),
4373 1.1 jmcneill MCX_PAGE_SIZE);
4374 1.1 jmcneill paslen = npages * sizeof(*pas);
4375 1.1 jmcneill insize = sizeof(struct mcx_cmd_create_eq_mb_in) + paslen;
4376 1.1 jmcneill
4377 1.15 jmcneill if (mcx_dmamem_alloc(sc, &eq->eq_mem, npages * MCX_PAGE_SIZE,
4378 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
4379 1.1 jmcneill printf(", unable to allocate event queue memory\n");
4380 1.1 jmcneill return (-1);
4381 1.1 jmcneill }
4382 1.1 jmcneill
4383 1.15 jmcneill eqe = (struct mcx_eq_entry *)MCX_DMA_KVA(&eq->eq_mem);
4384 1.1 jmcneill for (i = 0; i < (1 << MCX_LOG_EQ_SIZE); i++) {
4385 1.1 jmcneill eqe[i].eq_owner = MCX_EQ_ENTRY_OWNER_INIT;
4386 1.1 jmcneill }
4387 1.1 jmcneill
4388 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4389 1.1 jmcneill token = mcx_cmdq_token(sc);
4390 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + insize, sizeof(*out), token);
4391 1.1 jmcneill
4392 1.1 jmcneill in = mcx_cmdq_in(cqe);
4393 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_EQ);
4394 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4395 1.1 jmcneill
4396 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm,
4397 1.15 jmcneill howmany(insize, MCX_CMDQ_MAILBOX_DATASIZE),
4398 1.1 jmcneill &cqe->cq_input_ptr, token) != 0) {
4399 1.1 jmcneill printf(", unable to allocate create eq mailboxen\n");
4400 1.15 jmcneill goto free_eq;
4401 1.1 jmcneill }
4402 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
4403 1.1 jmcneill mbin->cmd_eq_ctx.eq_uar_size = htobe32(
4404 1.15 jmcneill (MCX_LOG_EQ_SIZE << MCX_EQ_CTX_LOG_EQ_SIZE_SHIFT) | uar);
4405 1.15 jmcneill mbin->cmd_eq_ctx.eq_intr = vector;
4406 1.15 jmcneill mbin->cmd_event_bitmask = htobe64(events);
4407 1.15 jmcneill
4408 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
4409 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_PREREAD);
4410 1.1 jmcneill
4411 1.1 jmcneill /* physical addresses follow the mailbox in data */
4412 1.15 jmcneill mcx_cmdq_mboxes_pas(&mxm, sizeof(*mbin), npages, &eq->eq_mem);
4413 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, howmany(insize, MCX_CMDQ_MAILBOX_DATASIZE));
4414 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4415 1.1 jmcneill
4416 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4417 1.1 jmcneill if (error != 0) {
4418 1.1 jmcneill printf(", create eq timeout\n");
4419 1.15 jmcneill goto free_mxm;
4420 1.1 jmcneill }
4421 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4422 1.1 jmcneill printf(", create eq command corrupt\n");
4423 1.15 jmcneill goto free_mxm;
4424 1.1 jmcneill }
4425 1.1 jmcneill
4426 1.1 jmcneill out = mcx_cmdq_out(cqe);
4427 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4428 1.1 jmcneill printf(", create eq failed (%x, %x)\n", out->cmd_status,
4429 1.1 jmcneill be32toh(out->cmd_syndrome));
4430 1.15 jmcneill goto free_mxm;
4431 1.1 jmcneill }
4432 1.1 jmcneill
4433 1.15 jmcneill eq->eq_n = mcx_get_id(out->cmd_eqn);
4434 1.15 jmcneill
4435 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
4436 1.15 jmcneill
4437 1.15 jmcneill mcx_arm_eq(sc, eq, uar);
4438 1.15 jmcneill
4439 1.15 jmcneill return (0);
4440 1.15 jmcneill
4441 1.15 jmcneill free_mxm:
4442 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
4443 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_POSTREAD);
4444 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4445 1.15 jmcneill free_eq:
4446 1.15 jmcneill mcx_dmamem_free(sc, &eq->eq_mem);
4447 1.15 jmcneill return (-1);
4448 1.1 jmcneill }
4449 1.1 jmcneill
4450 1.1 jmcneill static int
4451 1.1 jmcneill mcx_alloc_pd(struct mcx_softc *sc)
4452 1.1 jmcneill {
4453 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4454 1.1 jmcneill struct mcx_cmd_alloc_pd_in *in;
4455 1.1 jmcneill struct mcx_cmd_alloc_pd_out *out;
4456 1.1 jmcneill int error;
4457 1.1 jmcneill
4458 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4459 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
4460 1.1 jmcneill
4461 1.1 jmcneill in = mcx_cmdq_in(cqe);
4462 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ALLOC_PD);
4463 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4464 1.1 jmcneill
4465 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4466 1.1 jmcneill
4467 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4468 1.1 jmcneill if (error != 0) {
4469 1.1 jmcneill printf(", alloc pd timeout\n");
4470 1.1 jmcneill return (-1);
4471 1.1 jmcneill }
4472 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4473 1.1 jmcneill printf(", alloc pd command corrupt\n");
4474 1.1 jmcneill return (-1);
4475 1.1 jmcneill }
4476 1.1 jmcneill
4477 1.1 jmcneill out = mcx_cmdq_out(cqe);
4478 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4479 1.1 jmcneill printf(", alloc pd failed (%x)\n", out->cmd_status);
4480 1.1 jmcneill return (-1);
4481 1.1 jmcneill }
4482 1.1 jmcneill
4483 1.13 jmcneill sc->sc_pd = mcx_get_id(out->cmd_pd);
4484 1.1 jmcneill return (0);
4485 1.1 jmcneill }
4486 1.1 jmcneill
4487 1.1 jmcneill static int
4488 1.1 jmcneill mcx_alloc_tdomain(struct mcx_softc *sc)
4489 1.1 jmcneill {
4490 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4491 1.1 jmcneill struct mcx_cmd_alloc_td_in *in;
4492 1.1 jmcneill struct mcx_cmd_alloc_td_out *out;
4493 1.1 jmcneill int error;
4494 1.1 jmcneill
4495 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4496 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
4497 1.1 jmcneill
4498 1.1 jmcneill in = mcx_cmdq_in(cqe);
4499 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ALLOC_TRANSPORT_DOMAIN);
4500 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4501 1.1 jmcneill
4502 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4503 1.1 jmcneill
4504 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4505 1.1 jmcneill if (error != 0) {
4506 1.1 jmcneill printf(", alloc transport domain timeout\n");
4507 1.1 jmcneill return (-1);
4508 1.1 jmcneill }
4509 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4510 1.1 jmcneill printf(", alloc transport domain command corrupt\n");
4511 1.1 jmcneill return (-1);
4512 1.1 jmcneill }
4513 1.1 jmcneill
4514 1.1 jmcneill out = mcx_cmdq_out(cqe);
4515 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4516 1.1 jmcneill printf(", alloc transport domain failed (%x)\n",
4517 1.1 jmcneill out->cmd_status);
4518 1.1 jmcneill return (-1);
4519 1.1 jmcneill }
4520 1.1 jmcneill
4521 1.13 jmcneill sc->sc_tdomain = mcx_get_id(out->cmd_tdomain);
4522 1.1 jmcneill return (0);
4523 1.1 jmcneill }
4524 1.1 jmcneill
4525 1.1 jmcneill static int
4526 1.1 jmcneill mcx_query_nic_vport_context(struct mcx_softc *sc, uint8_t *enaddr)
4527 1.1 jmcneill {
4528 1.1 jmcneill struct mcx_dmamem mxm;
4529 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4530 1.1 jmcneill struct mcx_cmd_query_nic_vport_context_in *in;
4531 1.1 jmcneill struct mcx_cmd_query_nic_vport_context_out *out;
4532 1.1 jmcneill struct mcx_nic_vport_ctx *ctx;
4533 1.1 jmcneill uint8_t *addr;
4534 1.1 jmcneill int error, token, i;
4535 1.1 jmcneill
4536 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4537 1.1 jmcneill token = mcx_cmdq_token(sc);
4538 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*ctx), token);
4539 1.1 jmcneill
4540 1.1 jmcneill in = mcx_cmdq_in(cqe);
4541 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_NIC_VPORT_CONTEXT);
4542 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4543 1.1 jmcneill in->cmd_allowed_list_type = 0;
4544 1.1 jmcneill
4545 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
4546 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
4547 1.15 jmcneill printf(", unable to allocate "
4548 1.15 jmcneill "query nic vport context mailboxen\n");
4549 1.1 jmcneill return (-1);
4550 1.1 jmcneill }
4551 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
4552 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4553 1.1 jmcneill
4554 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4555 1.1 jmcneill if (error != 0) {
4556 1.1 jmcneill printf(", query nic vport context timeout\n");
4557 1.1 jmcneill goto free;
4558 1.1 jmcneill }
4559 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4560 1.1 jmcneill printf(", query nic vport context command corrupt\n");
4561 1.1 jmcneill goto free;
4562 1.1 jmcneill }
4563 1.1 jmcneill
4564 1.1 jmcneill out = mcx_cmdq_out(cqe);
4565 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4566 1.1 jmcneill printf(", query nic vport context failed (%x, %x)\n",
4567 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4568 1.1 jmcneill error = -1;
4569 1.1 jmcneill goto free;
4570 1.1 jmcneill }
4571 1.1 jmcneill
4572 1.15 jmcneill ctx = (struct mcx_nic_vport_ctx *)
4573 1.15 jmcneill mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
4574 1.1 jmcneill addr = (uint8_t *)&ctx->vp_perm_addr;
4575 1.1 jmcneill for (i = 0; i < ETHER_ADDR_LEN; i++) {
4576 1.1 jmcneill enaddr[i] = addr[i + 2];
4577 1.1 jmcneill }
4578 1.1 jmcneill free:
4579 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4580 1.1 jmcneill
4581 1.1 jmcneill return (error);
4582 1.1 jmcneill }
4583 1.1 jmcneill
4584 1.1 jmcneill static int
4585 1.1 jmcneill mcx_query_special_contexts(struct mcx_softc *sc)
4586 1.1 jmcneill {
4587 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4588 1.1 jmcneill struct mcx_cmd_query_special_ctx_in *in;
4589 1.1 jmcneill struct mcx_cmd_query_special_ctx_out *out;
4590 1.1 jmcneill int error;
4591 1.1 jmcneill
4592 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4593 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
4594 1.1 jmcneill
4595 1.1 jmcneill in = mcx_cmdq_in(cqe);
4596 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_SPECIAL_CONTEXTS);
4597 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4598 1.1 jmcneill
4599 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4600 1.1 jmcneill
4601 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4602 1.1 jmcneill if (error != 0) {
4603 1.1 jmcneill printf(", query special contexts timeout\n");
4604 1.1 jmcneill return (-1);
4605 1.1 jmcneill }
4606 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4607 1.1 jmcneill printf(", query special contexts command corrupt\n");
4608 1.1 jmcneill return (-1);
4609 1.1 jmcneill }
4610 1.1 jmcneill
4611 1.1 jmcneill out = mcx_cmdq_out(cqe);
4612 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4613 1.1 jmcneill printf(", query special contexts failed (%x)\n",
4614 1.1 jmcneill out->cmd_status);
4615 1.1 jmcneill return (-1);
4616 1.1 jmcneill }
4617 1.1 jmcneill
4618 1.1 jmcneill sc->sc_lkey = be32toh(out->cmd_resd_lkey);
4619 1.1 jmcneill return (0);
4620 1.1 jmcneill }
4621 1.1 jmcneill
4622 1.1 jmcneill static int
4623 1.1 jmcneill mcx_set_port_mtu(struct mcx_softc *sc, int mtu)
4624 1.1 jmcneill {
4625 1.1 jmcneill struct mcx_reg_pmtu pmtu;
4626 1.1 jmcneill int error;
4627 1.1 jmcneill
4628 1.1 jmcneill /* read max mtu */
4629 1.1 jmcneill memset(&pmtu, 0, sizeof(pmtu));
4630 1.1 jmcneill pmtu.rp_local_port = 1;
4631 1.1 jmcneill error = mcx_access_hca_reg(sc, MCX_REG_PMTU, MCX_REG_OP_READ, &pmtu,
4632 1.1 jmcneill sizeof(pmtu));
4633 1.1 jmcneill if (error != 0) {
4634 1.1 jmcneill printf(", unable to get port MTU\n");
4635 1.1 jmcneill return error;
4636 1.1 jmcneill }
4637 1.1 jmcneill
4638 1.1 jmcneill mtu = uimin(mtu, be16toh(pmtu.rp_max_mtu));
4639 1.1 jmcneill pmtu.rp_admin_mtu = htobe16(mtu);
4640 1.1 jmcneill error = mcx_access_hca_reg(sc, MCX_REG_PMTU, MCX_REG_OP_WRITE, &pmtu,
4641 1.1 jmcneill sizeof(pmtu));
4642 1.1 jmcneill if (error != 0) {
4643 1.1 jmcneill printf(", unable to set port MTU\n");
4644 1.1 jmcneill return error;
4645 1.1 jmcneill }
4646 1.1 jmcneill
4647 1.1 jmcneill sc->sc_hardmtu = mtu;
4648 1.15 jmcneill sc->sc_rxbufsz = roundup(mtu + ETHER_ALIGN, sizeof(long));
4649 1.1 jmcneill return 0;
4650 1.1 jmcneill }
4651 1.1 jmcneill
4652 1.1 jmcneill static int
4653 1.15 jmcneill mcx_create_cq(struct mcx_softc *sc, struct mcx_cq *cq, int uar, int db, int eqn)
4654 1.1 jmcneill {
4655 1.1 jmcneill struct mcx_cmdq_entry *cmde;
4656 1.1 jmcneill struct mcx_cq_entry *cqe;
4657 1.1 jmcneill struct mcx_dmamem mxm;
4658 1.1 jmcneill struct mcx_cmd_create_cq_in *in;
4659 1.1 jmcneill struct mcx_cmd_create_cq_mb_in *mbin;
4660 1.1 jmcneill struct mcx_cmd_create_cq_out *out;
4661 1.1 jmcneill int error;
4662 1.1 jmcneill uint64_t *pas;
4663 1.1 jmcneill int insize, npages, paslen, i, token;
4664 1.1 jmcneill
4665 1.15 jmcneill cq->cq_doorbell = MCX_CQ_DOORBELL_BASE + (MCX_CQ_DOORBELL_STRIDE * db);
4666 1.1 jmcneill
4667 1.1 jmcneill npages = howmany((1 << MCX_LOG_CQ_SIZE) * sizeof(struct mcx_cq_entry),
4668 1.1 jmcneill MCX_PAGE_SIZE);
4669 1.1 jmcneill paslen = npages * sizeof(*pas);
4670 1.1 jmcneill insize = sizeof(struct mcx_cmd_create_cq_mb_in) + paslen;
4671 1.1 jmcneill
4672 1.1 jmcneill if (mcx_dmamem_alloc(sc, &cq->cq_mem, npages * MCX_PAGE_SIZE,
4673 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
4674 1.1 jmcneill printf("%s: unable to allocate completion queue memory\n",
4675 1.1 jmcneill DEVNAME(sc));
4676 1.1 jmcneill return (-1);
4677 1.1 jmcneill }
4678 1.1 jmcneill cqe = MCX_DMA_KVA(&cq->cq_mem);
4679 1.1 jmcneill for (i = 0; i < (1 << MCX_LOG_CQ_SIZE); i++) {
4680 1.1 jmcneill cqe[i].cq_opcode_owner = MCX_CQ_ENTRY_FLAG_OWNER;
4681 1.1 jmcneill }
4682 1.1 jmcneill
4683 1.1 jmcneill cmde = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4684 1.1 jmcneill token = mcx_cmdq_token(sc);
4685 1.1 jmcneill mcx_cmdq_init(sc, cmde, sizeof(*in) + insize, sizeof(*out), token);
4686 1.1 jmcneill
4687 1.1 jmcneill in = mcx_cmdq_in(cmde);
4688 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_CQ);
4689 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4690 1.1 jmcneill
4691 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm,
4692 1.15 jmcneill howmany(insize, MCX_CMDQ_MAILBOX_DATASIZE),
4693 1.1 jmcneill &cmde->cq_input_ptr, token) != 0) {
4694 1.15 jmcneill printf("%s: unable to allocate create cq mailboxen\n",
4695 1.15 jmcneill DEVNAME(sc));
4696 1.15 jmcneill goto free_cq;
4697 1.1 jmcneill }
4698 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
4699 1.1 jmcneill mbin->cmd_cq_ctx.cq_uar_size = htobe32(
4700 1.15 jmcneill (MCX_LOG_CQ_SIZE << MCX_CQ_CTX_LOG_CQ_SIZE_SHIFT) | uar);
4701 1.1 jmcneill mbin->cmd_cq_ctx.cq_eqn = htobe32(eqn);
4702 1.1 jmcneill mbin->cmd_cq_ctx.cq_period_max_count = htobe32(
4703 1.1 jmcneill (MCX_CQ_MOD_PERIOD << MCX_CQ_CTX_PERIOD_SHIFT) |
4704 1.1 jmcneill MCX_CQ_MOD_COUNTER);
4705 1.1 jmcneill mbin->cmd_cq_ctx.cq_doorbell = htobe64(
4706 1.15 jmcneill MCX_DMA_DVA(&sc->sc_doorbell_mem) + cq->cq_doorbell);
4707 1.15 jmcneill
4708 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&cq->cq_mem),
4709 1.15 jmcneill 0, MCX_DMA_LEN(&cq->cq_mem), BUS_DMASYNC_PREREAD);
4710 1.1 jmcneill
4711 1.1 jmcneill /* physical addresses follow the mailbox in data */
4712 1.13 jmcneill mcx_cmdq_mboxes_pas(&mxm, sizeof(*mbin), npages, &cq->cq_mem);
4713 1.1 jmcneill mcx_cmdq_post(sc, cmde, 0);
4714 1.1 jmcneill
4715 1.1 jmcneill error = mcx_cmdq_poll(sc, cmde, 1000);
4716 1.1 jmcneill if (error != 0) {
4717 1.1 jmcneill printf("%s: create cq timeout\n", DEVNAME(sc));
4718 1.15 jmcneill goto free_mxm;
4719 1.1 jmcneill }
4720 1.1 jmcneill if (mcx_cmdq_verify(cmde) != 0) {
4721 1.1 jmcneill printf("%s: create cq command corrupt\n", DEVNAME(sc));
4722 1.15 jmcneill goto free_mxm;
4723 1.1 jmcneill }
4724 1.1 jmcneill
4725 1.1 jmcneill out = mcx_cmdq_out(cmde);
4726 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4727 1.1 jmcneill printf("%s: create cq failed (%x, %x)\n", DEVNAME(sc),
4728 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4729 1.15 jmcneill goto free_mxm;
4730 1.1 jmcneill }
4731 1.1 jmcneill
4732 1.13 jmcneill cq->cq_n = mcx_get_id(out->cmd_cqn);
4733 1.1 jmcneill cq->cq_cons = 0;
4734 1.1 jmcneill cq->cq_count = 0;
4735 1.1 jmcneill
4736 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4737 1.15 jmcneill
4738 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
4739 1.15 jmcneill cq->cq_doorbell, sizeof(struct mcx_cq_doorbell),
4740 1.15 jmcneill BUS_DMASYNC_PREWRITE);
4741 1.15 jmcneill
4742 1.15 jmcneill mcx_arm_cq(sc, cq, uar);
4743 1.15 jmcneill
4744 1.15 jmcneill return (0);
4745 1.15 jmcneill
4746 1.15 jmcneill free_mxm:
4747 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&cq->cq_mem),
4748 1.15 jmcneill 0, MCX_DMA_LEN(&cq->cq_mem), BUS_DMASYNC_POSTREAD);
4749 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
4750 1.15 jmcneill free_cq:
4751 1.15 jmcneill mcx_dmamem_free(sc, &cq->cq_mem);
4752 1.15 jmcneill return (-1);
4753 1.1 jmcneill }
4754 1.1 jmcneill
4755 1.1 jmcneill static int
4756 1.15 jmcneill mcx_destroy_cq(struct mcx_softc *sc, struct mcx_cq *cq)
4757 1.1 jmcneill {
4758 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4759 1.1 jmcneill struct mcx_cmd_destroy_cq_in *in;
4760 1.1 jmcneill struct mcx_cmd_destroy_cq_out *out;
4761 1.1 jmcneill int error;
4762 1.1 jmcneill int token;
4763 1.1 jmcneill
4764 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4765 1.1 jmcneill token = mcx_cmdq_token(sc);
4766 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
4767 1.1 jmcneill
4768 1.1 jmcneill in = mcx_cmdq_in(cqe);
4769 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_CQ);
4770 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4771 1.15 jmcneill in->cmd_cqn = htobe32(cq->cq_n);
4772 1.1 jmcneill
4773 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4774 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4775 1.1 jmcneill if (error != 0) {
4776 1.1 jmcneill printf("%s: destroy cq timeout\n", DEVNAME(sc));
4777 1.1 jmcneill return error;
4778 1.1 jmcneill }
4779 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4780 1.1 jmcneill printf("%s: destroy cq command corrupt\n", DEVNAME(sc));
4781 1.1 jmcneill return error;
4782 1.1 jmcneill }
4783 1.1 jmcneill
4784 1.1 jmcneill out = mcx_cmdq_out(cqe);
4785 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4786 1.1 jmcneill printf("%s: destroy cq failed (%x, %x)\n", DEVNAME(sc),
4787 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4788 1.1 jmcneill return -1;
4789 1.1 jmcneill }
4790 1.1 jmcneill
4791 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
4792 1.15 jmcneill cq->cq_doorbell, sizeof(struct mcx_cq_doorbell),
4793 1.15 jmcneill BUS_DMASYNC_POSTWRITE);
4794 1.15 jmcneill
4795 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&cq->cq_mem),
4796 1.15 jmcneill 0, MCX_DMA_LEN(&cq->cq_mem), BUS_DMASYNC_POSTREAD);
4797 1.15 jmcneill mcx_dmamem_free(sc, &cq->cq_mem);
4798 1.15 jmcneill
4799 1.15 jmcneill cq->cq_n = 0;
4800 1.15 jmcneill cq->cq_cons = 0;
4801 1.15 jmcneill cq->cq_count = 0;
4802 1.1 jmcneill return 0;
4803 1.1 jmcneill }
4804 1.1 jmcneill
4805 1.1 jmcneill static int
4806 1.15 jmcneill mcx_create_rq(struct mcx_softc *sc, struct mcx_rx *rx, int db, int cqn)
4807 1.1 jmcneill {
4808 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4809 1.1 jmcneill struct mcx_dmamem mxm;
4810 1.1 jmcneill struct mcx_cmd_create_rq_in *in;
4811 1.1 jmcneill struct mcx_cmd_create_rq_out *out;
4812 1.1 jmcneill struct mcx_rq_ctx *mbin;
4813 1.1 jmcneill int error;
4814 1.1 jmcneill uint64_t *pas;
4815 1.15 jmcneill uint32_t rq_flags;
4816 1.13 jmcneill int insize, npages, paslen, token;
4817 1.1 jmcneill
4818 1.15 jmcneill rx->rx_doorbell = MCX_WQ_DOORBELL_BASE +
4819 1.15 jmcneill (db * MCX_WQ_DOORBELL_STRIDE);
4820 1.15 jmcneill
4821 1.1 jmcneill npages = howmany((1 << MCX_LOG_RQ_SIZE) * sizeof(struct mcx_rq_entry),
4822 1.1 jmcneill MCX_PAGE_SIZE);
4823 1.1 jmcneill paslen = npages * sizeof(*pas);
4824 1.1 jmcneill insize = 0x10 + sizeof(struct mcx_rq_ctx) + paslen;
4825 1.1 jmcneill
4826 1.15 jmcneill if (mcx_dmamem_alloc(sc, &rx->rx_rq_mem, npages * MCX_PAGE_SIZE,
4827 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
4828 1.1 jmcneill printf("%s: unable to allocate receive queue memory\n",
4829 1.1 jmcneill DEVNAME(sc));
4830 1.1 jmcneill return (-1);
4831 1.1 jmcneill }
4832 1.1 jmcneill
4833 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4834 1.1 jmcneill token = mcx_cmdq_token(sc);
4835 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + insize, sizeof(*out), token);
4836 1.1 jmcneill
4837 1.1 jmcneill in = mcx_cmdq_in(cqe);
4838 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_RQ);
4839 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4840 1.1 jmcneill
4841 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm,
4842 1.15 jmcneill howmany(insize, MCX_CMDQ_MAILBOX_DATASIZE),
4843 1.1 jmcneill &cqe->cq_input_ptr, token) != 0) {
4844 1.1 jmcneill printf("%s: unable to allocate create rq mailboxen\n",
4845 1.1 jmcneill DEVNAME(sc));
4846 1.15 jmcneill goto free_rq;
4847 1.15 jmcneill }
4848 1.15 jmcneill mbin = (struct mcx_rq_ctx *)
4849 1.15 jmcneill (((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0))) + 0x10);
4850 1.15 jmcneill rq_flags = MCX_RQ_CTX_RLKEY;
4851 1.15 jmcneill mbin->rq_flags = htobe32(rq_flags);
4852 1.1 jmcneill mbin->rq_cqn = htobe32(cqn);
4853 1.1 jmcneill mbin->rq_wq.wq_type = MCX_WQ_CTX_TYPE_CYCLIC;
4854 1.1 jmcneill mbin->rq_wq.wq_pd = htobe32(sc->sc_pd);
4855 1.1 jmcneill mbin->rq_wq.wq_doorbell = htobe64(MCX_DMA_DVA(&sc->sc_doorbell_mem) +
4856 1.15 jmcneill rx->rx_doorbell);
4857 1.1 jmcneill mbin->rq_wq.wq_log_stride = htobe16(4);
4858 1.1 jmcneill mbin->rq_wq.wq_log_size = MCX_LOG_RQ_SIZE;
4859 1.1 jmcneill
4860 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&rx->rx_rq_mem),
4861 1.15 jmcneill 0, MCX_DMA_LEN(&rx->rx_rq_mem), BUS_DMASYNC_PREWRITE);
4862 1.15 jmcneill
4863 1.1 jmcneill /* physical addresses follow the mailbox in data */
4864 1.15 jmcneill mcx_cmdq_mboxes_pas(&mxm, sizeof(*mbin) + 0x10, npages, &rx->rx_rq_mem);
4865 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4866 1.1 jmcneill
4867 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4868 1.1 jmcneill if (error != 0) {
4869 1.1 jmcneill printf("%s: create rq timeout\n", DEVNAME(sc));
4870 1.15 jmcneill goto free_mxm;
4871 1.1 jmcneill }
4872 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4873 1.1 jmcneill printf("%s: create rq command corrupt\n", DEVNAME(sc));
4874 1.15 jmcneill goto free_mxm;
4875 1.1 jmcneill }
4876 1.1 jmcneill
4877 1.1 jmcneill out = mcx_cmdq_out(cqe);
4878 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4879 1.1 jmcneill printf("%s: create rq failed (%x, %x)\n", DEVNAME(sc),
4880 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4881 1.15 jmcneill goto free_mxm;
4882 1.1 jmcneill }
4883 1.1 jmcneill
4884 1.15 jmcneill rx->rx_rqn = mcx_get_id(out->cmd_rqn);
4885 1.1 jmcneill
4886 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
4887 1.15 jmcneill
4888 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
4889 1.15 jmcneill rx->rx_doorbell, sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
4890 1.15 jmcneill
4891 1.15 jmcneill return (0);
4892 1.1 jmcneill
4893 1.15 jmcneill free_mxm:
4894 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&rx->rx_rq_mem),
4895 1.15 jmcneill 0, MCX_DMA_LEN(&rx->rx_rq_mem), BUS_DMASYNC_POSTWRITE);
4896 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4897 1.15 jmcneill free_rq:
4898 1.15 jmcneill mcx_dmamem_free(sc, &rx->rx_rq_mem);
4899 1.15 jmcneill return (-1);
4900 1.1 jmcneill }
4901 1.1 jmcneill
4902 1.1 jmcneill static int
4903 1.15 jmcneill mcx_ready_rq(struct mcx_softc *sc, struct mcx_rx *rx)
4904 1.1 jmcneill {
4905 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4906 1.1 jmcneill struct mcx_dmamem mxm;
4907 1.1 jmcneill struct mcx_cmd_modify_rq_in *in;
4908 1.1 jmcneill struct mcx_cmd_modify_rq_mb_in *mbin;
4909 1.1 jmcneill struct mcx_cmd_modify_rq_out *out;
4910 1.1 jmcneill int error;
4911 1.1 jmcneill int token;
4912 1.1 jmcneill
4913 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4914 1.1 jmcneill token = mcx_cmdq_token(sc);
4915 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
4916 1.15 jmcneill sizeof(*out), token);
4917 1.1 jmcneill
4918 1.1 jmcneill in = mcx_cmdq_in(cqe);
4919 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_MODIFY_RQ);
4920 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4921 1.15 jmcneill in->cmd_rq_state = htobe32((MCX_QUEUE_STATE_RST << 28) | rx->rx_rqn);
4922 1.1 jmcneill
4923 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
4924 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
4925 1.15 jmcneill printf("%s: unable to allocate modify rq mailbox\n",
4926 1.15 jmcneill DEVNAME(sc));
4927 1.1 jmcneill return (-1);
4928 1.1 jmcneill }
4929 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
4930 1.1 jmcneill mbin->cmd_rq_ctx.rq_flags = htobe32(
4931 1.1 jmcneill MCX_QUEUE_STATE_RDY << MCX_RQ_CTX_STATE_SHIFT);
4932 1.1 jmcneill
4933 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
4934 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4935 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4936 1.1 jmcneill if (error != 0) {
4937 1.1 jmcneill printf("%s: modify rq timeout\n", DEVNAME(sc));
4938 1.1 jmcneill goto free;
4939 1.1 jmcneill }
4940 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4941 1.1 jmcneill printf("%s: modify rq command corrupt\n", DEVNAME(sc));
4942 1.1 jmcneill goto free;
4943 1.1 jmcneill }
4944 1.1 jmcneill
4945 1.1 jmcneill out = mcx_cmdq_out(cqe);
4946 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4947 1.1 jmcneill printf("%s: modify rq failed (%x, %x)\n", DEVNAME(sc),
4948 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4949 1.1 jmcneill error = -1;
4950 1.1 jmcneill goto free;
4951 1.1 jmcneill }
4952 1.1 jmcneill
4953 1.1 jmcneill free:
4954 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
4955 1.1 jmcneill return (error);
4956 1.1 jmcneill }
4957 1.1 jmcneill
4958 1.1 jmcneill static int
4959 1.15 jmcneill mcx_destroy_rq(struct mcx_softc *sc, struct mcx_rx *rx)
4960 1.1 jmcneill {
4961 1.1 jmcneill struct mcx_cmdq_entry *cqe;
4962 1.1 jmcneill struct mcx_cmd_destroy_rq_in *in;
4963 1.1 jmcneill struct mcx_cmd_destroy_rq_out *out;
4964 1.1 jmcneill int error;
4965 1.1 jmcneill int token;
4966 1.1 jmcneill
4967 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
4968 1.1 jmcneill token = mcx_cmdq_token(sc);
4969 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
4970 1.1 jmcneill
4971 1.1 jmcneill in = mcx_cmdq_in(cqe);
4972 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_RQ);
4973 1.1 jmcneill in->cmd_op_mod = htobe16(0);
4974 1.15 jmcneill in->cmd_rqn = htobe32(rx->rx_rqn);
4975 1.1 jmcneill
4976 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
4977 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
4978 1.1 jmcneill if (error != 0) {
4979 1.1 jmcneill printf("%s: destroy rq timeout\n", DEVNAME(sc));
4980 1.1 jmcneill return error;
4981 1.1 jmcneill }
4982 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
4983 1.1 jmcneill printf("%s: destroy rq command corrupt\n", DEVNAME(sc));
4984 1.1 jmcneill return error;
4985 1.1 jmcneill }
4986 1.1 jmcneill
4987 1.1 jmcneill out = mcx_cmdq_out(cqe);
4988 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
4989 1.1 jmcneill printf("%s: destroy rq failed (%x, %x)\n", DEVNAME(sc),
4990 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
4991 1.1 jmcneill return -1;
4992 1.1 jmcneill }
4993 1.1 jmcneill
4994 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
4995 1.15 jmcneill rx->rx_doorbell, sizeof(uint32_t), BUS_DMASYNC_POSTWRITE);
4996 1.15 jmcneill
4997 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&rx->rx_rq_mem),
4998 1.15 jmcneill 0, MCX_DMA_LEN(&rx->rx_rq_mem), BUS_DMASYNC_POSTWRITE);
4999 1.15 jmcneill mcx_dmamem_free(sc, &rx->rx_rq_mem);
5000 1.15 jmcneill
5001 1.15 jmcneill rx->rx_rqn = 0;
5002 1.1 jmcneill return 0;
5003 1.1 jmcneill }
5004 1.1 jmcneill
5005 1.1 jmcneill static int
5006 1.15 jmcneill mcx_create_tir_direct(struct mcx_softc *sc, struct mcx_rx *rx, int *tirn)
5007 1.1 jmcneill {
5008 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5009 1.1 jmcneill struct mcx_dmamem mxm;
5010 1.1 jmcneill struct mcx_cmd_create_tir_in *in;
5011 1.1 jmcneill struct mcx_cmd_create_tir_mb_in *mbin;
5012 1.1 jmcneill struct mcx_cmd_create_tir_out *out;
5013 1.1 jmcneill int error;
5014 1.1 jmcneill int token;
5015 1.1 jmcneill
5016 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5017 1.1 jmcneill token = mcx_cmdq_token(sc);
5018 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5019 1.15 jmcneill sizeof(*out), token);
5020 1.1 jmcneill
5021 1.1 jmcneill in = mcx_cmdq_in(cqe);
5022 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_TIR);
5023 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5024 1.1 jmcneill
5025 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5026 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5027 1.1 jmcneill printf("%s: unable to allocate create tir mailbox\n",
5028 1.1 jmcneill DEVNAME(sc));
5029 1.1 jmcneill return (-1);
5030 1.1 jmcneill }
5031 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5032 1.1 jmcneill /* leave disp_type = 0, so packets get sent to the inline rqn */
5033 1.15 jmcneill mbin->cmd_inline_rqn = htobe32(rx->rx_rqn);
5034 1.1 jmcneill mbin->cmd_tdomain = htobe32(sc->sc_tdomain);
5035 1.1 jmcneill
5036 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5037 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5038 1.1 jmcneill if (error != 0) {
5039 1.1 jmcneill printf("%s: create tir timeout\n", DEVNAME(sc));
5040 1.1 jmcneill goto free;
5041 1.1 jmcneill }
5042 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5043 1.1 jmcneill printf("%s: create tir command corrupt\n", DEVNAME(sc));
5044 1.1 jmcneill goto free;
5045 1.1 jmcneill }
5046 1.1 jmcneill
5047 1.1 jmcneill out = mcx_cmdq_out(cqe);
5048 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5049 1.1 jmcneill printf("%s: create tir failed (%x, %x)\n", DEVNAME(sc),
5050 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5051 1.1 jmcneill error = -1;
5052 1.1 jmcneill goto free;
5053 1.1 jmcneill }
5054 1.1 jmcneill
5055 1.15 jmcneill *tirn = mcx_get_id(out->cmd_tirn);
5056 1.15 jmcneill free:
5057 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
5058 1.15 jmcneill return (error);
5059 1.15 jmcneill }
5060 1.15 jmcneill
5061 1.15 jmcneill static int
5062 1.15 jmcneill mcx_create_tir_indirect(struct mcx_softc *sc, int rqtn, uint32_t hash_sel,
5063 1.15 jmcneill int *tirn)
5064 1.15 jmcneill {
5065 1.15 jmcneill struct mcx_cmdq_entry *cqe;
5066 1.15 jmcneill struct mcx_dmamem mxm;
5067 1.15 jmcneill struct mcx_cmd_create_tir_in *in;
5068 1.15 jmcneill struct mcx_cmd_create_tir_mb_in *mbin;
5069 1.15 jmcneill struct mcx_cmd_create_tir_out *out;
5070 1.15 jmcneill int error;
5071 1.15 jmcneill int token;
5072 1.15 jmcneill
5073 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5074 1.15 jmcneill token = mcx_cmdq_token(sc);
5075 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5076 1.15 jmcneill sizeof(*out), token);
5077 1.15 jmcneill
5078 1.15 jmcneill in = mcx_cmdq_in(cqe);
5079 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_TIR);
5080 1.15 jmcneill in->cmd_op_mod = htobe16(0);
5081 1.15 jmcneill
5082 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5083 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5084 1.15 jmcneill printf("%s: unable to allocate create tir mailbox\n",
5085 1.15 jmcneill DEVNAME(sc));
5086 1.15 jmcneill return (-1);
5087 1.15 jmcneill }
5088 1.15 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5089 1.15 jmcneill mbin->cmd_disp_type = htobe32(MCX_TIR_CTX_DISP_TYPE_INDIRECT
5090 1.15 jmcneill << MCX_TIR_CTX_DISP_TYPE_SHIFT);
5091 1.15 jmcneill mbin->cmd_indir_table = htobe32(rqtn);
5092 1.15 jmcneill mbin->cmd_tdomain = htobe32(sc->sc_tdomain |
5093 1.15 jmcneill MCX_TIR_CTX_HASH_TOEPLITZ << MCX_TIR_CTX_HASH_SHIFT);
5094 1.15 jmcneill mbin->cmd_rx_hash_sel_outer = htobe32(hash_sel);
5095 1.15 jmcneill stoeplitz_to_key(&mbin->cmd_rx_hash_key,
5096 1.15 jmcneill sizeof(mbin->cmd_rx_hash_key));
5097 1.15 jmcneill
5098 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
5099 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5100 1.15 jmcneill if (error != 0) {
5101 1.15 jmcneill printf("%s: create tir timeout\n", DEVNAME(sc));
5102 1.15 jmcneill goto free;
5103 1.15 jmcneill }
5104 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5105 1.15 jmcneill printf("%s: create tir command corrupt\n", DEVNAME(sc));
5106 1.15 jmcneill goto free;
5107 1.15 jmcneill }
5108 1.15 jmcneill
5109 1.15 jmcneill out = mcx_cmdq_out(cqe);
5110 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5111 1.15 jmcneill printf("%s: create tir failed (%x, %x)\n", DEVNAME(sc),
5112 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5113 1.15 jmcneill error = -1;
5114 1.15 jmcneill goto free;
5115 1.15 jmcneill }
5116 1.15 jmcneill
5117 1.15 jmcneill *tirn = mcx_get_id(out->cmd_tirn);
5118 1.1 jmcneill free:
5119 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5120 1.1 jmcneill return (error);
5121 1.1 jmcneill }
5122 1.1 jmcneill
5123 1.1 jmcneill static int
5124 1.15 jmcneill mcx_destroy_tir(struct mcx_softc *sc, int tirn)
5125 1.1 jmcneill {
5126 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5127 1.1 jmcneill struct mcx_cmd_destroy_tir_in *in;
5128 1.1 jmcneill struct mcx_cmd_destroy_tir_out *out;
5129 1.1 jmcneill int error;
5130 1.1 jmcneill int token;
5131 1.1 jmcneill
5132 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5133 1.1 jmcneill token = mcx_cmdq_token(sc);
5134 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
5135 1.1 jmcneill
5136 1.1 jmcneill in = mcx_cmdq_in(cqe);
5137 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_TIR);
5138 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5139 1.15 jmcneill in->cmd_tirn = htobe32(tirn);
5140 1.1 jmcneill
5141 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5142 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5143 1.1 jmcneill if (error != 0) {
5144 1.1 jmcneill printf("%s: destroy tir timeout\n", DEVNAME(sc));
5145 1.1 jmcneill return error;
5146 1.1 jmcneill }
5147 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5148 1.1 jmcneill printf("%s: destroy tir command corrupt\n", DEVNAME(sc));
5149 1.1 jmcneill return error;
5150 1.1 jmcneill }
5151 1.1 jmcneill
5152 1.1 jmcneill out = mcx_cmdq_out(cqe);
5153 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5154 1.1 jmcneill printf("%s: destroy tir failed (%x, %x)\n", DEVNAME(sc),
5155 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5156 1.1 jmcneill return -1;
5157 1.1 jmcneill }
5158 1.1 jmcneill
5159 1.15 jmcneill return (0);
5160 1.1 jmcneill }
5161 1.1 jmcneill
5162 1.1 jmcneill static int
5163 1.15 jmcneill mcx_create_sq(struct mcx_softc *sc, struct mcx_tx *tx, int uar, int db,
5164 1.15 jmcneill int cqn)
5165 1.1 jmcneill {
5166 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5167 1.1 jmcneill struct mcx_dmamem mxm;
5168 1.1 jmcneill struct mcx_cmd_create_sq_in *in;
5169 1.1 jmcneill struct mcx_sq_ctx *mbin;
5170 1.1 jmcneill struct mcx_cmd_create_sq_out *out;
5171 1.1 jmcneill int error;
5172 1.1 jmcneill uint64_t *pas;
5173 1.13 jmcneill int insize, npages, paslen, token;
5174 1.1 jmcneill
5175 1.15 jmcneill tx->tx_doorbell = MCX_WQ_DOORBELL_BASE +
5176 1.15 jmcneill (db * MCX_WQ_DOORBELL_STRIDE) + 4;
5177 1.15 jmcneill
5178 1.1 jmcneill npages = howmany((1 << MCX_LOG_SQ_SIZE) * sizeof(struct mcx_sq_entry),
5179 1.1 jmcneill MCX_PAGE_SIZE);
5180 1.1 jmcneill paslen = npages * sizeof(*pas);
5181 1.1 jmcneill insize = sizeof(struct mcx_sq_ctx) + paslen;
5182 1.1 jmcneill
5183 1.15 jmcneill if (mcx_dmamem_alloc(sc, &tx->tx_sq_mem, npages * MCX_PAGE_SIZE,
5184 1.1 jmcneill MCX_PAGE_SIZE) != 0) {
5185 1.15 jmcneill printf("%s: unable to allocate send queue memory\n",
5186 1.15 jmcneill DEVNAME(sc));
5187 1.1 jmcneill return (-1);
5188 1.1 jmcneill }
5189 1.1 jmcneill
5190 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5191 1.1 jmcneill token = mcx_cmdq_token(sc);
5192 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + insize + paslen, sizeof(*out),
5193 1.1 jmcneill token);
5194 1.1 jmcneill
5195 1.1 jmcneill in = mcx_cmdq_in(cqe);
5196 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_SQ);
5197 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5198 1.1 jmcneill
5199 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm,
5200 1.15 jmcneill howmany(insize, MCX_CMDQ_MAILBOX_DATASIZE),
5201 1.1 jmcneill &cqe->cq_input_ptr, token) != 0) {
5202 1.15 jmcneill printf("%s: unable to allocate create sq mailboxen\n",
5203 1.15 jmcneill DEVNAME(sc));
5204 1.15 jmcneill goto free_sq;
5205 1.1 jmcneill }
5206 1.15 jmcneill mbin = (struct mcx_sq_ctx *)
5207 1.15 jmcneill (((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0))) + 0x10);
5208 1.1 jmcneill mbin->sq_flags = htobe32(MCX_SQ_CTX_RLKEY |
5209 1.1 jmcneill (1 << MCX_SQ_CTX_MIN_WQE_INLINE_SHIFT));
5210 1.1 jmcneill mbin->sq_cqn = htobe32(cqn);
5211 1.1 jmcneill mbin->sq_tis_lst_sz = htobe32(1 << MCX_SQ_CTX_TIS_LST_SZ_SHIFT);
5212 1.15 jmcneill mbin->sq_tis_num = htobe32(sc->sc_tis);
5213 1.1 jmcneill mbin->sq_wq.wq_type = MCX_WQ_CTX_TYPE_CYCLIC;
5214 1.1 jmcneill mbin->sq_wq.wq_pd = htobe32(sc->sc_pd);
5215 1.15 jmcneill mbin->sq_wq.wq_uar_page = htobe32(uar);
5216 1.1 jmcneill mbin->sq_wq.wq_doorbell = htobe64(MCX_DMA_DVA(&sc->sc_doorbell_mem) +
5217 1.15 jmcneill tx->tx_doorbell);
5218 1.1 jmcneill mbin->sq_wq.wq_log_stride = htobe16(MCX_LOG_SQ_ENTRY_SIZE);
5219 1.1 jmcneill mbin->sq_wq.wq_log_size = MCX_LOG_SQ_SIZE;
5220 1.1 jmcneill
5221 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&tx->tx_sq_mem),
5222 1.15 jmcneill 0, MCX_DMA_LEN(&tx->tx_sq_mem), BUS_DMASYNC_PREWRITE);
5223 1.15 jmcneill
5224 1.1 jmcneill /* physical addresses follow the mailbox in data */
5225 1.15 jmcneill mcx_cmdq_mboxes_pas(&mxm, sizeof(*mbin) + 0x10,
5226 1.15 jmcneill npages, &tx->tx_sq_mem);
5227 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5228 1.1 jmcneill
5229 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5230 1.1 jmcneill if (error != 0) {
5231 1.1 jmcneill printf("%s: create sq timeout\n", DEVNAME(sc));
5232 1.15 jmcneill goto free_mxm;
5233 1.1 jmcneill }
5234 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5235 1.1 jmcneill printf("%s: create sq command corrupt\n", DEVNAME(sc));
5236 1.15 jmcneill goto free_mxm;
5237 1.1 jmcneill }
5238 1.1 jmcneill
5239 1.1 jmcneill out = mcx_cmdq_out(cqe);
5240 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5241 1.1 jmcneill printf("%s: create sq failed (%x, %x)\n", DEVNAME(sc),
5242 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5243 1.15 jmcneill goto free_mxm;
5244 1.1 jmcneill }
5245 1.1 jmcneill
5246 1.15 jmcneill tx->tx_uar = uar;
5247 1.15 jmcneill tx->tx_sqn = mcx_get_id(out->cmd_sqn);
5248 1.15 jmcneill
5249 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
5250 1.15 jmcneill
5251 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
5252 1.15 jmcneill tx->tx_doorbell, sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
5253 1.15 jmcneill
5254 1.15 jmcneill return (0);
5255 1.1 jmcneill
5256 1.15 jmcneill free_mxm:
5257 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&tx->tx_sq_mem),
5258 1.15 jmcneill 0, MCX_DMA_LEN(&tx->tx_sq_mem), BUS_DMASYNC_POSTWRITE);
5259 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5260 1.15 jmcneill free_sq:
5261 1.15 jmcneill mcx_dmamem_free(sc, &tx->tx_sq_mem);
5262 1.15 jmcneill return (-1);
5263 1.1 jmcneill }
5264 1.1 jmcneill
5265 1.1 jmcneill static int
5266 1.15 jmcneill mcx_destroy_sq(struct mcx_softc *sc, struct mcx_tx *tx)
5267 1.1 jmcneill {
5268 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5269 1.1 jmcneill struct mcx_cmd_destroy_sq_in *in;
5270 1.1 jmcneill struct mcx_cmd_destroy_sq_out *out;
5271 1.1 jmcneill int error;
5272 1.1 jmcneill int token;
5273 1.1 jmcneill
5274 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5275 1.1 jmcneill token = mcx_cmdq_token(sc);
5276 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
5277 1.1 jmcneill
5278 1.1 jmcneill in = mcx_cmdq_in(cqe);
5279 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_SQ);
5280 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5281 1.15 jmcneill in->cmd_sqn = htobe32(tx->tx_sqn);
5282 1.1 jmcneill
5283 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5284 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5285 1.1 jmcneill if (error != 0) {
5286 1.1 jmcneill printf("%s: destroy sq timeout\n", DEVNAME(sc));
5287 1.1 jmcneill return error;
5288 1.1 jmcneill }
5289 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5290 1.1 jmcneill printf("%s: destroy sq command corrupt\n", DEVNAME(sc));
5291 1.1 jmcneill return error;
5292 1.1 jmcneill }
5293 1.1 jmcneill
5294 1.1 jmcneill out = mcx_cmdq_out(cqe);
5295 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5296 1.1 jmcneill printf("%s: destroy sq failed (%x, %x)\n", DEVNAME(sc),
5297 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5298 1.1 jmcneill return -1;
5299 1.1 jmcneill }
5300 1.1 jmcneill
5301 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
5302 1.15 jmcneill tx->tx_doorbell, sizeof(uint32_t), BUS_DMASYNC_POSTWRITE);
5303 1.15 jmcneill
5304 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&tx->tx_sq_mem),
5305 1.15 jmcneill 0, MCX_DMA_LEN(&tx->tx_sq_mem), BUS_DMASYNC_POSTWRITE);
5306 1.15 jmcneill mcx_dmamem_free(sc, &tx->tx_sq_mem);
5307 1.15 jmcneill
5308 1.15 jmcneill tx->tx_sqn = 0;
5309 1.1 jmcneill return 0;
5310 1.1 jmcneill }
5311 1.1 jmcneill
5312 1.1 jmcneill static int
5313 1.15 jmcneill mcx_ready_sq(struct mcx_softc *sc, struct mcx_tx *tx)
5314 1.1 jmcneill {
5315 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5316 1.1 jmcneill struct mcx_dmamem mxm;
5317 1.1 jmcneill struct mcx_cmd_modify_sq_in *in;
5318 1.1 jmcneill struct mcx_cmd_modify_sq_mb_in *mbin;
5319 1.1 jmcneill struct mcx_cmd_modify_sq_out *out;
5320 1.1 jmcneill int error;
5321 1.1 jmcneill int token;
5322 1.1 jmcneill
5323 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5324 1.1 jmcneill token = mcx_cmdq_token(sc);
5325 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5326 1.15 jmcneill sizeof(*out), token);
5327 1.1 jmcneill
5328 1.1 jmcneill in = mcx_cmdq_in(cqe);
5329 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_MODIFY_SQ);
5330 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5331 1.15 jmcneill in->cmd_sq_state = htobe32((MCX_QUEUE_STATE_RST << 28) | tx->tx_sqn);
5332 1.1 jmcneill
5333 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5334 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5335 1.1 jmcneill printf("%s: unable to allocate modify sq mailbox\n",
5336 1.1 jmcneill DEVNAME(sc));
5337 1.1 jmcneill return (-1);
5338 1.1 jmcneill }
5339 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5340 1.1 jmcneill mbin->cmd_sq_ctx.sq_flags = htobe32(
5341 1.1 jmcneill MCX_QUEUE_STATE_RDY << MCX_SQ_CTX_STATE_SHIFT);
5342 1.1 jmcneill
5343 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5344 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5345 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5346 1.1 jmcneill if (error != 0) {
5347 1.1 jmcneill printf("%s: modify sq timeout\n", DEVNAME(sc));
5348 1.1 jmcneill goto free;
5349 1.1 jmcneill }
5350 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5351 1.1 jmcneill printf("%s: modify sq command corrupt\n", DEVNAME(sc));
5352 1.1 jmcneill goto free;
5353 1.1 jmcneill }
5354 1.1 jmcneill
5355 1.1 jmcneill out = mcx_cmdq_out(cqe);
5356 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5357 1.1 jmcneill printf("%s: modify sq failed (%x, %x)\n", DEVNAME(sc),
5358 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5359 1.1 jmcneill error = -1;
5360 1.1 jmcneill goto free;
5361 1.1 jmcneill }
5362 1.1 jmcneill
5363 1.1 jmcneill free:
5364 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5365 1.1 jmcneill return (error);
5366 1.1 jmcneill }
5367 1.1 jmcneill
5368 1.1 jmcneill static int
5369 1.15 jmcneill mcx_create_tis(struct mcx_softc *sc, int *tis)
5370 1.1 jmcneill {
5371 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5372 1.1 jmcneill struct mcx_dmamem mxm;
5373 1.1 jmcneill struct mcx_cmd_create_tis_in *in;
5374 1.1 jmcneill struct mcx_cmd_create_tis_mb_in *mbin;
5375 1.1 jmcneill struct mcx_cmd_create_tis_out *out;
5376 1.1 jmcneill int error;
5377 1.1 jmcneill int token;
5378 1.1 jmcneill
5379 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5380 1.1 jmcneill token = mcx_cmdq_token(sc);
5381 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5382 1.15 jmcneill sizeof(*out), token);
5383 1.1 jmcneill
5384 1.1 jmcneill in = mcx_cmdq_in(cqe);
5385 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_TIS);
5386 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5387 1.1 jmcneill
5388 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5389 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5390 1.15 jmcneill printf("%s: unable to allocate create tis mailbox\n",
5391 1.15 jmcneill DEVNAME(sc));
5392 1.1 jmcneill return (-1);
5393 1.1 jmcneill }
5394 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5395 1.1 jmcneill mbin->cmd_tdomain = htobe32(sc->sc_tdomain);
5396 1.1 jmcneill
5397 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5398 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5399 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5400 1.1 jmcneill if (error != 0) {
5401 1.1 jmcneill printf("%s: create tis timeout\n", DEVNAME(sc));
5402 1.1 jmcneill goto free;
5403 1.1 jmcneill }
5404 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5405 1.1 jmcneill printf("%s: create tis command corrupt\n", DEVNAME(sc));
5406 1.1 jmcneill goto free;
5407 1.1 jmcneill }
5408 1.1 jmcneill
5409 1.1 jmcneill out = mcx_cmdq_out(cqe);
5410 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5411 1.1 jmcneill printf("%s: create tis failed (%x, %x)\n", DEVNAME(sc),
5412 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5413 1.1 jmcneill error = -1;
5414 1.1 jmcneill goto free;
5415 1.1 jmcneill }
5416 1.1 jmcneill
5417 1.15 jmcneill *tis = mcx_get_id(out->cmd_tisn);
5418 1.1 jmcneill free:
5419 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5420 1.1 jmcneill return (error);
5421 1.1 jmcneill }
5422 1.1 jmcneill
5423 1.1 jmcneill static int
5424 1.15 jmcneill mcx_destroy_tis(struct mcx_softc *sc, int tis)
5425 1.1 jmcneill {
5426 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5427 1.1 jmcneill struct mcx_cmd_destroy_tis_in *in;
5428 1.1 jmcneill struct mcx_cmd_destroy_tis_out *out;
5429 1.1 jmcneill int error;
5430 1.1 jmcneill int token;
5431 1.1 jmcneill
5432 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5433 1.1 jmcneill token = mcx_cmdq_token(sc);
5434 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
5435 1.1 jmcneill
5436 1.1 jmcneill in = mcx_cmdq_in(cqe);
5437 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_TIS);
5438 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5439 1.15 jmcneill in->cmd_tisn = htobe32(tis);
5440 1.1 jmcneill
5441 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5442 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5443 1.1 jmcneill if (error != 0) {
5444 1.1 jmcneill printf("%s: destroy tis timeout\n", DEVNAME(sc));
5445 1.1 jmcneill return error;
5446 1.1 jmcneill }
5447 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5448 1.1 jmcneill printf("%s: destroy tis command corrupt\n", DEVNAME(sc));
5449 1.1 jmcneill return error;
5450 1.1 jmcneill }
5451 1.1 jmcneill
5452 1.1 jmcneill out = mcx_cmdq_out(cqe);
5453 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5454 1.1 jmcneill printf("%s: destroy tis failed (%x, %x)\n", DEVNAME(sc),
5455 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5456 1.1 jmcneill return -1;
5457 1.1 jmcneill }
5458 1.1 jmcneill
5459 1.15 jmcneill return 0;
5460 1.15 jmcneill }
5461 1.15 jmcneill
5462 1.15 jmcneill static int
5463 1.15 jmcneill mcx_create_rqt(struct mcx_softc *sc, int size, int *rqns, int *rqt)
5464 1.15 jmcneill {
5465 1.15 jmcneill struct mcx_cmdq_entry *cqe;
5466 1.15 jmcneill struct mcx_dmamem mxm;
5467 1.15 jmcneill struct mcx_cmd_create_rqt_in *in;
5468 1.15 jmcneill struct mcx_cmd_create_rqt_mb_in *mbin;
5469 1.15 jmcneill struct mcx_cmd_create_rqt_out *out;
5470 1.15 jmcneill struct mcx_rqt_ctx *rqt_ctx;
5471 1.15 jmcneill int *rqtn;
5472 1.15 jmcneill int error;
5473 1.15 jmcneill int token;
5474 1.15 jmcneill int i;
5475 1.15 jmcneill
5476 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5477 1.15 jmcneill token = mcx_cmdq_token(sc);
5478 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin) +
5479 1.15 jmcneill (size * sizeof(int)), sizeof(*out), token);
5480 1.15 jmcneill
5481 1.15 jmcneill in = mcx_cmdq_in(cqe);
5482 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_RQT);
5483 1.15 jmcneill in->cmd_op_mod = htobe16(0);
5484 1.15 jmcneill
5485 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5486 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5487 1.15 jmcneill printf("%s: unable to allocate create rqt mailbox\n",
5488 1.15 jmcneill DEVNAME(sc));
5489 1.15 jmcneill return (-1);
5490 1.15 jmcneill }
5491 1.15 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5492 1.15 jmcneill rqt_ctx = &mbin->cmd_rqt;
5493 1.15 jmcneill rqt_ctx->cmd_rqt_max_size = htobe16(sc->sc_max_rqt_size);
5494 1.15 jmcneill rqt_ctx->cmd_rqt_actual_size = htobe16(size);
5495 1.15 jmcneill
5496 1.15 jmcneill /* rqt list follows the rqt context */
5497 1.15 jmcneill rqtn = (int *)(rqt_ctx + 1);
5498 1.15 jmcneill for (i = 0; i < size; i++) {
5499 1.15 jmcneill rqtn[i] = htobe32(rqns[i]);
5500 1.15 jmcneill }
5501 1.15 jmcneill
5502 1.15 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5503 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
5504 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5505 1.15 jmcneill if (error != 0) {
5506 1.15 jmcneill printf("%s: create rqt timeout\n", DEVNAME(sc));
5507 1.15 jmcneill goto free;
5508 1.15 jmcneill }
5509 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5510 1.15 jmcneill printf("%s: create rqt command corrupt\n", DEVNAME(sc));
5511 1.15 jmcneill goto free;
5512 1.15 jmcneill }
5513 1.15 jmcneill
5514 1.15 jmcneill out = mcx_cmdq_out(cqe);
5515 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5516 1.15 jmcneill printf("%s: create rqt failed (%x, %x)\n", DEVNAME(sc),
5517 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5518 1.15 jmcneill error = -1;
5519 1.15 jmcneill goto free;
5520 1.15 jmcneill }
5521 1.15 jmcneill
5522 1.15 jmcneill *rqt = mcx_get_id(out->cmd_rqtn);
5523 1.15 jmcneill return (0);
5524 1.15 jmcneill free:
5525 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
5526 1.15 jmcneill return (error);
5527 1.15 jmcneill }
5528 1.15 jmcneill
5529 1.15 jmcneill static int
5530 1.15 jmcneill mcx_destroy_rqt(struct mcx_softc *sc, int rqt)
5531 1.15 jmcneill {
5532 1.15 jmcneill struct mcx_cmdq_entry *cqe;
5533 1.15 jmcneill struct mcx_cmd_destroy_rqt_in *in;
5534 1.15 jmcneill struct mcx_cmd_destroy_rqt_out *out;
5535 1.15 jmcneill int error;
5536 1.15 jmcneill int token;
5537 1.15 jmcneill
5538 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5539 1.15 jmcneill token = mcx_cmdq_token(sc);
5540 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
5541 1.15 jmcneill
5542 1.15 jmcneill in = mcx_cmdq_in(cqe);
5543 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_RQT);
5544 1.15 jmcneill in->cmd_op_mod = htobe16(0);
5545 1.15 jmcneill in->cmd_rqtn = htobe32(rqt);
5546 1.15 jmcneill
5547 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
5548 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5549 1.15 jmcneill if (error != 0) {
5550 1.15 jmcneill printf("%s: destroy rqt timeout\n", DEVNAME(sc));
5551 1.15 jmcneill return error;
5552 1.15 jmcneill }
5553 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5554 1.15 jmcneill printf("%s: destroy rqt command corrupt\n", DEVNAME(sc));
5555 1.15 jmcneill return error;
5556 1.15 jmcneill }
5557 1.15 jmcneill
5558 1.15 jmcneill out = mcx_cmdq_out(cqe);
5559 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5560 1.15 jmcneill printf("%s: destroy rqt failed (%x, %x)\n", DEVNAME(sc),
5561 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5562 1.15 jmcneill return -1;
5563 1.15 jmcneill }
5564 1.15 jmcneill
5565 1.1 jmcneill return 0;
5566 1.1 jmcneill }
5567 1.1 jmcneill
5568 1.1 jmcneill #if 0
5569 1.1 jmcneill static int
5570 1.1 jmcneill mcx_alloc_flow_counter(struct mcx_softc *sc, int i)
5571 1.1 jmcneill {
5572 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5573 1.1 jmcneill struct mcx_cmd_alloc_flow_counter_in *in;
5574 1.1 jmcneill struct mcx_cmd_alloc_flow_counter_out *out;
5575 1.1 jmcneill int error;
5576 1.1 jmcneill
5577 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5578 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), mcx_cmdq_token(sc));
5579 1.1 jmcneill
5580 1.1 jmcneill in = mcx_cmdq_in(cqe);
5581 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_ALLOC_FLOW_COUNTER);
5582 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5583 1.1 jmcneill
5584 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5585 1.1 jmcneill
5586 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5587 1.1 jmcneill if (error != 0) {
5588 1.1 jmcneill printf("%s: alloc flow counter timeout\n", DEVNAME(sc));
5589 1.1 jmcneill return (-1);
5590 1.1 jmcneill }
5591 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5592 1.1 jmcneill printf("%s: alloc flow counter command corrupt\n", DEVNAME(sc));
5593 1.1 jmcneill return (-1);
5594 1.1 jmcneill }
5595 1.1 jmcneill
5596 1.1 jmcneill out = (struct mcx_cmd_alloc_flow_counter_out *)cqe->cq_output_data;
5597 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5598 1.1 jmcneill printf("%s: alloc flow counter failed (%x)\n", DEVNAME(sc),
5599 1.1 jmcneill out->cmd_status);
5600 1.1 jmcneill return (-1);
5601 1.1 jmcneill }
5602 1.1 jmcneill
5603 1.1 jmcneill sc->sc_flow_counter_id[i] = be16toh(out->cmd_flow_counter_id);
5604 1.1 jmcneill printf("flow counter id %d = %d\n", i, sc->sc_flow_counter_id[i]);
5605 1.1 jmcneill
5606 1.1 jmcneill return (0);
5607 1.1 jmcneill }
5608 1.1 jmcneill #endif
5609 1.1 jmcneill
5610 1.1 jmcneill static int
5611 1.15 jmcneill mcx_create_flow_table(struct mcx_softc *sc, int log_size, int level,
5612 1.15 jmcneill int *flow_table_id)
5613 1.1 jmcneill {
5614 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5615 1.1 jmcneill struct mcx_dmamem mxm;
5616 1.1 jmcneill struct mcx_cmd_create_flow_table_in *in;
5617 1.1 jmcneill struct mcx_cmd_create_flow_table_mb_in *mbin;
5618 1.1 jmcneill struct mcx_cmd_create_flow_table_out *out;
5619 1.1 jmcneill int error;
5620 1.1 jmcneill int token;
5621 1.1 jmcneill
5622 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5623 1.1 jmcneill token = mcx_cmdq_token(sc);
5624 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5625 1.15 jmcneill sizeof(*out), token);
5626 1.1 jmcneill
5627 1.1 jmcneill in = mcx_cmdq_in(cqe);
5628 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_FLOW_TABLE);
5629 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5630 1.1 jmcneill
5631 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5632 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5633 1.1 jmcneill printf("%s: unable to allocate create flow table mailbox\n",
5634 1.1 jmcneill DEVNAME(sc));
5635 1.1 jmcneill return (-1);
5636 1.1 jmcneill }
5637 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5638 1.1 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5639 1.1 jmcneill mbin->cmd_ctx.ft_log_size = log_size;
5640 1.15 jmcneill mbin->cmd_ctx.ft_level = level;
5641 1.1 jmcneill
5642 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5643 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5644 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5645 1.1 jmcneill if (error != 0) {
5646 1.1 jmcneill printf("%s: create flow table timeout\n", DEVNAME(sc));
5647 1.1 jmcneill goto free;
5648 1.1 jmcneill }
5649 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5650 1.1 jmcneill printf("%s: create flow table command corrupt\n", DEVNAME(sc));
5651 1.1 jmcneill goto free;
5652 1.1 jmcneill }
5653 1.1 jmcneill
5654 1.1 jmcneill out = mcx_cmdq_out(cqe);
5655 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5656 1.1 jmcneill printf("%s: create flow table failed (%x, %x)\n", DEVNAME(sc),
5657 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5658 1.1 jmcneill error = -1;
5659 1.1 jmcneill goto free;
5660 1.1 jmcneill }
5661 1.1 jmcneill
5662 1.15 jmcneill *flow_table_id = mcx_get_id(out->cmd_table_id);
5663 1.1 jmcneill free:
5664 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5665 1.1 jmcneill return (error);
5666 1.1 jmcneill }
5667 1.1 jmcneill
5668 1.1 jmcneill static int
5669 1.15 jmcneill mcx_set_flow_table_root(struct mcx_softc *sc, int flow_table_id)
5670 1.1 jmcneill {
5671 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5672 1.1 jmcneill struct mcx_dmamem mxm;
5673 1.1 jmcneill struct mcx_cmd_set_flow_table_root_in *in;
5674 1.1 jmcneill struct mcx_cmd_set_flow_table_root_mb_in *mbin;
5675 1.1 jmcneill struct mcx_cmd_set_flow_table_root_out *out;
5676 1.1 jmcneill int error;
5677 1.1 jmcneill int token;
5678 1.1 jmcneill
5679 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5680 1.1 jmcneill token = mcx_cmdq_token(sc);
5681 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
5682 1.15 jmcneill sizeof(*out), token);
5683 1.1 jmcneill
5684 1.1 jmcneill in = mcx_cmdq_in(cqe);
5685 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_SET_FLOW_TABLE_ROOT);
5686 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5687 1.1 jmcneill
5688 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5689 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5690 1.1 jmcneill printf("%s: unable to allocate set flow table root mailbox\n",
5691 1.1 jmcneill DEVNAME(sc));
5692 1.1 jmcneill return (-1);
5693 1.1 jmcneill }
5694 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5695 1.1 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5696 1.15 jmcneill mbin->cmd_table_id = htobe32(flow_table_id);
5697 1.1 jmcneill
5698 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5699 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5700 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5701 1.1 jmcneill if (error != 0) {
5702 1.1 jmcneill printf("%s: set flow table root timeout\n", DEVNAME(sc));
5703 1.1 jmcneill goto free;
5704 1.1 jmcneill }
5705 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5706 1.1 jmcneill printf("%s: set flow table root command corrupt\n",
5707 1.1 jmcneill DEVNAME(sc));
5708 1.1 jmcneill goto free;
5709 1.1 jmcneill }
5710 1.1 jmcneill
5711 1.1 jmcneill out = mcx_cmdq_out(cqe);
5712 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5713 1.1 jmcneill printf("%s: set flow table root failed (%x, %x)\n",
5714 1.1 jmcneill DEVNAME(sc), out->cmd_status, be32toh(out->cmd_syndrome));
5715 1.1 jmcneill error = -1;
5716 1.1 jmcneill goto free;
5717 1.1 jmcneill }
5718 1.1 jmcneill
5719 1.1 jmcneill free:
5720 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5721 1.1 jmcneill return (error);
5722 1.1 jmcneill }
5723 1.1 jmcneill
5724 1.1 jmcneill static int
5725 1.15 jmcneill mcx_destroy_flow_table(struct mcx_softc *sc, int flow_table_id)
5726 1.1 jmcneill {
5727 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5728 1.1 jmcneill struct mcx_dmamem mxm;
5729 1.1 jmcneill struct mcx_cmd_destroy_flow_table_in *in;
5730 1.1 jmcneill struct mcx_cmd_destroy_flow_table_mb_in *mb;
5731 1.1 jmcneill struct mcx_cmd_destroy_flow_table_out *out;
5732 1.1 jmcneill int error;
5733 1.1 jmcneill int token;
5734 1.1 jmcneill
5735 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5736 1.1 jmcneill token = mcx_cmdq_token(sc);
5737 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mb), sizeof(*out), token);
5738 1.1 jmcneill
5739 1.1 jmcneill in = mcx_cmdq_in(cqe);
5740 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_FLOW_TABLE);
5741 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5742 1.1 jmcneill
5743 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
5744 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5745 1.1 jmcneill printf("%s: unable to allocate destroy flow table mailbox\n",
5746 1.1 jmcneill DEVNAME(sc));
5747 1.1 jmcneill return (-1);
5748 1.1 jmcneill }
5749 1.1 jmcneill mb = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5750 1.1 jmcneill mb->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5751 1.15 jmcneill mb->cmd_table_id = htobe32(flow_table_id);
5752 1.1 jmcneill
5753 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
5754 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5755 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5756 1.1 jmcneill if (error != 0) {
5757 1.1 jmcneill printf("%s: destroy flow table timeout\n", DEVNAME(sc));
5758 1.1 jmcneill goto free;
5759 1.1 jmcneill }
5760 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5761 1.15 jmcneill printf("%s: destroy flow table command corrupt\n",
5762 1.15 jmcneill DEVNAME(sc));
5763 1.1 jmcneill goto free;
5764 1.1 jmcneill }
5765 1.1 jmcneill
5766 1.1 jmcneill out = mcx_cmdq_out(cqe);
5767 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5768 1.1 jmcneill printf("%s: destroy flow table failed (%x, %x)\n", DEVNAME(sc),
5769 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5770 1.1 jmcneill error = -1;
5771 1.1 jmcneill goto free;
5772 1.1 jmcneill }
5773 1.1 jmcneill
5774 1.1 jmcneill free:
5775 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5776 1.1 jmcneill return (error);
5777 1.1 jmcneill }
5778 1.1 jmcneill
5779 1.1 jmcneill
5780 1.1 jmcneill static int
5781 1.15 jmcneill mcx_create_flow_group(struct mcx_softc *sc, int flow_table_id, int group,
5782 1.15 jmcneill int start, int size, int match_enable, struct mcx_flow_match *match)
5783 1.1 jmcneill {
5784 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5785 1.1 jmcneill struct mcx_dmamem mxm;
5786 1.1 jmcneill struct mcx_cmd_create_flow_group_in *in;
5787 1.1 jmcneill struct mcx_cmd_create_flow_group_mb_in *mbin;
5788 1.1 jmcneill struct mcx_cmd_create_flow_group_out *out;
5789 1.15 jmcneill struct mcx_flow_group *mfg;
5790 1.1 jmcneill int error;
5791 1.1 jmcneill int token;
5792 1.1 jmcneill
5793 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5794 1.1 jmcneill token = mcx_cmdq_token(sc);
5795 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin), sizeof(*out),
5796 1.1 jmcneill token);
5797 1.1 jmcneill
5798 1.1 jmcneill in = mcx_cmdq_in(cqe);
5799 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_CREATE_FLOW_GROUP);
5800 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5801 1.1 jmcneill
5802 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2, &cqe->cq_input_ptr, token)
5803 1.1 jmcneill != 0) {
5804 1.1 jmcneill printf("%s: unable to allocate create flow group mailbox\n",
5805 1.1 jmcneill DEVNAME(sc));
5806 1.1 jmcneill return (-1);
5807 1.1 jmcneill }
5808 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5809 1.1 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5810 1.15 jmcneill mbin->cmd_table_id = htobe32(flow_table_id);
5811 1.1 jmcneill mbin->cmd_start_flow_index = htobe32(start);
5812 1.1 jmcneill mbin->cmd_end_flow_index = htobe32(start + (size - 1));
5813 1.1 jmcneill
5814 1.1 jmcneill mbin->cmd_match_criteria_enable = match_enable;
5815 1.1 jmcneill memcpy(&mbin->cmd_match_criteria, match, sizeof(*match));
5816 1.1 jmcneill
5817 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 2);
5818 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5819 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5820 1.1 jmcneill if (error != 0) {
5821 1.1 jmcneill printf("%s: create flow group timeout\n", DEVNAME(sc));
5822 1.1 jmcneill goto free;
5823 1.1 jmcneill }
5824 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5825 1.1 jmcneill printf("%s: create flow group command corrupt\n", DEVNAME(sc));
5826 1.1 jmcneill goto free;
5827 1.1 jmcneill }
5828 1.1 jmcneill
5829 1.1 jmcneill out = mcx_cmdq_out(cqe);
5830 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5831 1.1 jmcneill printf("%s: create flow group failed (%x, %x)\n", DEVNAME(sc),
5832 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5833 1.1 jmcneill error = -1;
5834 1.1 jmcneill goto free;
5835 1.1 jmcneill }
5836 1.1 jmcneill
5837 1.15 jmcneill mfg = &sc->sc_flow_group[group];
5838 1.15 jmcneill mfg->g_id = mcx_get_id(out->cmd_group_id);
5839 1.15 jmcneill mfg->g_table = flow_table_id;
5840 1.15 jmcneill mfg->g_start = start;
5841 1.15 jmcneill mfg->g_size = size;
5842 1.1 jmcneill
5843 1.1 jmcneill free:
5844 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5845 1.1 jmcneill return (error);
5846 1.1 jmcneill }
5847 1.1 jmcneill
5848 1.1 jmcneill static int
5849 1.1 jmcneill mcx_destroy_flow_group(struct mcx_softc *sc, int group)
5850 1.1 jmcneill {
5851 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5852 1.1 jmcneill struct mcx_dmamem mxm;
5853 1.1 jmcneill struct mcx_cmd_destroy_flow_group_in *in;
5854 1.1 jmcneill struct mcx_cmd_destroy_flow_group_mb_in *mb;
5855 1.1 jmcneill struct mcx_cmd_destroy_flow_group_out *out;
5856 1.15 jmcneill struct mcx_flow_group *mfg;
5857 1.1 jmcneill int error;
5858 1.1 jmcneill int token;
5859 1.1 jmcneill
5860 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5861 1.1 jmcneill token = mcx_cmdq_token(sc);
5862 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mb), sizeof(*out), token);
5863 1.1 jmcneill
5864 1.1 jmcneill in = mcx_cmdq_in(cqe);
5865 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DESTROY_FLOW_GROUP);
5866 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5867 1.1 jmcneill
5868 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
5869 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
5870 1.1 jmcneill printf("%s: unable to allocate destroy flow group mailbox\n",
5871 1.1 jmcneill DEVNAME(sc));
5872 1.1 jmcneill return (-1);
5873 1.1 jmcneill }
5874 1.1 jmcneill mb = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5875 1.1 jmcneill mb->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5876 1.15 jmcneill mfg = &sc->sc_flow_group[group];
5877 1.15 jmcneill mb->cmd_table_id = htobe32(mfg->g_table);
5878 1.15 jmcneill mb->cmd_group_id = htobe32(mfg->g_id);
5879 1.1 jmcneill
5880 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 2);
5881 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5882 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5883 1.1 jmcneill if (error != 0) {
5884 1.1 jmcneill printf("%s: destroy flow group timeout\n", DEVNAME(sc));
5885 1.1 jmcneill goto free;
5886 1.1 jmcneill }
5887 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5888 1.1 jmcneill printf("%s: destroy flow group command corrupt\n", DEVNAME(sc));
5889 1.1 jmcneill goto free;
5890 1.1 jmcneill }
5891 1.1 jmcneill
5892 1.1 jmcneill out = mcx_cmdq_out(cqe);
5893 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5894 1.1 jmcneill printf("%s: destroy flow group failed (%x, %x)\n", DEVNAME(sc),
5895 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
5896 1.1 jmcneill error = -1;
5897 1.1 jmcneill goto free;
5898 1.1 jmcneill }
5899 1.1 jmcneill
5900 1.15 jmcneill mfg->g_id = -1;
5901 1.15 jmcneill mfg->g_table = -1;
5902 1.15 jmcneill mfg->g_size = 0;
5903 1.15 jmcneill mfg->g_start = 0;
5904 1.1 jmcneill free:
5905 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5906 1.1 jmcneill return (error);
5907 1.1 jmcneill }
5908 1.1 jmcneill
5909 1.1 jmcneill static int
5910 1.15 jmcneill mcx_set_flow_table_entry_mac(struct mcx_softc *sc, int group, int index,
5911 1.15 jmcneill const uint8_t *macaddr, uint32_t dest)
5912 1.1 jmcneill {
5913 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5914 1.1 jmcneill struct mcx_dmamem mxm;
5915 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_in *in;
5916 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_mb_in *mbin;
5917 1.1 jmcneill struct mcx_cmd_set_flow_table_entry_out *out;
5918 1.15 jmcneill struct mcx_flow_group *mfg;
5919 1.15 jmcneill uint32_t *pdest;
5920 1.1 jmcneill int error;
5921 1.1 jmcneill int token;
5922 1.1 jmcneill
5923 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
5924 1.1 jmcneill token = mcx_cmdq_token(sc);
5925 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin) + sizeof(*pdest),
5926 1.1 jmcneill sizeof(*out), token);
5927 1.1 jmcneill
5928 1.1 jmcneill in = mcx_cmdq_in(cqe);
5929 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_SET_FLOW_TABLE_ENTRY);
5930 1.1 jmcneill in->cmd_op_mod = htobe16(0);
5931 1.1 jmcneill
5932 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2, &cqe->cq_input_ptr, token)
5933 1.1 jmcneill != 0) {
5934 1.1 jmcneill printf("%s: unable to allocate set flow table entry mailbox\n",
5935 1.1 jmcneill DEVNAME(sc));
5936 1.1 jmcneill return (-1);
5937 1.1 jmcneill }
5938 1.15 jmcneill
5939 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
5940 1.1 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
5941 1.15 jmcneill
5942 1.15 jmcneill mfg = &sc->sc_flow_group[group];
5943 1.15 jmcneill mbin->cmd_table_id = htobe32(mfg->g_table);
5944 1.15 jmcneill mbin->cmd_flow_index = htobe32(mfg->g_start + index);
5945 1.15 jmcneill mbin->cmd_flow_ctx.fc_group_id = htobe32(mfg->g_id);
5946 1.1 jmcneill
5947 1.1 jmcneill /* flow context ends at offset 0x330, 0x130 into the second mbox */
5948 1.15 jmcneill pdest = (uint32_t *)
5949 1.1 jmcneill (((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 1))) + 0x130);
5950 1.1 jmcneill mbin->cmd_flow_ctx.fc_action = htobe32(MCX_FLOW_CONTEXT_ACTION_FORWARD);
5951 1.1 jmcneill mbin->cmd_flow_ctx.fc_dest_list_size = htobe32(1);
5952 1.15 jmcneill *pdest = htobe32(dest);
5953 1.1 jmcneill
5954 1.1 jmcneill /* the only thing we match on at the moment is the dest mac address */
5955 1.1 jmcneill if (macaddr != NULL) {
5956 1.1 jmcneill memcpy(mbin->cmd_flow_ctx.fc_match_value.mc_dest_mac, macaddr,
5957 1.1 jmcneill ETHER_ADDR_LEN);
5958 1.1 jmcneill }
5959 1.1 jmcneill
5960 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 2);
5961 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
5962 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
5963 1.1 jmcneill if (error != 0) {
5964 1.1 jmcneill printf("%s: set flow table entry timeout\n", DEVNAME(sc));
5965 1.1 jmcneill goto free;
5966 1.1 jmcneill }
5967 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
5968 1.1 jmcneill printf("%s: set flow table entry command corrupt\n",
5969 1.1 jmcneill DEVNAME(sc));
5970 1.1 jmcneill goto free;
5971 1.1 jmcneill }
5972 1.1 jmcneill
5973 1.1 jmcneill out = mcx_cmdq_out(cqe);
5974 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
5975 1.1 jmcneill printf("%s: set flow table entry failed (%x, %x)\n",
5976 1.1 jmcneill DEVNAME(sc), out->cmd_status, be32toh(out->cmd_syndrome));
5977 1.1 jmcneill error = -1;
5978 1.1 jmcneill goto free;
5979 1.1 jmcneill }
5980 1.1 jmcneill
5981 1.1 jmcneill free:
5982 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
5983 1.1 jmcneill return (error);
5984 1.1 jmcneill }
5985 1.1 jmcneill
5986 1.1 jmcneill static int
5987 1.15 jmcneill mcx_set_flow_table_entry_proto(struct mcx_softc *sc, int group, int index,
5988 1.15 jmcneill int ethertype, int ip_proto, uint32_t dest)
5989 1.1 jmcneill {
5990 1.1 jmcneill struct mcx_cmdq_entry *cqe;
5991 1.1 jmcneill struct mcx_dmamem mxm;
5992 1.15 jmcneill struct mcx_cmd_set_flow_table_entry_in *in;
5993 1.15 jmcneill struct mcx_cmd_set_flow_table_entry_mb_in *mbin;
5994 1.15 jmcneill struct mcx_cmd_set_flow_table_entry_out *out;
5995 1.15 jmcneill struct mcx_flow_group *mfg;
5996 1.15 jmcneill uint32_t *pdest;
5997 1.1 jmcneill int error;
5998 1.1 jmcneill int token;
5999 1.1 jmcneill
6000 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6001 1.1 jmcneill token = mcx_cmdq_token(sc);
6002 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin) + sizeof(*pdest),
6003 1.15 jmcneill sizeof(*out), token);
6004 1.1 jmcneill
6005 1.1 jmcneill in = mcx_cmdq_in(cqe);
6006 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_SET_FLOW_TABLE_ENTRY);
6007 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6008 1.1 jmcneill
6009 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2, &cqe->cq_input_ptr, token)
6010 1.15 jmcneill != 0) {
6011 1.15 jmcneill printf("%s: unable to allocate set flow table entry mailbox\n",
6012 1.1 jmcneill DEVNAME(sc));
6013 1.1 jmcneill return (-1);
6014 1.1 jmcneill }
6015 1.15 jmcneill
6016 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6017 1.1 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
6018 1.15 jmcneill
6019 1.15 jmcneill mfg = &sc->sc_flow_group[group];
6020 1.15 jmcneill mbin->cmd_table_id = htobe32(mfg->g_table);
6021 1.15 jmcneill mbin->cmd_flow_index = htobe32(mfg->g_start + index);
6022 1.15 jmcneill mbin->cmd_flow_ctx.fc_group_id = htobe32(mfg->g_id);
6023 1.15 jmcneill
6024 1.15 jmcneill /* flow context ends at offset 0x330, 0x130 into the second mbox */
6025 1.15 jmcneill pdest = (uint32_t *)
6026 1.15 jmcneill (((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 1))) + 0x130);
6027 1.15 jmcneill mbin->cmd_flow_ctx.fc_action = htobe32(MCX_FLOW_CONTEXT_ACTION_FORWARD);
6028 1.15 jmcneill mbin->cmd_flow_ctx.fc_dest_list_size = htobe32(1);
6029 1.15 jmcneill *pdest = htobe32(dest);
6030 1.15 jmcneill
6031 1.15 jmcneill mbin->cmd_flow_ctx.fc_match_value.mc_ethertype = htobe16(ethertype);
6032 1.15 jmcneill mbin->cmd_flow_ctx.fc_match_value.mc_ip_proto = ip_proto;
6033 1.1 jmcneill
6034 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 2);
6035 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6036 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6037 1.1 jmcneill if (error != 0) {
6038 1.15 jmcneill printf("%s: set flow table entry timeout\n", DEVNAME(sc));
6039 1.1 jmcneill goto free;
6040 1.1 jmcneill }
6041 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6042 1.15 jmcneill printf("%s: set flow table entry command corrupt\n",
6043 1.1 jmcneill DEVNAME(sc));
6044 1.1 jmcneill goto free;
6045 1.1 jmcneill }
6046 1.1 jmcneill
6047 1.1 jmcneill out = mcx_cmdq_out(cqe);
6048 1.1 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
6049 1.15 jmcneill printf("%s: set flow table entry failed (%x, %x)\n",
6050 1.15 jmcneill DEVNAME(sc), out->cmd_status, be32toh(out->cmd_syndrome));
6051 1.1 jmcneill error = -1;
6052 1.1 jmcneill goto free;
6053 1.1 jmcneill }
6054 1.1 jmcneill
6055 1.1 jmcneill free:
6056 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
6057 1.1 jmcneill return (error);
6058 1.1 jmcneill }
6059 1.1 jmcneill
6060 1.15 jmcneill static int
6061 1.15 jmcneill mcx_delete_flow_table_entry(struct mcx_softc *sc, int group, int index)
6062 1.1 jmcneill {
6063 1.15 jmcneill struct mcx_cmdq_entry *cqe;
6064 1.1 jmcneill struct mcx_dmamem mxm;
6065 1.15 jmcneill struct mcx_cmd_delete_flow_table_entry_in *in;
6066 1.15 jmcneill struct mcx_cmd_delete_flow_table_entry_mb_in *mbin;
6067 1.15 jmcneill struct mcx_cmd_delete_flow_table_entry_out *out;
6068 1.15 jmcneill struct mcx_flow_group *mfg;
6069 1.1 jmcneill int error;
6070 1.15 jmcneill int token;
6071 1.15 jmcneill
6072 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6073 1.15 jmcneill token = mcx_cmdq_token(sc);
6074 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin), sizeof(*out),
6075 1.15 jmcneill token);
6076 1.15 jmcneill
6077 1.15 jmcneill in = mcx_cmdq_in(cqe);
6078 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_DELETE_FLOW_TABLE_ENTRY);
6079 1.15 jmcneill in->cmd_op_mod = htobe16(0);
6080 1.15 jmcneill
6081 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6082 1.15 jmcneill &cqe->cq_input_ptr, token) != 0) {
6083 1.15 jmcneill printf("%s: unable to allocate "
6084 1.15 jmcneill "delete flow table entry mailbox\n", DEVNAME(sc));
6085 1.15 jmcneill return (-1);
6086 1.15 jmcneill }
6087 1.15 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6088 1.15 jmcneill mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
6089 1.15 jmcneill
6090 1.15 jmcneill mfg = &sc->sc_flow_group[group];
6091 1.15 jmcneill mbin->cmd_table_id = htobe32(mfg->g_table);
6092 1.15 jmcneill mbin->cmd_flow_index = htobe32(mfg->g_start + index);
6093 1.15 jmcneill
6094 1.15 jmcneill mcx_cmdq_mboxes_sign(&mxm, 2);
6095 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
6096 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6097 1.15 jmcneill if (error != 0) {
6098 1.15 jmcneill printf("%s: delete flow table entry timeout\n", DEVNAME(sc));
6099 1.15 jmcneill goto free;
6100 1.15 jmcneill }
6101 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6102 1.15 jmcneill printf("%s: delete flow table entry command corrupt\n",
6103 1.15 jmcneill DEVNAME(sc));
6104 1.15 jmcneill goto free;
6105 1.15 jmcneill }
6106 1.15 jmcneill
6107 1.15 jmcneill out = mcx_cmdq_out(cqe);
6108 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
6109 1.15 jmcneill printf("%s: delete flow table entry %d:%d failed (%x, %x)\n",
6110 1.15 jmcneill DEVNAME(sc), group, index, out->cmd_status,
6111 1.15 jmcneill be32toh(out->cmd_syndrome));
6112 1.15 jmcneill error = -1;
6113 1.15 jmcneill goto free;
6114 1.15 jmcneill }
6115 1.15 jmcneill
6116 1.15 jmcneill free:
6117 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
6118 1.15 jmcneill return (error);
6119 1.15 jmcneill }
6120 1.15 jmcneill
6121 1.15 jmcneill #if 0
6122 1.15 jmcneill int
6123 1.15 jmcneill mcx_dump_flow_table(struct mcx_softc *sc, int flow_table_id)
6124 1.15 jmcneill {
6125 1.15 jmcneill struct mcx_dmamem mxm;
6126 1.15 jmcneill struct mcx_cmdq_entry *cqe;
6127 1.15 jmcneill struct mcx_cmd_query_flow_table_in *in;
6128 1.15 jmcneill struct mcx_cmd_query_flow_table_mb_in *mbin;
6129 1.15 jmcneill struct mcx_cmd_query_flow_table_out *out;
6130 1.15 jmcneill struct mcx_cmd_query_flow_table_mb_out *mbout;
6131 1.15 jmcneill uint8_t token = mcx_cmdq_token(sc);
6132 1.15 jmcneill int error;
6133 1.15 jmcneill int i;
6134 1.15 jmcneill uint8_t *dump;
6135 1.1 jmcneill
6136 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6137 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
6138 1.1 jmcneill sizeof(*out) + sizeof(*mbout) + 16, token);
6139 1.1 jmcneill
6140 1.1 jmcneill in = mcx_cmdq_in(cqe);
6141 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_FLOW_TABLE);
6142 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6143 1.1 jmcneill
6144 1.1 jmcneill CTASSERT(sizeof(*mbin) <= MCX_CMDQ_MAILBOX_DATASIZE);
6145 1.1 jmcneill CTASSERT(sizeof(*mbout) <= MCX_CMDQ_MAILBOX_DATASIZE);
6146 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6147 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
6148 1.1 jmcneill printf(", unable to allocate query flow table mailboxes\n");
6149 1.1 jmcneill return (-1);
6150 1.1 jmcneill }
6151 1.1 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
6152 1.1 jmcneill
6153 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6154 1.1 jmcneill mbin->cmd_table_type = 0;
6155 1.15 jmcneill mbin->cmd_table_id = htobe32(flow_table_id);
6156 1.1 jmcneill
6157 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6158 1.1 jmcneill
6159 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6160 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6161 1.1 jmcneill if (error != 0) {
6162 1.1 jmcneill printf("%s: query flow table timeout\n", DEVNAME(sc));
6163 1.1 jmcneill goto free;
6164 1.1 jmcneill }
6165 1.1 jmcneill error = mcx_cmdq_verify(cqe);
6166 1.1 jmcneill if (error != 0) {
6167 1.1 jmcneill printf("%s: query flow table reply corrupt\n", DEVNAME(sc));
6168 1.1 jmcneill goto free;
6169 1.1 jmcneill }
6170 1.1 jmcneill
6171 1.1 jmcneill out = mcx_cmdq_out(cqe);
6172 1.1 jmcneill switch (out->cmd_status) {
6173 1.1 jmcneill case MCX_CQ_STATUS_OK:
6174 1.1 jmcneill break;
6175 1.1 jmcneill default:
6176 1.1 jmcneill printf("%s: query flow table failed (%x/%x)\n", DEVNAME(sc),
6177 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6178 1.1 jmcneill error = -1;
6179 1.1 jmcneill goto free;
6180 1.1 jmcneill }
6181 1.1 jmcneill
6182 1.1 jmcneill mbout = (struct mcx_cmd_query_flow_table_mb_out *)
6183 1.1 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6184 1.1 jmcneill dump = (uint8_t *)mbout + 8;
6185 1.1 jmcneill for (i = 0; i < sizeof(struct mcx_flow_table_ctx); i++) {
6186 1.1 jmcneill printf("%.2x ", dump[i]);
6187 1.1 jmcneill if (i % 16 == 15)
6188 1.1 jmcneill printf("\n");
6189 1.1 jmcneill }
6190 1.1 jmcneill free:
6191 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
6192 1.1 jmcneill return (error);
6193 1.1 jmcneill }
6194 1.1 jmcneill int
6195 1.15 jmcneill mcx_dump_flow_table_entry(struct mcx_softc *sc, int flow_table_id, int index)
6196 1.1 jmcneill {
6197 1.1 jmcneill struct mcx_dmamem mxm;
6198 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6199 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_in *in;
6200 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_mb_in *mbin;
6201 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_out *out;
6202 1.1 jmcneill struct mcx_cmd_query_flow_table_entry_mb_out *mbout;
6203 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
6204 1.1 jmcneill int error;
6205 1.1 jmcneill int i;
6206 1.1 jmcneill uint8_t *dump;
6207 1.1 jmcneill
6208 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6209 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
6210 1.1 jmcneill sizeof(*out) + sizeof(*mbout) + 16, token);
6211 1.1 jmcneill
6212 1.1 jmcneill in = mcx_cmdq_in(cqe);
6213 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_FLOW_TABLE_ENTRY);
6214 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6215 1.1 jmcneill
6216 1.1 jmcneill CTASSERT(sizeof(*mbin) <= MCX_CMDQ_MAILBOX_DATASIZE);
6217 1.1 jmcneill CTASSERT(sizeof(*mbout) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6218 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6219 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
6220 1.15 jmcneill printf(", unable to allocate "
6221 1.15 jmcneill "query flow table entry mailboxes\n");
6222 1.1 jmcneill return (-1);
6223 1.1 jmcneill }
6224 1.1 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
6225 1.1 jmcneill
6226 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6227 1.1 jmcneill mbin->cmd_table_type = 0;
6228 1.15 jmcneill mbin->cmd_table_id = htobe32(flow_table_id);
6229 1.1 jmcneill mbin->cmd_flow_index = htobe32(index);
6230 1.1 jmcneill
6231 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6232 1.1 jmcneill
6233 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6234 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6235 1.1 jmcneill if (error != 0) {
6236 1.1 jmcneill printf("%s: query flow table entry timeout\n", DEVNAME(sc));
6237 1.1 jmcneill goto free;
6238 1.1 jmcneill }
6239 1.1 jmcneill error = mcx_cmdq_verify(cqe);
6240 1.1 jmcneill if (error != 0) {
6241 1.1 jmcneill printf("%s: query flow table entry reply corrupt\n",
6242 1.1 jmcneill DEVNAME(sc));
6243 1.1 jmcneill goto free;
6244 1.1 jmcneill }
6245 1.1 jmcneill
6246 1.1 jmcneill out = mcx_cmdq_out(cqe);
6247 1.1 jmcneill switch (out->cmd_status) {
6248 1.1 jmcneill case MCX_CQ_STATUS_OK:
6249 1.1 jmcneill break;
6250 1.1 jmcneill default:
6251 1.1 jmcneill printf("%s: query flow table entry failed (%x/%x)\n",
6252 1.1 jmcneill DEVNAME(sc), out->cmd_status, be32toh(out->cmd_syndrome));
6253 1.1 jmcneill error = -1;
6254 1.1 jmcneill goto free;
6255 1.1 jmcneill }
6256 1.1 jmcneill
6257 1.1 jmcneill mbout = (struct mcx_cmd_query_flow_table_entry_mb_out *)
6258 1.1 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6259 1.1 jmcneill dump = (uint8_t *)mbout;
6260 1.1 jmcneill for (i = 0; i < MCX_CMDQ_MAILBOX_DATASIZE; i++) {
6261 1.1 jmcneill printf("%.2x ", dump[i]);
6262 1.1 jmcneill if (i % 16 == 15)
6263 1.1 jmcneill printf("\n");
6264 1.1 jmcneill }
6265 1.1 jmcneill
6266 1.1 jmcneill free:
6267 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
6268 1.1 jmcneill return (error);
6269 1.1 jmcneill }
6270 1.1 jmcneill
6271 1.1 jmcneill int
6272 1.15 jmcneill mcx_dump_flow_group(struct mcx_softc *sc, int flow_table_id)
6273 1.1 jmcneill {
6274 1.1 jmcneill struct mcx_dmamem mxm;
6275 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6276 1.1 jmcneill struct mcx_cmd_query_flow_group_in *in;
6277 1.1 jmcneill struct mcx_cmd_query_flow_group_mb_in *mbin;
6278 1.1 jmcneill struct mcx_cmd_query_flow_group_out *out;
6279 1.1 jmcneill struct mcx_cmd_query_flow_group_mb_out *mbout;
6280 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
6281 1.1 jmcneill int error;
6282 1.1 jmcneill int i;
6283 1.1 jmcneill uint8_t *dump;
6284 1.1 jmcneill
6285 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6286 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
6287 1.1 jmcneill sizeof(*out) + sizeof(*mbout) + 16, token);
6288 1.1 jmcneill
6289 1.1 jmcneill in = mcx_cmdq_in(cqe);
6290 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_FLOW_GROUP);
6291 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6292 1.1 jmcneill
6293 1.1 jmcneill CTASSERT(sizeof(*mbin) <= MCX_CMDQ_MAILBOX_DATASIZE);
6294 1.1 jmcneill CTASSERT(sizeof(*mbout) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6295 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6296 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
6297 1.1 jmcneill printf(", unable to allocate query flow group mailboxes\n");
6298 1.1 jmcneill return (-1);
6299 1.1 jmcneill }
6300 1.1 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
6301 1.1 jmcneill
6302 1.1 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6303 1.1 jmcneill mbin->cmd_table_type = 0;
6304 1.15 jmcneill mbin->cmd_table_id = htobe32(flow_table_id);
6305 1.1 jmcneill mbin->cmd_group_id = htobe32(sc->sc_flow_group_id);
6306 1.1 jmcneill
6307 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6308 1.1 jmcneill
6309 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6310 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6311 1.1 jmcneill if (error != 0) {
6312 1.1 jmcneill printf("%s: query flow group timeout\n", DEVNAME(sc));
6313 1.1 jmcneill goto free;
6314 1.1 jmcneill }
6315 1.1 jmcneill error = mcx_cmdq_verify(cqe);
6316 1.1 jmcneill if (error != 0) {
6317 1.1 jmcneill printf("%s: query flow group reply corrupt\n", DEVNAME(sc));
6318 1.1 jmcneill goto free;
6319 1.1 jmcneill }
6320 1.1 jmcneill
6321 1.1 jmcneill out = mcx_cmdq_out(cqe);
6322 1.1 jmcneill switch (out->cmd_status) {
6323 1.1 jmcneill case MCX_CQ_STATUS_OK:
6324 1.1 jmcneill break;
6325 1.1 jmcneill default:
6326 1.1 jmcneill printf("%s: query flow group failed (%x/%x)\n", DEVNAME(sc),
6327 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6328 1.1 jmcneill error = -1;
6329 1.1 jmcneill goto free;
6330 1.1 jmcneill }
6331 1.1 jmcneill
6332 1.1 jmcneill mbout = (struct mcx_cmd_query_flow_group_mb_out *)
6333 1.1 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6334 1.1 jmcneill dump = (uint8_t *)mbout;
6335 1.1 jmcneill for (i = 0; i < MCX_CMDQ_MAILBOX_DATASIZE; i++) {
6336 1.1 jmcneill printf("%.2x ", dump[i]);
6337 1.1 jmcneill if (i % 16 == 15)
6338 1.1 jmcneill printf("\n");
6339 1.1 jmcneill }
6340 1.1 jmcneill dump = (uint8_t *)(mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 1)));
6341 1.1 jmcneill for (i = 0; i < MCX_CMDQ_MAILBOX_DATASIZE; i++) {
6342 1.1 jmcneill printf("%.2x ", dump[i]);
6343 1.1 jmcneill if (i % 16 == 15)
6344 1.1 jmcneill printf("\n");
6345 1.1 jmcneill }
6346 1.1 jmcneill
6347 1.1 jmcneill free:
6348 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
6349 1.1 jmcneill return (error);
6350 1.1 jmcneill }
6351 1.1 jmcneill
6352 1.15 jmcneill static int
6353 1.15 jmcneill mcx_dump_counters(struct mcx_softc *sc)
6354 1.15 jmcneill {
6355 1.15 jmcneill struct mcx_dmamem mxm;
6356 1.15 jmcneill struct mcx_cmdq_entry *cqe;
6357 1.15 jmcneill struct mcx_cmd_query_vport_counters_in *in;
6358 1.15 jmcneill struct mcx_cmd_query_vport_counters_mb_in *mbin;
6359 1.15 jmcneill struct mcx_cmd_query_vport_counters_out *out;
6360 1.15 jmcneill struct mcx_nic_vport_counters *counters;
6361 1.15 jmcneill int error, token;
6362 1.15 jmcneill
6363 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6364 1.15 jmcneill token = mcx_cmdq_token(sc);
6365 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin),
6366 1.15 jmcneill sizeof(*out) + sizeof(*counters), token);
6367 1.15 jmcneill
6368 1.15 jmcneill in = mcx_cmdq_in(cqe);
6369 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_VPORT_COUNTERS);
6370 1.15 jmcneill in->cmd_op_mod = htobe16(0);
6371 1.15 jmcneill
6372 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
6373 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
6374 1.15 jmcneill printf(", unable to allocate "
6375 1.15 jmcneill "query nic vport counters mailboxen\n");
6376 1.15 jmcneill return (-1);
6377 1.15 jmcneill }
6378 1.15 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
6379 1.15 jmcneill
6380 1.15 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6381 1.15 jmcneill mbin->cmd_clear = 0x80;
6382 1.15 jmcneill
6383 1.15 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6384 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
6385 1.15 jmcneill
6386 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6387 1.15 jmcneill if (error != 0) {
6388 1.15 jmcneill printf("%s: query nic vport counters timeout\n", DEVNAME(sc));
6389 1.15 jmcneill goto free;
6390 1.15 jmcneill }
6391 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6392 1.15 jmcneill printf("%s: query nic vport counters command corrupt\n",
6393 1.15 jmcneill DEVNAME(sc));
6394 1.15 jmcneill goto free;
6395 1.15 jmcneill }
6396 1.15 jmcneill
6397 1.15 jmcneill out = mcx_cmdq_out(cqe);
6398 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
6399 1.15 jmcneill printf("%s: query nic vport counters failed (%x, %x)\n",
6400 1.15 jmcneill DEVNAME(sc), out->cmd_status, betoh32(out->cmd_syndrome));
6401 1.15 jmcneill error = -1;
6402 1.15 jmcneill goto free;
6403 1.15 jmcneill }
6404 1.15 jmcneill
6405 1.15 jmcneill counters = (struct mcx_nic_vport_counters *)
6406 1.15 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6407 1.15 jmcneill if (counters->rx_bcast.packets + counters->tx_bcast.packets +
6408 1.15 jmcneill counters->rx_ucast.packets + counters->tx_ucast.packets +
6409 1.15 jmcneill counters->rx_err.packets + counters->tx_err.packets)
6410 1.15 jmcneill printf("%s: err %llx/%llx uc %llx/%llx bc %llx/%llx\n",
6411 1.15 jmcneill DEVNAME(sc),
6412 1.15 jmcneill betoh64(counters->tx_err.packets),
6413 1.15 jmcneill betoh64(counters->rx_err.packets),
6414 1.15 jmcneill betoh64(counters->tx_ucast.packets),
6415 1.15 jmcneill betoh64(counters->rx_ucast.packets),
6416 1.15 jmcneill betoh64(counters->tx_bcast.packets),
6417 1.15 jmcneill betoh64(counters->rx_bcast.packets));
6418 1.15 jmcneill free:
6419 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
6420 1.15 jmcneill
6421 1.15 jmcneill return (error);
6422 1.15 jmcneill }
6423 1.15 jmcneill
6424 1.15 jmcneill static int
6425 1.15 jmcneill mcx_dump_flow_counter(struct mcx_softc *sc, int index, const char *what)
6426 1.15 jmcneill {
6427 1.15 jmcneill struct mcx_dmamem mxm;
6428 1.15 jmcneill struct mcx_cmdq_entry *cqe;
6429 1.15 jmcneill struct mcx_cmd_query_flow_counter_in *in;
6430 1.15 jmcneill struct mcx_cmd_query_flow_counter_mb_in *mbin;
6431 1.15 jmcneill struct mcx_cmd_query_flow_counter_out *out;
6432 1.15 jmcneill struct mcx_counter *counters;
6433 1.15 jmcneill int error, token;
6434 1.15 jmcneill
6435 1.15 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6436 1.15 jmcneill token = mcx_cmdq_token(sc);
6437 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin), sizeof(*out) +
6438 1.15 jmcneill sizeof(*counters), token);
6439 1.15 jmcneill
6440 1.15 jmcneill in = mcx_cmdq_in(cqe);
6441 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_FLOW_COUNTER);
6442 1.15 jmcneill in->cmd_op_mod = htobe16(0);
6443 1.15 jmcneill
6444 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1,
6445 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
6446 1.15 jmcneill printf(", unable to allocate query flow counter mailboxen\n");
6447 1.15 jmcneill return (-1);
6448 1.15 jmcneill }
6449 1.15 jmcneill cqe->cq_input_ptr = cqe->cq_output_ptr;
6450 1.15 jmcneill mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
6451 1.15 jmcneill mbin->cmd_flow_counter_id = htobe16(sc->sc_flow_counter_id[index]);
6452 1.15 jmcneill mbin->cmd_clear = 0x80;
6453 1.15 jmcneill
6454 1.15 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6455 1.15 jmcneill mcx_cmdq_post(sc, cqe, 0);
6456 1.15 jmcneill
6457 1.15 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6458 1.15 jmcneill if (error != 0) {
6459 1.15 jmcneill printf("%s: query flow counter timeout\n", DEVNAME(sc));
6460 1.15 jmcneill goto free;
6461 1.15 jmcneill }
6462 1.15 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6463 1.15 jmcneill printf("%s: query flow counter command corrupt\n", DEVNAME(sc));
6464 1.15 jmcneill goto free;
6465 1.15 jmcneill }
6466 1.15 jmcneill
6467 1.15 jmcneill out = mcx_cmdq_out(cqe);
6468 1.15 jmcneill if (out->cmd_status != MCX_CQ_STATUS_OK) {
6469 1.15 jmcneill printf("%s: query flow counter failed (%x, %x)\n", DEVNAME(sc),
6470 1.15 jmcneill out->cmd_status, betoh32(out->cmd_syndrome));
6471 1.15 jmcneill error = -1;
6472 1.15 jmcneill goto free;
6473 1.15 jmcneill }
6474 1.15 jmcneill
6475 1.15 jmcneill counters = (struct mcx_counter *)
6476 1.15 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6477 1.15 jmcneill if (counters->packets)
6478 1.15 jmcneill printf("%s: %s inflow %llx\n", DEVNAME(sc), what,
6479 1.15 jmcneill betoh64(counters->packets));
6480 1.15 jmcneill free:
6481 1.15 jmcneill mcx_dmamem_free(sc, &mxm);
6482 1.15 jmcneill
6483 1.15 jmcneill return (error);
6484 1.15 jmcneill }
6485 1.15 jmcneill
6486 1.15 jmcneill #endif
6487 1.15 jmcneill
6488 1.15 jmcneill #if NKSTAT > 0
6489 1.15 jmcneill
6490 1.1 jmcneill int
6491 1.15 jmcneill mcx_query_rq(struct mcx_softc *sc, struct mcx_rx *rx, struct mcx_rq_ctx *rq_ctx)
6492 1.1 jmcneill {
6493 1.1 jmcneill struct mcx_dmamem mxm;
6494 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6495 1.1 jmcneill struct mcx_cmd_query_rq_in *in;
6496 1.1 jmcneill struct mcx_cmd_query_rq_out *out;
6497 1.1 jmcneill struct mcx_cmd_query_rq_mb_out *mbout;
6498 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
6499 1.1 jmcneill int error;
6500 1.1 jmcneill
6501 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6502 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*mbout) + 16,
6503 1.1 jmcneill token);
6504 1.1 jmcneill
6505 1.1 jmcneill in = mcx_cmdq_in(cqe);
6506 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_RQ);
6507 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6508 1.15 jmcneill in->cmd_rqn = htobe32(rx->rx_rqn);
6509 1.1 jmcneill
6510 1.1 jmcneill CTASSERT(sizeof(*mbout) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6511 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6512 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
6513 1.15 jmcneill printf("%s: unable to allocate query rq mailboxes\n", DEVNAME(sc));
6514 1.1 jmcneill return (-1);
6515 1.1 jmcneill }
6516 1.1 jmcneill
6517 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6518 1.1 jmcneill
6519 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6520 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6521 1.1 jmcneill if (error != 0) {
6522 1.1 jmcneill printf("%s: query rq timeout\n", DEVNAME(sc));
6523 1.1 jmcneill goto free;
6524 1.1 jmcneill }
6525 1.1 jmcneill error = mcx_cmdq_verify(cqe);
6526 1.1 jmcneill if (error != 0) {
6527 1.1 jmcneill printf("%s: query rq reply corrupt\n", DEVNAME(sc));
6528 1.1 jmcneill goto free;
6529 1.1 jmcneill }
6530 1.1 jmcneill
6531 1.1 jmcneill out = mcx_cmdq_out(cqe);
6532 1.1 jmcneill switch (out->cmd_status) {
6533 1.1 jmcneill case MCX_CQ_STATUS_OK:
6534 1.1 jmcneill break;
6535 1.1 jmcneill default:
6536 1.1 jmcneill printf("%s: query rq failed (%x/%x)\n", DEVNAME(sc),
6537 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6538 1.1 jmcneill error = -1;
6539 1.1 jmcneill goto free;
6540 1.1 jmcneill }
6541 1.1 jmcneill
6542 1.1 jmcneill mbout = (struct mcx_cmd_query_rq_mb_out *)
6543 1.1 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6544 1.15 jmcneill memcpy(rq_ctx, &mbout->cmd_ctx, sizeof(*rq_ctx));
6545 1.1 jmcneill
6546 1.1 jmcneill free:
6547 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
6548 1.1 jmcneill return (error);
6549 1.1 jmcneill }
6550 1.1 jmcneill
6551 1.1 jmcneill int
6552 1.15 jmcneill mcx_query_sq(struct mcx_softc *sc, struct mcx_tx *tx, struct mcx_sq_ctx *sq_ctx)
6553 1.1 jmcneill {
6554 1.1 jmcneill struct mcx_dmamem mxm;
6555 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6556 1.1 jmcneill struct mcx_cmd_query_sq_in *in;
6557 1.1 jmcneill struct mcx_cmd_query_sq_out *out;
6558 1.1 jmcneill struct mcx_cmd_query_sq_mb_out *mbout;
6559 1.1 jmcneill uint8_t token = mcx_cmdq_token(sc);
6560 1.1 jmcneill int error;
6561 1.1 jmcneill
6562 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6563 1.1 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*mbout) + 16,
6564 1.1 jmcneill token);
6565 1.1 jmcneill
6566 1.1 jmcneill in = mcx_cmdq_in(cqe);
6567 1.1 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_SQ);
6568 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6569 1.15 jmcneill in->cmd_sqn = htobe32(tx->tx_sqn);
6570 1.1 jmcneill
6571 1.1 jmcneill CTASSERT(sizeof(*mbout) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6572 1.1 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6573 1.1 jmcneill &cqe->cq_output_ptr, token) != 0) {
6574 1.15 jmcneill printf("%s: unable to allocate query sq mailboxes\n", DEVNAME(sc));
6575 1.1 jmcneill return (-1);
6576 1.1 jmcneill }
6577 1.1 jmcneill
6578 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6579 1.1 jmcneill
6580 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6581 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6582 1.1 jmcneill if (error != 0) {
6583 1.1 jmcneill printf("%s: query sq timeout\n", DEVNAME(sc));
6584 1.1 jmcneill goto free;
6585 1.1 jmcneill }
6586 1.1 jmcneill error = mcx_cmdq_verify(cqe);
6587 1.1 jmcneill if (error != 0) {
6588 1.1 jmcneill printf("%s: query sq reply corrupt\n", DEVNAME(sc));
6589 1.1 jmcneill goto free;
6590 1.1 jmcneill }
6591 1.1 jmcneill
6592 1.1 jmcneill out = mcx_cmdq_out(cqe);
6593 1.1 jmcneill switch (out->cmd_status) {
6594 1.1 jmcneill case MCX_CQ_STATUS_OK:
6595 1.1 jmcneill break;
6596 1.1 jmcneill default:
6597 1.1 jmcneill printf("%s: query sq failed (%x/%x)\n", DEVNAME(sc),
6598 1.1 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6599 1.1 jmcneill error = -1;
6600 1.1 jmcneill goto free;
6601 1.1 jmcneill }
6602 1.1 jmcneill
6603 1.1 jmcneill mbout = (struct mcx_cmd_query_sq_mb_out *)
6604 1.1 jmcneill (mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6605 1.15 jmcneill memcpy(sq_ctx, &mbout->cmd_ctx, sizeof(*sq_ctx));
6606 1.1 jmcneill
6607 1.1 jmcneill free:
6608 1.1 jmcneill mcx_cq_mboxes_free(sc, &mxm);
6609 1.1 jmcneill return (error);
6610 1.1 jmcneill }
6611 1.1 jmcneill
6612 1.15 jmcneill int
6613 1.15 jmcneill mcx_query_cq(struct mcx_softc *sc, struct mcx_cq *cq, struct mcx_cq_ctx *cq_ctx)
6614 1.1 jmcneill {
6615 1.1 jmcneill struct mcx_dmamem mxm;
6616 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6617 1.15 jmcneill struct mcx_cmd_query_cq_in *in;
6618 1.15 jmcneill struct mcx_cmd_query_cq_out *out;
6619 1.15 jmcneill struct mcx_cq_ctx *ctx;
6620 1.15 jmcneill uint8_t token = mcx_cmdq_token(sc);
6621 1.15 jmcneill int error;
6622 1.1 jmcneill
6623 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6624 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*ctx) + 16,
6625 1.15 jmcneill token);
6626 1.1 jmcneill
6627 1.1 jmcneill in = mcx_cmdq_in(cqe);
6628 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_CQ);
6629 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6630 1.15 jmcneill in->cmd_cqn = htobe32(cq->cq_n);
6631 1.1 jmcneill
6632 1.15 jmcneill CTASSERT(sizeof(*ctx) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6633 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6634 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
6635 1.15 jmcneill printf("%s: unable to allocate query cq mailboxes\n",
6636 1.15 jmcneill DEVNAME(sc));
6637 1.1 jmcneill return (-1);
6638 1.1 jmcneill }
6639 1.1 jmcneill
6640 1.15 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6641 1.1 jmcneill
6642 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6643 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6644 1.1 jmcneill if (error != 0) {
6645 1.15 jmcneill printf("%s: query cq timeout\n", DEVNAME(sc));
6646 1.1 jmcneill goto free;
6647 1.1 jmcneill }
6648 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6649 1.15 jmcneill printf("%s: query cq reply corrupt\n", DEVNAME(sc));
6650 1.1 jmcneill goto free;
6651 1.1 jmcneill }
6652 1.1 jmcneill
6653 1.1 jmcneill out = mcx_cmdq_out(cqe);
6654 1.15 jmcneill switch (out->cmd_status) {
6655 1.15 jmcneill case MCX_CQ_STATUS_OK:
6656 1.15 jmcneill break;
6657 1.15 jmcneill default:
6658 1.15 jmcneill printf("%s: query qc failed (%x/%x)\n", DEVNAME(sc),
6659 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6660 1.1 jmcneill error = -1;
6661 1.1 jmcneill goto free;
6662 1.1 jmcneill }
6663 1.1 jmcneill
6664 1.15 jmcneill ctx = (struct mcx_cq_ctx *)(mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6665 1.15 jmcneill memcpy(cq_ctx, ctx, sizeof(*cq_ctx));
6666 1.1 jmcneill free:
6667 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
6668 1.1 jmcneill return (error);
6669 1.1 jmcneill }
6670 1.1 jmcneill
6671 1.15 jmcneill int
6672 1.15 jmcneill mcx_query_eq(struct mcx_softc *sc, struct mcx_eq *eq, struct mcx_eq_ctx *eq_ctx)
6673 1.1 jmcneill {
6674 1.1 jmcneill struct mcx_dmamem mxm;
6675 1.1 jmcneill struct mcx_cmdq_entry *cqe;
6676 1.15 jmcneill struct mcx_cmd_query_eq_in *in;
6677 1.15 jmcneill struct mcx_cmd_query_eq_out *out;
6678 1.15 jmcneill struct mcq_eq_ctx *ctx;
6679 1.15 jmcneill uint8_t token = mcx_cmdq_token(sc);
6680 1.15 jmcneill int error;
6681 1.1 jmcneill
6682 1.1 jmcneill cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
6683 1.15 jmcneill mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out) + sizeof(*ctx) + 16,
6684 1.15 jmcneill token);
6685 1.1 jmcneill
6686 1.1 jmcneill in = mcx_cmdq_in(cqe);
6687 1.15 jmcneill in->cmd_opcode = htobe16(MCX_CMD_QUERY_EQ);
6688 1.1 jmcneill in->cmd_op_mod = htobe16(0);
6689 1.15 jmcneill in->cmd_eqn = htobe32(eq->eq_n);
6690 1.1 jmcneill
6691 1.15 jmcneill CTASSERT(sizeof(*ctx) <= MCX_CMDQ_MAILBOX_DATASIZE*2);
6692 1.15 jmcneill if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2,
6693 1.15 jmcneill &cqe->cq_output_ptr, token) != 0) {
6694 1.15 jmcneill printf("%s: unable to allocate query eq mailboxes\n",
6695 1.15 jmcneill DEVNAME(sc));
6696 1.1 jmcneill return (-1);
6697 1.1 jmcneill }
6698 1.1 jmcneill
6699 1.1 jmcneill mcx_cmdq_mboxes_sign(&mxm, 1);
6700 1.15 jmcneill
6701 1.1 jmcneill mcx_cmdq_post(sc, cqe, 0);
6702 1.1 jmcneill error = mcx_cmdq_poll(sc, cqe, 1000);
6703 1.1 jmcneill if (error != 0) {
6704 1.15 jmcneill printf("%s: query eq timeout\n", DEVNAME(sc));
6705 1.1 jmcneill goto free;
6706 1.1 jmcneill }
6707 1.1 jmcneill if (mcx_cmdq_verify(cqe) != 0) {
6708 1.15 jmcneill printf("%s: query eq reply corrupt\n", DEVNAME(sc));
6709 1.1 jmcneill goto free;
6710 1.1 jmcneill }
6711 1.1 jmcneill
6712 1.1 jmcneill out = mcx_cmdq_out(cqe);
6713 1.15 jmcneill switch (out->cmd_status) {
6714 1.15 jmcneill case MCX_CQ_STATUS_OK:
6715 1.15 jmcneill break;
6716 1.15 jmcneill default:
6717 1.15 jmcneill printf("%s: query eq failed (%x/%x)\n", DEVNAME(sc),
6718 1.15 jmcneill out->cmd_status, be32toh(out->cmd_syndrome));
6719 1.1 jmcneill error = -1;
6720 1.1 jmcneill goto free;
6721 1.1 jmcneill }
6722 1.1 jmcneill
6723 1.15 jmcneill ctx = (struct mcx_eq_ctx *)(mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0)));
6724 1.15 jmcneill memcpy(eq_ctx, ctx, sizeof(*eq_ctx));
6725 1.1 jmcneill free:
6726 1.1 jmcneill mcx_dmamem_free(sc, &mxm);
6727 1.1 jmcneill return (error);
6728 1.1 jmcneill }
6729 1.1 jmcneill
6730 1.15 jmcneill #endif /* NKSTAT > 0 */
6731 1.15 jmcneill
6732 1.1 jmcneill
6733 1.15 jmcneill static inline unsigned int
6734 1.15 jmcneill mcx_rx_fill_slots(struct mcx_softc *sc, struct mcx_rx *rx, uint nslots)
6735 1.1 jmcneill {
6736 1.15 jmcneill struct mcx_rq_entry *ring, *rqe;
6737 1.1 jmcneill struct mcx_slot *ms;
6738 1.1 jmcneill struct mbuf *m;
6739 1.1 jmcneill uint slot, p, fills;
6740 1.1 jmcneill
6741 1.15 jmcneill ring = MCX_DMA_KVA(&rx->rx_rq_mem);
6742 1.15 jmcneill p = rx->rx_prod;
6743 1.15 jmcneill
6744 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&rx->rx_rq_mem),
6745 1.15 jmcneill 0, MCX_DMA_LEN(&rx->rx_rq_mem), BUS_DMASYNC_POSTWRITE);
6746 1.15 jmcneill
6747 1.1 jmcneill slot = (p % (1 << MCX_LOG_RQ_SIZE));
6748 1.1 jmcneill rqe = ring;
6749 1.1 jmcneill for (fills = 0; fills < nslots; fills++) {
6750 1.15 jmcneill slot = p % (1 << MCX_LOG_RQ_SIZE);
6751 1.15 jmcneill
6752 1.15 jmcneill ms = &rx->rx_slots[slot];
6753 1.15 jmcneill rqe = &ring[slot];
6754 1.15 jmcneill
6755 1.1 jmcneill m = NULL;
6756 1.1 jmcneill MGETHDR(m, M_DONTWAIT, MT_DATA);
6757 1.1 jmcneill if (m == NULL)
6758 1.1 jmcneill break;
6759 1.1 jmcneill
6760 1.1 jmcneill MCLGET(m, M_DONTWAIT);
6761 1.1 jmcneill if ((m->m_flags & M_EXT) == 0) {
6762 1.1 jmcneill m_freem(m);
6763 1.1 jmcneill break;
6764 1.1 jmcneill }
6765 1.1 jmcneill
6766 1.15 jmcneill m->m_len = m->m_pkthdr.len = sc->sc_hardmtu;
6767 1.15 jmcneill m_adj(m, m->m_ext.ext_size - sc->sc_rxbufsz);
6768 1.15 jmcneill m_adj(m, ETHER_ALIGN);
6769 1.15 jmcneill
6770 1.1 jmcneill if (bus_dmamap_load_mbuf(sc->sc_dmat, ms->ms_map, m,
6771 1.1 jmcneill BUS_DMA_NOWAIT) != 0) {
6772 1.1 jmcneill m_freem(m);
6773 1.1 jmcneill break;
6774 1.1 jmcneill }
6775 1.3 tnn bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, ms->ms_map->dm_mapsize, BUS_DMASYNC_PREREAD);
6776 1.1 jmcneill ms->ms_m = m;
6777 1.1 jmcneill
6778 1.15 jmcneill be32enc(&rqe->rqe_byte_count, ms->ms_map->dm_segs[0].ds_len);
6779 1.15 jmcneill be64enc(&rqe->rqe_addr, ms->ms_map->dm_segs[0].ds_addr);
6780 1.15 jmcneill be32enc(&rqe->rqe_lkey, sc->sc_lkey);
6781 1.1 jmcneill
6782 1.1 jmcneill p++;
6783 1.1 jmcneill }
6784 1.1 jmcneill
6785 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&rx->rx_rq_mem),
6786 1.15 jmcneill 0, MCX_DMA_LEN(&rx->rx_rq_mem), BUS_DMASYNC_PREWRITE);
6787 1.15 jmcneill
6788 1.15 jmcneill rx->rx_prod = p;
6789 1.1 jmcneill
6790 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
6791 1.15 jmcneill rx->rx_doorbell, sizeof(uint32_t), BUS_DMASYNC_POSTWRITE);
6792 1.15 jmcneill be32enc(MCX_DMA_OFF(&sc->sc_doorbell_mem, rx->rx_doorbell),
6793 1.15 jmcneill p & MCX_WQ_DOORBELL_MASK);
6794 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
6795 1.15 jmcneill rx->rx_doorbell, sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
6796 1.1 jmcneill
6797 1.1 jmcneill return (nslots - fills);
6798 1.1 jmcneill }
6799 1.1 jmcneill
6800 1.1 jmcneill static int
6801 1.15 jmcneill mcx_rx_fill(struct mcx_softc *sc, struct mcx_rx *rx)
6802 1.1 jmcneill {
6803 1.1 jmcneill u_int slots;
6804 1.1 jmcneill
6805 1.15 jmcneill slots = mcx_rxr_get(&rx->rx_rxr, (1 << MCX_LOG_RQ_SIZE));
6806 1.1 jmcneill if (slots == 0)
6807 1.1 jmcneill return (1);
6808 1.1 jmcneill
6809 1.15 jmcneill slots = mcx_rx_fill_slots(sc, rx, slots);
6810 1.15 jmcneill mcx_rxr_put(&rx->rx_rxr, slots);
6811 1.1 jmcneill return (0);
6812 1.1 jmcneill }
6813 1.1 jmcneill
6814 1.1 jmcneill void
6815 1.15 jmcneill mcx_refill(void *xrx)
6816 1.1 jmcneill {
6817 1.15 jmcneill struct mcx_rx *rx = xrx;
6818 1.15 jmcneill struct mcx_softc *sc = rx->rx_softc;
6819 1.1 jmcneill
6820 1.15 jmcneill mcx_rx_fill(sc, rx);
6821 1.1 jmcneill
6822 1.15 jmcneill if (mcx_rxr_inuse(&rx->rx_rxr) == 0)
6823 1.15 jmcneill callout_schedule(&rx->rx_refill, 1);
6824 1.1 jmcneill }
6825 1.1 jmcneill
6826 1.15 jmcneill static int
6827 1.15 jmcneill mcx_process_txeof(struct mcx_softc *sc, struct mcx_tx *tx,
6828 1.15 jmcneill struct mcx_cq_entry *cqe)
6829 1.1 jmcneill {
6830 1.1 jmcneill struct mcx_slot *ms;
6831 1.1 jmcneill bus_dmamap_t map;
6832 1.1 jmcneill int slot, slots;
6833 1.1 jmcneill
6834 1.1 jmcneill slot = be16toh(cqe->cq_wqe_count) % (1 << MCX_LOG_SQ_SIZE);
6835 1.1 jmcneill
6836 1.15 jmcneill ms = &tx->tx_slots[slot];
6837 1.1 jmcneill map = ms->ms_map;
6838 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
6839 1.1 jmcneill BUS_DMASYNC_POSTWRITE);
6840 1.1 jmcneill
6841 1.1 jmcneill slots = 1;
6842 1.1 jmcneill if (map->dm_nsegs > 1)
6843 1.1 jmcneill slots += (map->dm_nsegs+2) / MCX_SQ_SEGS_PER_SLOT;
6844 1.1 jmcneill
6845 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, map);
6846 1.1 jmcneill m_freem(ms->ms_m);
6847 1.1 jmcneill ms->ms_m = NULL;
6848 1.15 jmcneill
6849 1.15 jmcneill return (slots);
6850 1.1 jmcneill }
6851 1.1 jmcneill
6852 1.1 jmcneill static uint64_t
6853 1.1 jmcneill mcx_uptime(void)
6854 1.1 jmcneill {
6855 1.1 jmcneill struct timespec ts;
6856 1.1 jmcneill
6857 1.1 jmcneill nanouptime(&ts);
6858 1.1 jmcneill
6859 1.1 jmcneill return ((uint64_t)ts.tv_sec * 1000000000 + (uint64_t)ts.tv_nsec);
6860 1.1 jmcneill }
6861 1.1 jmcneill
6862 1.1 jmcneill static void
6863 1.1 jmcneill mcx_calibrate_first(struct mcx_softc *sc)
6864 1.1 jmcneill {
6865 1.1 jmcneill struct mcx_calibration *c = &sc->sc_calibration[0];
6866 1.15 jmcneill int s;
6867 1.1 jmcneill
6868 1.1 jmcneill sc->sc_calibration_gen = 0;
6869 1.1 jmcneill
6870 1.15 jmcneill s = splhigh(); /* crit_enter? */
6871 1.1 jmcneill c->c_ubase = mcx_uptime();
6872 1.1 jmcneill c->c_tbase = mcx_timer(sc);
6873 1.15 jmcneill splx(s);
6874 1.15 jmcneill c->c_ratio = 0;
6875 1.1 jmcneill
6876 1.15 jmcneill #if notyet
6877 1.1 jmcneill callout_schedule(&sc->sc_calibrate, MCX_CALIBRATE_FIRST * hz);
6878 1.15 jmcneill #endif
6879 1.1 jmcneill }
6880 1.1 jmcneill
6881 1.15 jmcneill #define MCX_TIMESTAMP_SHIFT 24
6882 1.1 jmcneill
6883 1.1 jmcneill static void
6884 1.1 jmcneill mcx_calibrate(void *arg)
6885 1.1 jmcneill {
6886 1.1 jmcneill struct mcx_softc *sc = arg;
6887 1.1 jmcneill struct mcx_calibration *nc, *pc;
6888 1.15 jmcneill uint64_t udiff, tdiff;
6889 1.1 jmcneill unsigned int gen;
6890 1.15 jmcneill int s;
6891 1.1 jmcneill
6892 1.1 jmcneill if (!ISSET(sc->sc_ec.ec_if.if_flags, IFF_RUNNING))
6893 1.1 jmcneill return;
6894 1.1 jmcneill
6895 1.1 jmcneill callout_schedule(&sc->sc_calibrate, MCX_CALIBRATE_NORMAL * hz);
6896 1.1 jmcneill
6897 1.1 jmcneill gen = sc->sc_calibration_gen;
6898 1.1 jmcneill pc = &sc->sc_calibration[gen % __arraycount(sc->sc_calibration)];
6899 1.1 jmcneill gen++;
6900 1.1 jmcneill nc = &sc->sc_calibration[gen % __arraycount(sc->sc_calibration)];
6901 1.1 jmcneill
6902 1.1 jmcneill nc->c_uptime = pc->c_ubase;
6903 1.1 jmcneill nc->c_timestamp = pc->c_tbase;
6904 1.1 jmcneill
6905 1.15 jmcneill s = splhigh(); /* crit_enter? */
6906 1.1 jmcneill nc->c_ubase = mcx_uptime();
6907 1.1 jmcneill nc->c_tbase = mcx_timer(sc);
6908 1.15 jmcneill splx(s);
6909 1.1 jmcneill
6910 1.15 jmcneill udiff = nc->c_ubase - nc->c_uptime;
6911 1.15 jmcneill tdiff = nc->c_tbase - nc->c_timestamp;
6912 1.15 jmcneill
6913 1.15 jmcneill /*
6914 1.15 jmcneill * udiff is the wall clock time between calibration ticks,
6915 1.15 jmcneill * which should be 32 seconds or 32 billion nanoseconds. if
6916 1.15 jmcneill * we squint, 1 billion nanoseconds is kind of like a 32 bit
6917 1.15 jmcneill * number, so 32 billion should still have a lot of high bits
6918 1.15 jmcneill * spare. we use this space by shifting the nanoseconds up
6919 1.15 jmcneill * 24 bits so we have a nice big number to divide by the
6920 1.15 jmcneill * number of mcx timer ticks.
6921 1.15 jmcneill */
6922 1.15 jmcneill nc->c_ratio = (udiff << MCX_TIMESTAMP_SHIFT) / tdiff;
6923 1.1 jmcneill
6924 1.1 jmcneill membar_producer();
6925 1.1 jmcneill sc->sc_calibration_gen = gen;
6926 1.1 jmcneill }
6927 1.1 jmcneill
6928 1.1 jmcneill static int
6929 1.15 jmcneill mcx_process_rx(struct mcx_softc *sc, struct mcx_rx *rx,
6930 1.15 jmcneill struct mcx_cq_entry *cqe, struct mcx_mbufq *mq,
6931 1.15 jmcneill const struct mcx_calibration *c)
6932 1.1 jmcneill {
6933 1.15 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
6934 1.1 jmcneill struct mcx_slot *ms;
6935 1.1 jmcneill struct mbuf *m;
6936 1.20 jmcneill uint32_t flags, len;
6937 1.1 jmcneill int slot;
6938 1.1 jmcneill
6939 1.20 jmcneill len = be32dec(&cqe->cq_byte_cnt);
6940 1.1 jmcneill slot = be16toh(cqe->cq_wqe_count) % (1 << MCX_LOG_RQ_SIZE);
6941 1.1 jmcneill
6942 1.15 jmcneill ms = &rx->rx_slots[slot];
6943 1.20 jmcneill bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, len, BUS_DMASYNC_POSTREAD);
6944 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, ms->ms_map);
6945 1.1 jmcneill
6946 1.1 jmcneill m = ms->ms_m;
6947 1.1 jmcneill ms->ms_m = NULL;
6948 1.1 jmcneill
6949 1.1 jmcneill m_set_rcvif(m, &sc->sc_ec.ec_if);
6950 1.20 jmcneill m->m_pkthdr.len = m->m_len = len;
6951 1.1 jmcneill
6952 1.1 jmcneill #if 0
6953 1.1 jmcneill if (cqe->cq_rx_hash_type) {
6954 1.15 jmcneill m->m_pkthdr.ph_flowid = be32toh(cqe->cq_rx_hash);
6955 1.15 jmcneill m->m_pkthdr.csum_flags |= M_FLOWID;
6956 1.1 jmcneill }
6957 1.1 jmcneill #endif
6958 1.1 jmcneill
6959 1.15 jmcneill flags = be32dec(&cqe->cq_flags);
6960 1.15 jmcneill if (flags & MCX_CQ_ENTRY_FLAGS_L3_OK) {
6961 1.15 jmcneill if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx)
6962 1.15 jmcneill m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
6963 1.15 jmcneill }
6964 1.15 jmcneill if (flags & MCX_CQ_ENTRY_FLAGS_L4_OK) {
6965 1.15 jmcneill if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx)
6966 1.15 jmcneill m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
6967 1.15 jmcneill if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx)
6968 1.15 jmcneill m->m_pkthdr.csum_flags |= M_CSUM_TCPv6;
6969 1.15 jmcneill if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx)
6970 1.15 jmcneill m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
6971 1.15 jmcneill if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx)
6972 1.15 jmcneill m->m_pkthdr.csum_flags |= M_CSUM_UDPv6;
6973 1.15 jmcneill }
6974 1.15 jmcneill if (flags & MCX_CQ_ENTRY_FLAGS_CV) {
6975 1.15 jmcneill vlan_set_tag(m, flags & MCX_CQ_ENTRY_FLAGS_VLAN_MASK);
6976 1.15 jmcneill }
6977 1.15 jmcneill
6978 1.15 jmcneill #if notyet
6979 1.15 jmcneill if (ISSET(sc->sc_ec.ec_if.if_flags, IFF_LINK0) && c->c_ratio) {
6980 1.15 jmcneill uint64_t t = be64dec(&cqe->cq_timestamp);
6981 1.15 jmcneill t -= c->c_timestamp;
6982 1.15 jmcneill t *= c->c_ratio;
6983 1.15 jmcneill t >>= MCX_TIMESTAMP_SHIFT;
6984 1.15 jmcneill t += c->c_uptime;
6985 1.1 jmcneill
6986 1.15 jmcneill m->m_pkthdr.ph_timestamp = t;
6987 1.1 jmcneill SET(m->m_pkthdr.csum_flags, M_TIMESTAMP);
6988 1.1 jmcneill }
6989 1.1 jmcneill #endif
6990 1.1 jmcneill
6991 1.1 jmcneill MBUFQ_ENQUEUE(mq, m);
6992 1.1 jmcneill
6993 1.1 jmcneill return (1);
6994 1.1 jmcneill }
6995 1.1 jmcneill
6996 1.1 jmcneill static struct mcx_cq_entry *
6997 1.1 jmcneill mcx_next_cq_entry(struct mcx_softc *sc, struct mcx_cq *cq)
6998 1.1 jmcneill {
6999 1.1 jmcneill struct mcx_cq_entry *cqe;
7000 1.1 jmcneill int next;
7001 1.1 jmcneill
7002 1.1 jmcneill cqe = (struct mcx_cq_entry *)MCX_DMA_KVA(&cq->cq_mem);
7003 1.1 jmcneill next = cq->cq_cons % (1 << MCX_LOG_CQ_SIZE);
7004 1.1 jmcneill
7005 1.1 jmcneill if ((cqe[next].cq_opcode_owner & MCX_CQ_ENTRY_FLAG_OWNER) ==
7006 1.1 jmcneill ((cq->cq_cons >> MCX_LOG_CQ_SIZE) & 1)) {
7007 1.1 jmcneill return (&cqe[next]);
7008 1.1 jmcneill }
7009 1.1 jmcneill
7010 1.1 jmcneill return (NULL);
7011 1.1 jmcneill }
7012 1.1 jmcneill
7013 1.1 jmcneill static void
7014 1.15 jmcneill mcx_arm_cq(struct mcx_softc *sc, struct mcx_cq *cq, int uar)
7015 1.1 jmcneill {
7016 1.15 jmcneill struct mcx_cq_doorbell *db;
7017 1.1 jmcneill bus_size_t offset;
7018 1.1 jmcneill uint32_t val;
7019 1.1 jmcneill uint64_t uval;
7020 1.1 jmcneill
7021 1.1 jmcneill val = ((cq->cq_count) & 3) << MCX_CQ_DOORBELL_ARM_CMD_SN_SHIFT;
7022 1.1 jmcneill val |= (cq->cq_cons & MCX_CQ_DOORBELL_ARM_CI_MASK);
7023 1.1 jmcneill
7024 1.15 jmcneill db = MCX_DMA_OFF(&sc->sc_doorbell_mem, cq->cq_doorbell);
7025 1.15 jmcneill
7026 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
7027 1.15 jmcneill cq->cq_doorbell, sizeof(*db), BUS_DMASYNC_POSTWRITE);
7028 1.1 jmcneill
7029 1.15 jmcneill be32enc(&db->db_update_ci, cq->cq_cons & MCX_CQ_DOORBELL_ARM_CI_MASK);
7030 1.15 jmcneill be32enc(&db->db_arm_ci, val);
7031 1.15 jmcneill
7032 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
7033 1.15 jmcneill cq->cq_doorbell, sizeof(*db), BUS_DMASYNC_PREWRITE);
7034 1.15 jmcneill
7035 1.15 jmcneill offset = (MCX_PAGE_SIZE * uar) + MCX_UAR_CQ_DOORBELL;
7036 1.15 jmcneill
7037 1.15 jmcneill uval = (uint64_t)val << 32;
7038 1.1 jmcneill uval |= cq->cq_n;
7039 1.15 jmcneill
7040 1.15 jmcneill bus_space_write_8(sc->sc_memt, sc->sc_memh, offset, htobe64(uval));
7041 1.15 jmcneill mcx_bar(sc, offset, sizeof(uval), BUS_SPACE_BARRIER_WRITE);
7042 1.1 jmcneill }
7043 1.1 jmcneill
7044 1.1 jmcneill void
7045 1.15 jmcneill mcx_process_cq(struct mcx_softc *sc, struct mcx_queues *q, struct mcx_cq *cq)
7046 1.1 jmcneill {
7047 1.15 jmcneill struct mcx_rx *rx = &q->q_rx;
7048 1.15 jmcneill struct mcx_tx *tx = &q->q_tx;
7049 1.1 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
7050 1.1 jmcneill const struct mcx_calibration *c;
7051 1.1 jmcneill unsigned int gen;
7052 1.1 jmcneill struct mcx_cq_entry *cqe;
7053 1.1 jmcneill struct mcx_mbufq mq;
7054 1.1 jmcneill struct mbuf *m;
7055 1.1 jmcneill int rxfree, txfree;
7056 1.1 jmcneill
7057 1.1 jmcneill MBUFQ_INIT(&mq);
7058 1.1 jmcneill
7059 1.1 jmcneill gen = sc->sc_calibration_gen;
7060 1.1 jmcneill membar_consumer();
7061 1.1 jmcneill c = &sc->sc_calibration[gen % __arraycount(sc->sc_calibration)];
7062 1.1 jmcneill
7063 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&cq->cq_mem),
7064 1.15 jmcneill 0, MCX_DMA_LEN(&cq->cq_mem), BUS_DMASYNC_POSTREAD);
7065 1.15 jmcneill
7066 1.1 jmcneill rxfree = 0;
7067 1.1 jmcneill txfree = 0;
7068 1.1 jmcneill while ((cqe = mcx_next_cq_entry(sc, cq))) {
7069 1.1 jmcneill uint8_t opcode;
7070 1.1 jmcneill opcode = (cqe->cq_opcode_owner >> MCX_CQ_ENTRY_OPCODE_SHIFT);
7071 1.1 jmcneill switch (opcode) {
7072 1.1 jmcneill case MCX_CQ_ENTRY_OPCODE_REQ:
7073 1.15 jmcneill txfree += mcx_process_txeof(sc, tx, cqe);
7074 1.1 jmcneill break;
7075 1.1 jmcneill case MCX_CQ_ENTRY_OPCODE_SEND:
7076 1.15 jmcneill rxfree += mcx_process_rx(sc, rx, cqe, &mq, c);
7077 1.1 jmcneill break;
7078 1.1 jmcneill case MCX_CQ_ENTRY_OPCODE_REQ_ERR:
7079 1.1 jmcneill case MCX_CQ_ENTRY_OPCODE_SEND_ERR:
7080 1.1 jmcneill /* uint8_t *cqp = (uint8_t *)cqe; */
7081 1.15 jmcneill /* printf("%s: cq completion error: %x\n",
7082 1.15 jmcneill DEVNAME(sc), cqp[0x37]); */
7083 1.1 jmcneill break;
7084 1.1 jmcneill
7085 1.1 jmcneill default:
7086 1.15 jmcneill /* printf("%s: cq completion opcode %x??\n",
7087 1.15 jmcneill DEVNAME(sc), opcode); */
7088 1.1 jmcneill break;
7089 1.1 jmcneill }
7090 1.1 jmcneill
7091 1.1 jmcneill cq->cq_cons++;
7092 1.1 jmcneill }
7093 1.1 jmcneill
7094 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&cq->cq_mem),
7095 1.15 jmcneill 0, MCX_DMA_LEN(&cq->cq_mem), BUS_DMASYNC_PREREAD);
7096 1.15 jmcneill
7097 1.1 jmcneill if (rxfree > 0) {
7098 1.15 jmcneill mcx_rxr_put(&rx->rx_rxr, rxfree);
7099 1.1 jmcneill while (MBUFQ_FIRST(&mq) != NULL) {
7100 1.1 jmcneill MBUFQ_DEQUEUE(&mq, m);
7101 1.1 jmcneill if_percpuq_enqueue(ifp->if_percpuq, m);
7102 1.1 jmcneill }
7103 1.1 jmcneill
7104 1.15 jmcneill mcx_rx_fill(sc, rx);
7105 1.15 jmcneill if (mcx_rxr_inuse(&rx->rx_rxr) == 0)
7106 1.15 jmcneill callout_schedule(&rx->rx_refill, 1);
7107 1.1 jmcneill }
7108 1.17 jmcneill
7109 1.17 jmcneill cq->cq_count++;
7110 1.17 jmcneill mcx_arm_cq(sc, cq, q->q_uar);
7111 1.17 jmcneill
7112 1.1 jmcneill if (txfree > 0) {
7113 1.15 jmcneill tx->tx_cons += txfree;
7114 1.1 jmcneill if_schedule_deferred_start(ifp);
7115 1.1 jmcneill }
7116 1.1 jmcneill }
7117 1.1 jmcneill
7118 1.15 jmcneill
7119 1.1 jmcneill static void
7120 1.15 jmcneill mcx_arm_eq(struct mcx_softc *sc, struct mcx_eq *eq, int uar)
7121 1.1 jmcneill {
7122 1.1 jmcneill bus_size_t offset;
7123 1.1 jmcneill uint32_t val;
7124 1.1 jmcneill
7125 1.15 jmcneill offset = (MCX_PAGE_SIZE * uar) + MCX_UAR_EQ_DOORBELL_ARM;
7126 1.15 jmcneill val = (eq->eq_n << 24) | (eq->eq_cons & 0xffffff);
7127 1.1 jmcneill
7128 1.1 jmcneill mcx_wr(sc, offset, val);
7129 1.15 jmcneill mcx_bar(sc, offset, sizeof(val), BUS_SPACE_BARRIER_WRITE);
7130 1.1 jmcneill }
7131 1.1 jmcneill
7132 1.1 jmcneill static struct mcx_eq_entry *
7133 1.15 jmcneill mcx_next_eq_entry(struct mcx_softc *sc, struct mcx_eq *eq)
7134 1.1 jmcneill {
7135 1.1 jmcneill struct mcx_eq_entry *eqe;
7136 1.1 jmcneill int next;
7137 1.1 jmcneill
7138 1.15 jmcneill eqe = (struct mcx_eq_entry *)MCX_DMA_KVA(&eq->eq_mem);
7139 1.15 jmcneill next = eq->eq_cons % (1 << MCX_LOG_EQ_SIZE);
7140 1.15 jmcneill if ((eqe[next].eq_owner & 1) ==
7141 1.15 jmcneill ((eq->eq_cons >> MCX_LOG_EQ_SIZE) & 1)) {
7142 1.15 jmcneill eq->eq_cons++;
7143 1.1 jmcneill return (&eqe[next]);
7144 1.1 jmcneill }
7145 1.1 jmcneill return (NULL);
7146 1.1 jmcneill }
7147 1.1 jmcneill
7148 1.1 jmcneill int
7149 1.15 jmcneill mcx_admin_intr(void *xsc)
7150 1.1 jmcneill {
7151 1.1 jmcneill struct mcx_softc *sc = (struct mcx_softc *)xsc;
7152 1.15 jmcneill struct mcx_eq *eq = &sc->sc_admin_eq;
7153 1.1 jmcneill struct mcx_eq_entry *eqe;
7154 1.1 jmcneill
7155 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
7156 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_POSTREAD);
7157 1.15 jmcneill
7158 1.15 jmcneill while ((eqe = mcx_next_eq_entry(sc, eq)) != NULL) {
7159 1.1 jmcneill switch (eqe->eq_event_type) {
7160 1.1 jmcneill case MCX_EVENT_TYPE_LAST_WQE:
7161 1.1 jmcneill /* printf("%s: last wqe reached?\n", DEVNAME(sc)); */
7162 1.1 jmcneill break;
7163 1.1 jmcneill
7164 1.1 jmcneill case MCX_EVENT_TYPE_CQ_ERROR:
7165 1.1 jmcneill /* printf("%s: cq error\n", DEVNAME(sc)); */
7166 1.1 jmcneill break;
7167 1.1 jmcneill
7168 1.1 jmcneill case MCX_EVENT_TYPE_CMD_COMPLETION:
7169 1.1 jmcneill /* wakeup probably */
7170 1.1 jmcneill break;
7171 1.1 jmcneill
7172 1.1 jmcneill case MCX_EVENT_TYPE_PORT_CHANGE:
7173 1.1 jmcneill workqueue_enqueue(sc->sc_workq, &sc->sc_port_change, NULL);
7174 1.1 jmcneill break;
7175 1.1 jmcneill
7176 1.1 jmcneill default:
7177 1.1 jmcneill /* printf("%s: something happened\n", DEVNAME(sc)); */
7178 1.1 jmcneill break;
7179 1.1 jmcneill }
7180 1.1 jmcneill }
7181 1.15 jmcneill
7182 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
7183 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_PREREAD);
7184 1.15 jmcneill
7185 1.15 jmcneill mcx_arm_eq(sc, eq, sc->sc_uar);
7186 1.15 jmcneill
7187 1.15 jmcneill return (1);
7188 1.15 jmcneill }
7189 1.15 jmcneill
7190 1.15 jmcneill int
7191 1.15 jmcneill mcx_cq_intr(void *xq)
7192 1.15 jmcneill {
7193 1.15 jmcneill struct mcx_queues *q = (struct mcx_queues *)xq;
7194 1.15 jmcneill struct mcx_softc *sc = q->q_sc;
7195 1.15 jmcneill struct mcx_eq *eq = &q->q_eq;
7196 1.15 jmcneill struct mcx_eq_entry *eqe;
7197 1.15 jmcneill int cqn;
7198 1.15 jmcneill
7199 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
7200 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_POSTREAD);
7201 1.15 jmcneill
7202 1.15 jmcneill while ((eqe = mcx_next_eq_entry(sc, eq)) != NULL) {
7203 1.15 jmcneill switch (eqe->eq_event_type) {
7204 1.15 jmcneill case MCX_EVENT_TYPE_COMPLETION:
7205 1.15 jmcneill cqn = be32toh(eqe->eq_event_data[6]);
7206 1.15 jmcneill if (cqn == q->q_cq.cq_n)
7207 1.15 jmcneill mcx_process_cq(sc, q, &q->q_cq);
7208 1.15 jmcneill break;
7209 1.15 jmcneill }
7210 1.15 jmcneill }
7211 1.15 jmcneill
7212 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&eq->eq_mem),
7213 1.15 jmcneill 0, MCX_DMA_LEN(&eq->eq_mem), BUS_DMASYNC_PREREAD);
7214 1.15 jmcneill
7215 1.15 jmcneill mcx_arm_eq(sc, eq, q->q_uar);
7216 1.15 jmcneill
7217 1.1 jmcneill return (1);
7218 1.1 jmcneill }
7219 1.1 jmcneill
7220 1.1 jmcneill static void
7221 1.1 jmcneill mcx_free_slots(struct mcx_softc *sc, struct mcx_slot *slots, int allocated,
7222 1.1 jmcneill int total)
7223 1.1 jmcneill {
7224 1.1 jmcneill struct mcx_slot *ms;
7225 1.1 jmcneill
7226 1.1 jmcneill int i = allocated;
7227 1.1 jmcneill while (i-- > 0) {
7228 1.1 jmcneill ms = &slots[i];
7229 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, ms->ms_map);
7230 1.1 jmcneill if (ms->ms_m != NULL)
7231 1.1 jmcneill m_freem(ms->ms_m);
7232 1.1 jmcneill }
7233 1.1 jmcneill kmem_free(slots, total * sizeof(*ms));
7234 1.1 jmcneill }
7235 1.1 jmcneill
7236 1.1 jmcneill static int
7237 1.15 jmcneill mcx_queue_up(struct mcx_softc *sc, struct mcx_queues *q)
7238 1.1 jmcneill {
7239 1.15 jmcneill struct mcx_rx *rx;
7240 1.15 jmcneill struct mcx_tx *tx;
7241 1.1 jmcneill struct mcx_slot *ms;
7242 1.15 jmcneill int i;
7243 1.1 jmcneill
7244 1.15 jmcneill rx = &q->q_rx;
7245 1.15 jmcneill rx->rx_slots = kmem_zalloc(sizeof(*ms) * (1 << MCX_LOG_RQ_SIZE),
7246 1.1 jmcneill KM_SLEEP);
7247 1.1 jmcneill
7248 1.1 jmcneill for (i = 0; i < (1 << MCX_LOG_RQ_SIZE); i++) {
7249 1.15 jmcneill ms = &rx->rx_slots[i];
7250 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, sc->sc_hardmtu, 1,
7251 1.1 jmcneill sc->sc_hardmtu, 0,
7252 1.1 jmcneill BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
7253 1.1 jmcneill &ms->ms_map) != 0) {
7254 1.1 jmcneill printf("%s: failed to allocate rx dma maps\n",
7255 1.1 jmcneill DEVNAME(sc));
7256 1.1 jmcneill goto destroy_rx_slots;
7257 1.1 jmcneill }
7258 1.15 jmcneill }
7259 1.15 jmcneill
7260 1.15 jmcneill tx = &q->q_tx;
7261 1.15 jmcneill tx->tx_slots = kmem_zalloc(sizeof(*ms) * (1 << MCX_LOG_SQ_SIZE),
7262 1.15 jmcneill KM_SLEEP);
7263 1.15 jmcneill
7264 1.15 jmcneill for (i = 0; i < (1 << MCX_LOG_SQ_SIZE); i++) {
7265 1.15 jmcneill ms = &tx->tx_slots[i];
7266 1.15 jmcneill if (bus_dmamap_create(sc->sc_dmat, sc->sc_hardmtu,
7267 1.15 jmcneill MCX_SQ_MAX_SEGMENTS, sc->sc_hardmtu, 0,
7268 1.15 jmcneill BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
7269 1.15 jmcneill &ms->ms_map) != 0) {
7270 1.15 jmcneill printf("%s: failed to allocate tx dma maps\n",
7271 1.15 jmcneill DEVNAME(sc));
7272 1.15 jmcneill goto destroy_tx_slots;
7273 1.15 jmcneill }
7274 1.15 jmcneill }
7275 1.15 jmcneill
7276 1.15 jmcneill if (mcx_create_cq(sc, &q->q_cq, q->q_uar, q->q_index,
7277 1.15 jmcneill q->q_eq.eq_n) != 0)
7278 1.15 jmcneill goto destroy_tx_slots;
7279 1.15 jmcneill
7280 1.15 jmcneill if (mcx_create_sq(sc, tx, q->q_uar, q->q_index, q->q_cq.cq_n)
7281 1.15 jmcneill != 0)
7282 1.15 jmcneill goto destroy_cq;
7283 1.15 jmcneill
7284 1.15 jmcneill if (mcx_create_rq(sc, rx, q->q_index, q->q_cq.cq_n) != 0)
7285 1.15 jmcneill goto destroy_sq;
7286 1.15 jmcneill
7287 1.15 jmcneill return 0;
7288 1.15 jmcneill
7289 1.15 jmcneill destroy_sq:
7290 1.15 jmcneill mcx_destroy_sq(sc, tx);
7291 1.15 jmcneill destroy_cq:
7292 1.15 jmcneill mcx_destroy_cq(sc, &q->q_cq);
7293 1.15 jmcneill destroy_tx_slots:
7294 1.15 jmcneill mcx_free_slots(sc, tx->tx_slots, i, (1 << MCX_LOG_SQ_SIZE));
7295 1.15 jmcneill tx->tx_slots = NULL;
7296 1.15 jmcneill
7297 1.15 jmcneill i = (1 << MCX_LOG_RQ_SIZE);
7298 1.15 jmcneill destroy_rx_slots:
7299 1.15 jmcneill mcx_free_slots(sc, rx->rx_slots, i, (1 << MCX_LOG_RQ_SIZE));
7300 1.15 jmcneill rx->rx_slots = NULL;
7301 1.15 jmcneill return ENOMEM;
7302 1.15 jmcneill }
7303 1.15 jmcneill
7304 1.15 jmcneill static int
7305 1.15 jmcneill mcx_rss_group_entry_count(struct mcx_softc *sc, int group)
7306 1.15 jmcneill {
7307 1.15 jmcneill int i;
7308 1.15 jmcneill int count;
7309 1.15 jmcneill
7310 1.15 jmcneill count = 0;
7311 1.15 jmcneill for (i = 0; i < __arraycount(mcx_rss_config); i++) {
7312 1.15 jmcneill if (mcx_rss_config[i].flow_group == group)
7313 1.15 jmcneill count++;
7314 1.15 jmcneill }
7315 1.15 jmcneill
7316 1.15 jmcneill return count;
7317 1.15 jmcneill }
7318 1.15 jmcneill
7319 1.15 jmcneill static int
7320 1.15 jmcneill mcx_init(struct ifnet *ifp)
7321 1.15 jmcneill {
7322 1.15 jmcneill struct mcx_softc *sc = ifp->if_softc;
7323 1.15 jmcneill struct mcx_rx *rx;
7324 1.15 jmcneill struct mcx_tx *tx;
7325 1.15 jmcneill int i, start, count, flow_group, flow_index;
7326 1.15 jmcneill struct mcx_flow_match match_crit;
7327 1.15 jmcneill struct mcx_rss_rule *rss;
7328 1.15 jmcneill uint32_t dest;
7329 1.15 jmcneill int rqns[MCX_MAX_QUEUES] = { 0 };
7330 1.15 jmcneill
7331 1.15 jmcneill if (ISSET(ifp->if_flags, IFF_RUNNING))
7332 1.15 jmcneill mcx_stop(ifp, 0);
7333 1.1 jmcneill
7334 1.15 jmcneill if (mcx_create_tis(sc, &sc->sc_tis) != 0)
7335 1.15 jmcneill goto down;
7336 1.1 jmcneill
7337 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++) {
7338 1.15 jmcneill if (mcx_queue_up(sc, &sc->sc_queues[i]) != 0) {
7339 1.15 jmcneill goto down;
7340 1.1 jmcneill }
7341 1.1 jmcneill }
7342 1.1 jmcneill
7343 1.15 jmcneill /* RSS flow table and flow groups */
7344 1.15 jmcneill if (mcx_create_flow_table(sc, MCX_LOG_FLOW_TABLE_SIZE, 1,
7345 1.15 jmcneill &sc->sc_rss_flow_table_id) != 0)
7346 1.1 jmcneill goto down;
7347 1.1 jmcneill
7348 1.15 jmcneill dest = MCX_FLOW_CONTEXT_DEST_TYPE_TABLE |
7349 1.15 jmcneill sc->sc_rss_flow_table_id;
7350 1.1 jmcneill
7351 1.15 jmcneill /* L4 RSS flow group (v4/v6 tcp/udp, no fragments) */
7352 1.15 jmcneill memset(&match_crit, 0, sizeof(match_crit));
7353 1.15 jmcneill match_crit.mc_ethertype = 0xffff;
7354 1.15 jmcneill match_crit.mc_ip_proto = 0xff;
7355 1.15 jmcneill match_crit.mc_vlan_flags = MCX_FLOW_MATCH_IP_FRAG;
7356 1.15 jmcneill start = 0;
7357 1.15 jmcneill count = mcx_rss_group_entry_count(sc, MCX_FLOW_GROUP_RSS_L4);
7358 1.15 jmcneill if (count != 0) {
7359 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_rss_flow_table_id,
7360 1.15 jmcneill MCX_FLOW_GROUP_RSS_L4, start, count,
7361 1.15 jmcneill MCX_CREATE_FLOW_GROUP_CRIT_OUTER, &match_crit) != 0)
7362 1.15 jmcneill goto down;
7363 1.15 jmcneill start += count;
7364 1.15 jmcneill }
7365 1.1 jmcneill
7366 1.15 jmcneill /* L3 RSS flow group (v4/v6, including fragments) */
7367 1.15 jmcneill memset(&match_crit, 0, sizeof(match_crit));
7368 1.15 jmcneill match_crit.mc_ethertype = 0xffff;
7369 1.15 jmcneill count = mcx_rss_group_entry_count(sc, MCX_FLOW_GROUP_RSS_L3);
7370 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_rss_flow_table_id,
7371 1.15 jmcneill MCX_FLOW_GROUP_RSS_L3, start, count,
7372 1.15 jmcneill MCX_CREATE_FLOW_GROUP_CRIT_OUTER, &match_crit) != 0)
7373 1.1 jmcneill goto down;
7374 1.15 jmcneill start += count;
7375 1.1 jmcneill
7376 1.15 jmcneill /* non-RSS flow group */
7377 1.15 jmcneill count = mcx_rss_group_entry_count(sc, MCX_FLOW_GROUP_RSS_NONE);
7378 1.15 jmcneill memset(&match_crit, 0, sizeof(match_crit));
7379 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_rss_flow_table_id,
7380 1.15 jmcneill MCX_FLOW_GROUP_RSS_NONE, start, count, 0, &match_crit) != 0)
7381 1.1 jmcneill goto down;
7382 1.1 jmcneill
7383 1.15 jmcneill /* Root flow table, matching packets based on mac address */
7384 1.15 jmcneill if (mcx_create_flow_table(sc, MCX_LOG_FLOW_TABLE_SIZE, 0,
7385 1.15 jmcneill &sc->sc_mac_flow_table_id) != 0)
7386 1.1 jmcneill goto down;
7387 1.1 jmcneill
7388 1.1 jmcneill /* promisc flow group */
7389 1.1 jmcneill start = 0;
7390 1.1 jmcneill memset(&match_crit, 0, sizeof(match_crit));
7391 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_mac_flow_table_id,
7392 1.15 jmcneill MCX_FLOW_GROUP_PROMISC, start, 1, 0, &match_crit) != 0)
7393 1.1 jmcneill goto down;
7394 1.1 jmcneill sc->sc_promisc_flow_enabled = 0;
7395 1.1 jmcneill start++;
7396 1.1 jmcneill
7397 1.1 jmcneill /* all multicast flow group */
7398 1.1 jmcneill match_crit.mc_dest_mac[0] = 0x01;
7399 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_mac_flow_table_id,
7400 1.15 jmcneill MCX_FLOW_GROUP_ALLMULTI, start, 1,
7401 1.1 jmcneill MCX_CREATE_FLOW_GROUP_CRIT_OUTER, &match_crit) != 0)
7402 1.1 jmcneill goto down;
7403 1.1 jmcneill sc->sc_allmulti_flow_enabled = 0;
7404 1.1 jmcneill start++;
7405 1.1 jmcneill
7406 1.1 jmcneill /* mac address matching flow group */
7407 1.1 jmcneill memset(&match_crit.mc_dest_mac, 0xff, sizeof(match_crit.mc_dest_mac));
7408 1.15 jmcneill if (mcx_create_flow_group(sc, sc->sc_mac_flow_table_id,
7409 1.15 jmcneill MCX_FLOW_GROUP_MAC, start, (1 << MCX_LOG_FLOW_TABLE_SIZE) - start,
7410 1.1 jmcneill MCX_CREATE_FLOW_GROUP_CRIT_OUTER, &match_crit) != 0)
7411 1.1 jmcneill goto down;
7412 1.1 jmcneill
7413 1.1 jmcneill /* flow table entries for unicast and broadcast */
7414 1.1 jmcneill start = 0;
7415 1.15 jmcneill if (mcx_set_flow_table_entry_mac(sc, MCX_FLOW_GROUP_MAC, start,
7416 1.15 jmcneill LLADDR(satosdl(ifp->if_dl->ifa_addr)), dest) != 0)
7417 1.1 jmcneill goto down;
7418 1.1 jmcneill start++;
7419 1.1 jmcneill
7420 1.15 jmcneill if (mcx_set_flow_table_entry_mac(sc, MCX_FLOW_GROUP_MAC, start,
7421 1.15 jmcneill etherbroadcastaddr, dest) != 0)
7422 1.1 jmcneill goto down;
7423 1.1 jmcneill start++;
7424 1.1 jmcneill
7425 1.1 jmcneill /* multicast entries go after that */
7426 1.1 jmcneill sc->sc_mcast_flow_base = start;
7427 1.1 jmcneill
7428 1.1 jmcneill /* re-add any existing multicast flows */
7429 1.1 jmcneill for (i = 0; i < MCX_NUM_MCAST_FLOWS; i++) {
7430 1.1 jmcneill if (sc->sc_mcast_flows[i][0] != 0) {
7431 1.15 jmcneill mcx_set_flow_table_entry_mac(sc, MCX_FLOW_GROUP_MAC,
7432 1.1 jmcneill sc->sc_mcast_flow_base + i,
7433 1.15 jmcneill sc->sc_mcast_flows[i], dest);
7434 1.1 jmcneill }
7435 1.1 jmcneill }
7436 1.1 jmcneill
7437 1.15 jmcneill if (mcx_set_flow_table_root(sc, sc->sc_mac_flow_table_id) != 0)
7438 1.1 jmcneill goto down;
7439 1.1 jmcneill
7440 1.15 jmcneill /*
7441 1.15 jmcneill * the RQT can be any size as long as it's a power of two.
7442 1.15 jmcneill * since we also restrict the number of queues to a power of two,
7443 1.15 jmcneill * we can just put each rx queue in once.
7444 1.15 jmcneill */
7445 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++)
7446 1.15 jmcneill rqns[i] = sc->sc_queues[i].q_rx.rx_rqn;
7447 1.15 jmcneill
7448 1.15 jmcneill if (mcx_create_rqt(sc, sc->sc_nqueues, rqns, &sc->sc_rqt) != 0)
7449 1.1 jmcneill goto down;
7450 1.1 jmcneill
7451 1.15 jmcneill start = 0;
7452 1.15 jmcneill flow_index = 0;
7453 1.15 jmcneill flow_group = -1;
7454 1.15 jmcneill for (i = 0; i < __arraycount(mcx_rss_config); i++) {
7455 1.15 jmcneill rss = &mcx_rss_config[i];
7456 1.15 jmcneill if (rss->flow_group != flow_group) {
7457 1.15 jmcneill flow_group = rss->flow_group;
7458 1.15 jmcneill flow_index = 0;
7459 1.15 jmcneill }
7460 1.15 jmcneill
7461 1.15 jmcneill if (rss->hash_sel == 0) {
7462 1.15 jmcneill if (mcx_create_tir_direct(sc, &sc->sc_queues[0].q_rx,
7463 1.15 jmcneill &sc->sc_tir[i]) != 0)
7464 1.15 jmcneill goto down;
7465 1.15 jmcneill } else {
7466 1.15 jmcneill if (mcx_create_tir_indirect(sc, sc->sc_rqt,
7467 1.15 jmcneill rss->hash_sel, &sc->sc_tir[i]) != 0)
7468 1.15 jmcneill goto down;
7469 1.15 jmcneill }
7470 1.15 jmcneill
7471 1.15 jmcneill if (mcx_set_flow_table_entry_proto(sc, flow_group,
7472 1.15 jmcneill flow_index, rss->ethertype, rss->ip_proto,
7473 1.15 jmcneill MCX_FLOW_CONTEXT_DEST_TYPE_TIR | sc->sc_tir[i]) != 0)
7474 1.15 jmcneill goto down;
7475 1.15 jmcneill flow_index++;
7476 1.15 jmcneill }
7477 1.15 jmcneill
7478 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++) {
7479 1.15 jmcneill struct mcx_queues *q = &sc->sc_queues[i];
7480 1.15 jmcneill rx = &q->q_rx;
7481 1.15 jmcneill tx = &q->q_tx;
7482 1.15 jmcneill
7483 1.15 jmcneill /* start the queues */
7484 1.15 jmcneill if (mcx_ready_sq(sc, tx) != 0)
7485 1.15 jmcneill goto down;
7486 1.15 jmcneill
7487 1.15 jmcneill if (mcx_ready_rq(sc, rx) != 0)
7488 1.15 jmcneill goto down;
7489 1.15 jmcneill
7490 1.15 jmcneill mcx_rxr_init(&rx->rx_rxr, 1, (1 << MCX_LOG_RQ_SIZE));
7491 1.15 jmcneill rx->rx_prod = 0;
7492 1.15 jmcneill mcx_rx_fill(sc, rx);
7493 1.1 jmcneill
7494 1.15 jmcneill tx->tx_cons = 0;
7495 1.15 jmcneill tx->tx_prod = 0;
7496 1.15 jmcneill }
7497 1.1 jmcneill
7498 1.1 jmcneill mcx_calibrate_first(sc);
7499 1.1 jmcneill
7500 1.1 jmcneill SET(ifp->if_flags, IFF_RUNNING);
7501 1.1 jmcneill CLR(ifp->if_flags, IFF_OACTIVE);
7502 1.1 jmcneill if_schedule_deferred_start(ifp);
7503 1.1 jmcneill
7504 1.1 jmcneill return 0;
7505 1.1 jmcneill down:
7506 1.1 jmcneill mcx_stop(ifp, 0);
7507 1.1 jmcneill return EIO;
7508 1.1 jmcneill }
7509 1.1 jmcneill
7510 1.1 jmcneill static void
7511 1.1 jmcneill mcx_stop(struct ifnet *ifp, int disable)
7512 1.1 jmcneill {
7513 1.1 jmcneill struct mcx_softc *sc = ifp->if_softc;
7514 1.15 jmcneill struct mcx_rss_rule *rss;
7515 1.15 jmcneill int group, i, flow_group, flow_index;
7516 1.1 jmcneill
7517 1.1 jmcneill CLR(ifp->if_flags, IFF_RUNNING);
7518 1.1 jmcneill
7519 1.1 jmcneill /*
7520 1.1 jmcneill * delete flow table entries first, so no packets can arrive
7521 1.1 jmcneill * after the barriers
7522 1.1 jmcneill */
7523 1.1 jmcneill if (sc->sc_promisc_flow_enabled)
7524 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_PROMISC, 0);
7525 1.1 jmcneill if (sc->sc_allmulti_flow_enabled)
7526 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_ALLMULTI, 0);
7527 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_MAC, 0);
7528 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_MAC, 1);
7529 1.1 jmcneill for (i = 0; i < MCX_NUM_MCAST_FLOWS; i++) {
7530 1.1 jmcneill if (sc->sc_mcast_flows[i][0] != 0) {
7531 1.1 jmcneill mcx_delete_flow_table_entry(sc, MCX_FLOW_GROUP_MAC,
7532 1.1 jmcneill sc->sc_mcast_flow_base + i);
7533 1.1 jmcneill }
7534 1.1 jmcneill }
7535 1.1 jmcneill
7536 1.15 jmcneill flow_group = -1;
7537 1.15 jmcneill flow_index = 0;
7538 1.15 jmcneill for (i = 0; i < __arraycount(mcx_rss_config); i++) {
7539 1.15 jmcneill rss = &mcx_rss_config[i];
7540 1.15 jmcneill if (rss->flow_group != flow_group) {
7541 1.15 jmcneill flow_group = rss->flow_group;
7542 1.15 jmcneill flow_index = 0;
7543 1.15 jmcneill }
7544 1.15 jmcneill
7545 1.15 jmcneill mcx_delete_flow_table_entry(sc, flow_group, flow_index);
7546 1.15 jmcneill
7547 1.15 jmcneill mcx_destroy_tir(sc, sc->sc_tir[i]);
7548 1.15 jmcneill sc->sc_tir[i] = 0;
7549 1.15 jmcneill
7550 1.15 jmcneill flow_index++;
7551 1.15 jmcneill }
7552 1.15 jmcneill
7553 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++) {
7554 1.15 jmcneill callout_halt(&sc->sc_queues[i].q_rx.rx_refill, NULL);
7555 1.15 jmcneill }
7556 1.15 jmcneill
7557 1.1 jmcneill callout_halt(&sc->sc_calibrate, NULL);
7558 1.1 jmcneill
7559 1.1 jmcneill for (group = 0; group < MCX_NUM_FLOW_GROUPS; group++) {
7560 1.15 jmcneill if (sc->sc_flow_group[group].g_id != -1)
7561 1.15 jmcneill mcx_destroy_flow_group(sc, group);
7562 1.15 jmcneill }
7563 1.15 jmcneill
7564 1.15 jmcneill if (sc->sc_mac_flow_table_id != -1) {
7565 1.15 jmcneill mcx_destroy_flow_table(sc, sc->sc_mac_flow_table_id);
7566 1.15 jmcneill sc->sc_mac_flow_table_id = -1;
7567 1.15 jmcneill }
7568 1.15 jmcneill if (sc->sc_rss_flow_table_id != -1) {
7569 1.15 jmcneill mcx_destroy_flow_table(sc, sc->sc_rss_flow_table_id);
7570 1.15 jmcneill sc->sc_rss_flow_table_id = -1;
7571 1.15 jmcneill }
7572 1.15 jmcneill if (sc->sc_rqt != -1) {
7573 1.15 jmcneill mcx_destroy_rqt(sc, sc->sc_rqt);
7574 1.15 jmcneill sc->sc_rqt = -1;
7575 1.15 jmcneill }
7576 1.15 jmcneill
7577 1.15 jmcneill for (i = 0; i < sc->sc_nqueues; i++) {
7578 1.15 jmcneill struct mcx_queues *q = &sc->sc_queues[i];
7579 1.15 jmcneill struct mcx_rx *rx = &q->q_rx;
7580 1.15 jmcneill struct mcx_tx *tx = &q->q_tx;
7581 1.15 jmcneill struct mcx_cq *cq = &q->q_cq;
7582 1.15 jmcneill
7583 1.15 jmcneill if (rx->rx_rqn != 0)
7584 1.15 jmcneill mcx_destroy_rq(sc, rx);
7585 1.15 jmcneill
7586 1.15 jmcneill if (tx->tx_sqn != 0)
7587 1.15 jmcneill mcx_destroy_sq(sc, tx);
7588 1.15 jmcneill
7589 1.15 jmcneill if (tx->tx_slots != NULL) {
7590 1.15 jmcneill mcx_free_slots(sc, tx->tx_slots,
7591 1.15 jmcneill (1 << MCX_LOG_SQ_SIZE), (1 << MCX_LOG_SQ_SIZE));
7592 1.15 jmcneill tx->tx_slots = NULL;
7593 1.15 jmcneill }
7594 1.15 jmcneill if (rx->rx_slots != NULL) {
7595 1.15 jmcneill mcx_free_slots(sc, rx->rx_slots,
7596 1.15 jmcneill (1 << MCX_LOG_RQ_SIZE), (1 << MCX_LOG_RQ_SIZE));
7597 1.15 jmcneill rx->rx_slots = NULL;
7598 1.15 jmcneill }
7599 1.15 jmcneill
7600 1.15 jmcneill if (cq->cq_n != 0)
7601 1.15 jmcneill mcx_destroy_cq(sc, cq);
7602 1.15 jmcneill }
7603 1.15 jmcneill if (sc->sc_tis != 0) {
7604 1.15 jmcneill mcx_destroy_tis(sc, sc->sc_tis);
7605 1.15 jmcneill sc->sc_tis = 0;
7606 1.1 jmcneill }
7607 1.1 jmcneill }
7608 1.1 jmcneill
7609 1.1 jmcneill static int
7610 1.1 jmcneill mcx_ioctl(struct ifnet *ifp, u_long cmd, void *data)
7611 1.1 jmcneill {
7612 1.1 jmcneill struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc;
7613 1.1 jmcneill struct ifreq *ifr = (struct ifreq *)data;
7614 1.7 jmcneill struct ethercom *ec = &sc->sc_ec;
7615 1.1 jmcneill uint8_t addrhi[ETHER_ADDR_LEN], addrlo[ETHER_ADDR_LEN];
7616 1.7 jmcneill struct ether_multi *enm;
7617 1.7 jmcneill struct ether_multistep step;
7618 1.7 jmcneill int s, i, flags, error = 0;
7619 1.15 jmcneill uint32_t dest;
7620 1.1 jmcneill
7621 1.1 jmcneill s = splnet();
7622 1.1 jmcneill switch (cmd) {
7623 1.1 jmcneill
7624 1.1 jmcneill case SIOCADDMULTI:
7625 1.1 jmcneill if (ether_addmulti(ifreq_getaddr(cmd, ifr), &sc->sc_ec) == ENETRESET) {
7626 1.1 jmcneill error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
7627 1.7 jmcneill if (error != 0) {
7628 1.7 jmcneill splx(s);
7629 1.1 jmcneill return (error);
7630 1.7 jmcneill }
7631 1.1 jmcneill
7632 1.15 jmcneill dest = MCX_FLOW_CONTEXT_DEST_TYPE_TABLE |
7633 1.15 jmcneill sc->sc_rss_flow_table_id;
7634 1.15 jmcneill
7635 1.1 jmcneill for (i = 0; i < MCX_NUM_MCAST_FLOWS; i++) {
7636 1.1 jmcneill if (sc->sc_mcast_flows[i][0] == 0) {
7637 1.1 jmcneill memcpy(sc->sc_mcast_flows[i], addrlo,
7638 1.1 jmcneill ETHER_ADDR_LEN);
7639 1.1 jmcneill if (ISSET(ifp->if_flags, IFF_RUNNING)) {
7640 1.15 jmcneill mcx_set_flow_table_entry_mac(sc,
7641 1.1 jmcneill MCX_FLOW_GROUP_MAC,
7642 1.1 jmcneill sc->sc_mcast_flow_base + i,
7643 1.15 jmcneill sc->sc_mcast_flows[i], dest);
7644 1.1 jmcneill }
7645 1.1 jmcneill break;
7646 1.1 jmcneill }
7647 1.1 jmcneill }
7648 1.1 jmcneill
7649 1.1 jmcneill if (!ISSET(ifp->if_flags, IFF_ALLMULTI)) {
7650 1.1 jmcneill if (i == MCX_NUM_MCAST_FLOWS) {
7651 1.1 jmcneill SET(ifp->if_flags, IFF_ALLMULTI);
7652 1.1 jmcneill sc->sc_extra_mcast++;
7653 1.1 jmcneill error = ENETRESET;
7654 1.1 jmcneill }
7655 1.1 jmcneill
7656 1.7 jmcneill if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN)) {
7657 1.1 jmcneill SET(ifp->if_flags, IFF_ALLMULTI);
7658 1.1 jmcneill error = ENETRESET;
7659 1.1 jmcneill }
7660 1.1 jmcneill }
7661 1.1 jmcneill }
7662 1.1 jmcneill break;
7663 1.1 jmcneill
7664 1.1 jmcneill case SIOCDELMULTI:
7665 1.1 jmcneill if (ether_delmulti(ifreq_getaddr(cmd, ifr), &sc->sc_ec) == ENETRESET) {
7666 1.1 jmcneill error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
7667 1.7 jmcneill if (error != 0) {
7668 1.7 jmcneill splx(s);
7669 1.1 jmcneill return (error);
7670 1.7 jmcneill }
7671 1.1 jmcneill
7672 1.1 jmcneill for (i = 0; i < MCX_NUM_MCAST_FLOWS; i++) {
7673 1.1 jmcneill if (memcmp(sc->sc_mcast_flows[i], addrlo,
7674 1.1 jmcneill ETHER_ADDR_LEN) == 0) {
7675 1.1 jmcneill if (ISSET(ifp->if_flags, IFF_RUNNING)) {
7676 1.1 jmcneill mcx_delete_flow_table_entry(sc,
7677 1.1 jmcneill MCX_FLOW_GROUP_MAC,
7678 1.1 jmcneill sc->sc_mcast_flow_base + i);
7679 1.1 jmcneill }
7680 1.1 jmcneill sc->sc_mcast_flows[i][0] = 0;
7681 1.1 jmcneill break;
7682 1.1 jmcneill }
7683 1.1 jmcneill }
7684 1.1 jmcneill
7685 1.1 jmcneill if (i == MCX_NUM_MCAST_FLOWS)
7686 1.1 jmcneill sc->sc_extra_mcast--;
7687 1.1 jmcneill
7688 1.1 jmcneill if (ISSET(ifp->if_flags, IFF_ALLMULTI) &&
7689 1.7 jmcneill sc->sc_extra_mcast == 0) {
7690 1.7 jmcneill flags = 0;
7691 1.7 jmcneill ETHER_LOCK(ec);
7692 1.7 jmcneill ETHER_FIRST_MULTI(step, ec, enm);
7693 1.7 jmcneill while (enm != NULL) {
7694 1.7 jmcneill if (memcmp(enm->enm_addrlo,
7695 1.7 jmcneill enm->enm_addrhi, ETHER_ADDR_LEN)) {
7696 1.7 jmcneill SET(flags, IFF_ALLMULTI);
7697 1.7 jmcneill break;
7698 1.7 jmcneill }
7699 1.7 jmcneill ETHER_NEXT_MULTI(step, enm);
7700 1.7 jmcneill }
7701 1.7 jmcneill ETHER_UNLOCK(ec);
7702 1.7 jmcneill if (!ISSET(flags, IFF_ALLMULTI)) {
7703 1.7 jmcneill CLR(ifp->if_flags, IFF_ALLMULTI);
7704 1.7 jmcneill error = ENETRESET;
7705 1.7 jmcneill }
7706 1.1 jmcneill }
7707 1.1 jmcneill }
7708 1.1 jmcneill break;
7709 1.1 jmcneill
7710 1.1 jmcneill default:
7711 1.1 jmcneill error = ether_ioctl(ifp, cmd, data);
7712 1.1 jmcneill }
7713 1.1 jmcneill
7714 1.1 jmcneill if (error == ENETRESET) {
7715 1.1 jmcneill if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7716 1.1 jmcneill (IFF_UP | IFF_RUNNING))
7717 1.1 jmcneill mcx_iff(sc);
7718 1.1 jmcneill error = 0;
7719 1.1 jmcneill }
7720 1.1 jmcneill splx(s);
7721 1.1 jmcneill
7722 1.1 jmcneill return (error);
7723 1.1 jmcneill }
7724 1.1 jmcneill
7725 1.1 jmcneill #if 0
7726 1.1 jmcneill static int
7727 1.1 jmcneill mcx_get_sffpage(struct ifnet *ifp, struct if_sffpage *sff)
7728 1.1 jmcneill {
7729 1.1 jmcneill struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc;
7730 1.1 jmcneill struct mcx_reg_mcia mcia;
7731 1.1 jmcneill struct mcx_reg_pmlp pmlp;
7732 1.1 jmcneill int offset, error;
7733 1.1 jmcneill
7734 1.1 jmcneill /* get module number */
7735 1.1 jmcneill memset(&pmlp, 0, sizeof(pmlp));
7736 1.1 jmcneill pmlp.rp_local_port = 1;
7737 1.1 jmcneill error = mcx_access_hca_reg(sc, MCX_REG_PMLP, MCX_REG_OP_READ, &pmlp,
7738 1.1 jmcneill sizeof(pmlp));
7739 1.1 jmcneill if (error != 0) {
7740 1.1 jmcneill printf("%s: unable to get eeprom module number\n",
7741 1.1 jmcneill DEVNAME(sc));
7742 1.1 jmcneill return error;
7743 1.1 jmcneill }
7744 1.1 jmcneill
7745 1.1 jmcneill for (offset = 0; offset < 256; offset += MCX_MCIA_EEPROM_BYTES) {
7746 1.1 jmcneill memset(&mcia, 0, sizeof(mcia));
7747 1.1 jmcneill mcia.rm_l = 0;
7748 1.1 jmcneill mcia.rm_module = be32toh(pmlp.rp_lane0_mapping) &
7749 1.1 jmcneill MCX_PMLP_MODULE_NUM_MASK;
7750 1.1 jmcneill mcia.rm_i2c_addr = sff->sff_addr / 2; /* apparently */
7751 1.1 jmcneill mcia.rm_page_num = sff->sff_page;
7752 1.1 jmcneill mcia.rm_dev_addr = htobe16(offset);
7753 1.1 jmcneill mcia.rm_size = htobe16(MCX_MCIA_EEPROM_BYTES);
7754 1.1 jmcneill
7755 1.1 jmcneill error = mcx_access_hca_reg(sc, MCX_REG_MCIA, MCX_REG_OP_READ,
7756 1.1 jmcneill &mcia, sizeof(mcia));
7757 1.1 jmcneill if (error != 0) {
7758 1.1 jmcneill printf("%s: unable to read eeprom at %x\n",
7759 1.1 jmcneill DEVNAME(sc), offset);
7760 1.1 jmcneill return error;
7761 1.1 jmcneill }
7762 1.1 jmcneill
7763 1.1 jmcneill memcpy(sff->sff_data + offset, mcia.rm_data,
7764 1.1 jmcneill MCX_MCIA_EEPROM_BYTES);
7765 1.1 jmcneill }
7766 1.1 jmcneill
7767 1.1 jmcneill return 0;
7768 1.1 jmcneill }
7769 1.1 jmcneill #endif
7770 1.1 jmcneill
7771 1.1 jmcneill static int
7772 1.1 jmcneill mcx_load_mbuf(struct mcx_softc *sc, struct mcx_slot *ms, struct mbuf *m)
7773 1.1 jmcneill {
7774 1.1 jmcneill switch (bus_dmamap_load_mbuf(sc->sc_dmat, ms->ms_map, m,
7775 1.1 jmcneill BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) {
7776 1.1 jmcneill case 0:
7777 1.1 jmcneill break;
7778 1.1 jmcneill
7779 1.1 jmcneill case EFBIG:
7780 1.6 nonaka if (m_defrag(m, M_DONTWAIT) != NULL &&
7781 1.1 jmcneill bus_dmamap_load_mbuf(sc->sc_dmat, ms->ms_map, m,
7782 1.1 jmcneill BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0)
7783 1.1 jmcneill break;
7784 1.1 jmcneill
7785 1.1 jmcneill /* FALLTHROUGH */
7786 1.1 jmcneill default:
7787 1.1 jmcneill return (1);
7788 1.1 jmcneill }
7789 1.1 jmcneill
7790 1.1 jmcneill ms->ms_m = m;
7791 1.1 jmcneill return (0);
7792 1.1 jmcneill }
7793 1.1 jmcneill
7794 1.1 jmcneill static void
7795 1.16 jmcneill mcx_send_common_locked(struct ifnet *ifp, struct mcx_tx *tx, bool is_transmit)
7796 1.1 jmcneill {
7797 1.1 jmcneill struct mcx_softc *sc = ifp->if_softc;
7798 1.1 jmcneill struct mcx_sq_entry *sq, *sqe;
7799 1.1 jmcneill struct mcx_sq_entry_seg *sqs;
7800 1.1 jmcneill struct mcx_slot *ms;
7801 1.1 jmcneill bus_dmamap_t map;
7802 1.1 jmcneill struct mbuf *m;
7803 1.1 jmcneill u_int idx, free, used;
7804 1.1 jmcneill uint64_t *bf;
7805 1.15 jmcneill uint32_t csum;
7806 1.1 jmcneill size_t bf_base;
7807 1.1 jmcneill int i, seg, nseg;
7808 1.1 jmcneill
7809 1.16 jmcneill KASSERT(mutex_owned(&tx->tx_lock));
7810 1.16 jmcneill
7811 1.16 jmcneill if ((ifp->if_flags & IFF_RUNNING) == 0)
7812 1.16 jmcneill return;
7813 1.16 jmcneill
7814 1.15 jmcneill bf_base = (tx->tx_uar * MCX_PAGE_SIZE) + MCX_UAR_BF;
7815 1.1 jmcneill
7816 1.15 jmcneill idx = tx->tx_prod % (1 << MCX_LOG_SQ_SIZE);
7817 1.15 jmcneill free = (tx->tx_cons + (1 << MCX_LOG_SQ_SIZE)) - tx->tx_prod;
7818 1.1 jmcneill
7819 1.1 jmcneill used = 0;
7820 1.1 jmcneill bf = NULL;
7821 1.15 jmcneill
7822 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&tx->tx_sq_mem),
7823 1.15 jmcneill 0, MCX_DMA_LEN(&tx->tx_sq_mem), BUS_DMASYNC_POSTWRITE);
7824 1.15 jmcneill
7825 1.15 jmcneill sq = (struct mcx_sq_entry *)MCX_DMA_KVA(&tx->tx_sq_mem);
7826 1.1 jmcneill
7827 1.1 jmcneill for (;;) {
7828 1.1 jmcneill if (used + MCX_SQ_ENTRY_MAX_SLOTS >= free) {
7829 1.1 jmcneill SET(ifp->if_flags, IFF_OACTIVE);
7830 1.1 jmcneill break;
7831 1.1 jmcneill }
7832 1.1 jmcneill
7833 1.16 jmcneill if (is_transmit) {
7834 1.16 jmcneill m = pcq_get(tx->tx_pcq);
7835 1.16 jmcneill } else {
7836 1.16 jmcneill IFQ_DEQUEUE(&ifp->if_snd, m);
7837 1.16 jmcneill }
7838 1.1 jmcneill if (m == NULL) {
7839 1.1 jmcneill break;
7840 1.1 jmcneill }
7841 1.1 jmcneill
7842 1.1 jmcneill sqe = sq + idx;
7843 1.15 jmcneill ms = &tx->tx_slots[idx];
7844 1.1 jmcneill memset(sqe, 0, sizeof(*sqe));
7845 1.1 jmcneill
7846 1.1 jmcneill /* ctrl segment */
7847 1.1 jmcneill sqe->sqe_opcode_index = htobe32(MCX_SQE_WQE_OPCODE_SEND |
7848 1.15 jmcneill ((tx->tx_prod & 0xffff) << MCX_SQE_WQE_INDEX_SHIFT));
7849 1.1 jmcneill /* always generate a completion event */
7850 1.1 jmcneill sqe->sqe_signature = htobe32(MCX_SQE_CE_CQE_ALWAYS);
7851 1.1 jmcneill
7852 1.1 jmcneill /* eth segment */
7853 1.15 jmcneill csum = 0;
7854 1.15 jmcneill if (m->m_pkthdr.csum_flags & M_CSUM_IPv4)
7855 1.15 jmcneill csum |= MCX_SQE_L3_CSUM;
7856 1.15 jmcneill if (m->m_pkthdr.csum_flags &
7857 1.15 jmcneill (M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_TCPv6 | M_CSUM_UDPv6))
7858 1.15 jmcneill csum |= MCX_SQE_L4_CSUM;
7859 1.15 jmcneill sqe->sqe_mss_csum = htobe32(csum);
7860 1.1 jmcneill sqe->sqe_inline_header_size = htobe16(MCX_SQ_INLINE_SIZE);
7861 1.15 jmcneill if (vlan_has_tag(m)) {
7862 1.15 jmcneill struct ether_vlan_header *evh;
7863 1.15 jmcneill evh = (struct ether_vlan_header *)
7864 1.15 jmcneill &sqe->sqe_inline_headers;
7865 1.15 jmcneill
7866 1.15 jmcneill m_copydata(m, 0, ETHER_HDR_LEN, evh);
7867 1.15 jmcneill evh->evl_proto = evh->evl_encap_proto;
7868 1.15 jmcneill evh->evl_encap_proto = htons(ETHERTYPE_VLAN);
7869 1.15 jmcneill evh->evl_tag = htons(vlan_get_tag(m));
7870 1.15 jmcneill m_adj(m, ETHER_HDR_LEN);
7871 1.15 jmcneill } else {
7872 1.15 jmcneill m_copydata(m, 0, MCX_SQ_INLINE_SIZE,
7873 1.15 jmcneill sqe->sqe_inline_headers);
7874 1.15 jmcneill m_adj(m, MCX_SQ_INLINE_SIZE);
7875 1.15 jmcneill }
7876 1.1 jmcneill
7877 1.1 jmcneill if (mcx_load_mbuf(sc, ms, m) != 0) {
7878 1.1 jmcneill m_freem(m);
7879 1.10 thorpej if_statinc(ifp, if_oerrors);
7880 1.1 jmcneill continue;
7881 1.1 jmcneill }
7882 1.1 jmcneill bf = (uint64_t *)sqe;
7883 1.1 jmcneill
7884 1.1 jmcneill if (ifp->if_bpf != NULL)
7885 1.1 jmcneill bpf_mtap2(ifp->if_bpf, sqe->sqe_inline_headers,
7886 1.1 jmcneill MCX_SQ_INLINE_SIZE, m, BPF_D_OUT);
7887 1.1 jmcneill
7888 1.1 jmcneill map = ms->ms_map;
7889 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
7890 1.1 jmcneill BUS_DMASYNC_PREWRITE);
7891 1.1 jmcneill
7892 1.1 jmcneill sqe->sqe_ds_sq_num =
7893 1.15 jmcneill htobe32((tx->tx_sqn << MCX_SQE_SQ_NUM_SHIFT) |
7894 1.1 jmcneill (map->dm_nsegs + 3));
7895 1.1 jmcneill
7896 1.1 jmcneill /* data segment - first wqe has one segment */
7897 1.1 jmcneill sqs = sqe->sqe_segs;
7898 1.1 jmcneill seg = 0;
7899 1.1 jmcneill nseg = 1;
7900 1.1 jmcneill for (i = 0; i < map->dm_nsegs; i++) {
7901 1.1 jmcneill if (seg == nseg) {
7902 1.1 jmcneill /* next slot */
7903 1.1 jmcneill idx++;
7904 1.1 jmcneill if (idx == (1 << MCX_LOG_SQ_SIZE))
7905 1.1 jmcneill idx = 0;
7906 1.15 jmcneill tx->tx_prod++;
7907 1.1 jmcneill used++;
7908 1.1 jmcneill
7909 1.1 jmcneill sqs = (struct mcx_sq_entry_seg *)(sq + idx);
7910 1.1 jmcneill seg = 0;
7911 1.1 jmcneill nseg = MCX_SQ_SEGS_PER_SLOT;
7912 1.1 jmcneill }
7913 1.1 jmcneill sqs[seg].sqs_byte_count =
7914 1.1 jmcneill htobe32(map->dm_segs[i].ds_len);
7915 1.1 jmcneill sqs[seg].sqs_lkey = htobe32(sc->sc_lkey);
7916 1.1 jmcneill sqs[seg].sqs_addr = htobe64(map->dm_segs[i].ds_addr);
7917 1.1 jmcneill seg++;
7918 1.1 jmcneill }
7919 1.1 jmcneill
7920 1.1 jmcneill idx++;
7921 1.1 jmcneill if (idx == (1 << MCX_LOG_SQ_SIZE))
7922 1.1 jmcneill idx = 0;
7923 1.15 jmcneill tx->tx_prod++;
7924 1.1 jmcneill used++;
7925 1.1 jmcneill }
7926 1.1 jmcneill
7927 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&tx->tx_sq_mem),
7928 1.15 jmcneill 0, MCX_DMA_LEN(&tx->tx_sq_mem), BUS_DMASYNC_PREWRITE);
7929 1.15 jmcneill
7930 1.1 jmcneill if (used) {
7931 1.15 jmcneill bus_size_t blueflame;
7932 1.1 jmcneill
7933 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
7934 1.15 jmcneill tx->tx_doorbell, sizeof(uint32_t), BUS_DMASYNC_POSTWRITE);
7935 1.15 jmcneill be32enc(MCX_DMA_OFF(&sc->sc_doorbell_mem, tx->tx_doorbell),
7936 1.15 jmcneill tx->tx_prod & MCX_WQ_DOORBELL_MASK);
7937 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, MCX_DMA_MAP(&sc->sc_doorbell_mem),
7938 1.15 jmcneill tx->tx_doorbell, sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
7939 1.1 jmcneill
7940 1.1 jmcneill /*
7941 1.1 jmcneill * write the first 64 bits of the last sqe we produced
7942 1.1 jmcneill * to the blue flame buffer
7943 1.1 jmcneill */
7944 1.15 jmcneill
7945 1.15 jmcneill blueflame = bf_base + tx->tx_bf_offset;
7946 1.1 jmcneill bus_space_write_8(sc->sc_memt, sc->sc_memh,
7947 1.15 jmcneill blueflame, *bf);
7948 1.15 jmcneill mcx_bar(sc, blueflame, sizeof(*bf), BUS_SPACE_BARRIER_WRITE);
7949 1.15 jmcneill
7950 1.1 jmcneill /* next write goes to the other buffer */
7951 1.15 jmcneill tx->tx_bf_offset ^= sc->sc_bf_size;
7952 1.1 jmcneill }
7953 1.1 jmcneill }
7954 1.1 jmcneill
7955 1.1 jmcneill static void
7956 1.16 jmcneill mcx_start(struct ifnet *ifp)
7957 1.16 jmcneill {
7958 1.16 jmcneill struct mcx_softc *sc = ifp->if_softc;
7959 1.16 jmcneill /* mcx_start() always uses TX ring[0] */
7960 1.16 jmcneill struct mcx_tx *tx = &sc->sc_queues[0].q_tx;
7961 1.16 jmcneill
7962 1.16 jmcneill mutex_enter(&tx->tx_lock);
7963 1.16 jmcneill if (!ISSET(ifp->if_flags, IFF_OACTIVE)) {
7964 1.16 jmcneill mcx_send_common_locked(ifp, tx, false);
7965 1.16 jmcneill }
7966 1.16 jmcneill mutex_exit(&tx->tx_lock);
7967 1.16 jmcneill }
7968 1.16 jmcneill
7969 1.16 jmcneill static int
7970 1.16 jmcneill mcx_transmit(struct ifnet *ifp, struct mbuf *m)
7971 1.16 jmcneill {
7972 1.16 jmcneill struct mcx_softc *sc = ifp->if_softc;
7973 1.16 jmcneill struct mcx_tx *tx;
7974 1.16 jmcneill
7975 1.16 jmcneill tx = &sc->sc_queues[cpu_index(curcpu()) % sc->sc_nqueues].q_tx;
7976 1.16 jmcneill if (__predict_false(!pcq_put(tx->tx_pcq, m))) {
7977 1.16 jmcneill m_freem(m);
7978 1.16 jmcneill return ENOBUFS;
7979 1.16 jmcneill }
7980 1.16 jmcneill
7981 1.16 jmcneill if (mutex_tryenter(&tx->tx_lock)) {
7982 1.16 jmcneill mcx_send_common_locked(ifp, tx, true);
7983 1.16 jmcneill mutex_exit(&tx->tx_lock);
7984 1.16 jmcneill } else {
7985 1.16 jmcneill softint_schedule(tx->tx_softint);
7986 1.16 jmcneill }
7987 1.16 jmcneill
7988 1.16 jmcneill return 0;
7989 1.16 jmcneill }
7990 1.16 jmcneill
7991 1.16 jmcneill static void
7992 1.16 jmcneill mcx_deferred_transmit(void *arg)
7993 1.16 jmcneill {
7994 1.16 jmcneill struct mcx_tx *tx = arg;
7995 1.16 jmcneill struct mcx_softc *sc = tx->tx_softc;
7996 1.16 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
7997 1.16 jmcneill
7998 1.16 jmcneill mutex_enter(&tx->tx_lock);
7999 1.16 jmcneill if (pcq_peek(tx->tx_pcq) != NULL) {
8000 1.16 jmcneill mcx_send_common_locked(ifp, tx, true);
8001 1.16 jmcneill }
8002 1.16 jmcneill mutex_exit(&tx->tx_lock);
8003 1.16 jmcneill }
8004 1.16 jmcneill
8005 1.16 jmcneill static void
8006 1.1 jmcneill mcx_watchdog(struct ifnet *ifp)
8007 1.1 jmcneill {
8008 1.1 jmcneill }
8009 1.1 jmcneill
8010 1.1 jmcneill static void
8011 1.1 jmcneill mcx_media_add_types(struct mcx_softc *sc)
8012 1.1 jmcneill {
8013 1.1 jmcneill struct mcx_reg_ptys ptys;
8014 1.1 jmcneill int i;
8015 1.1 jmcneill uint32_t proto_cap;
8016 1.1 jmcneill
8017 1.1 jmcneill memset(&ptys, 0, sizeof(ptys));
8018 1.1 jmcneill ptys.rp_local_port = 1;
8019 1.1 jmcneill ptys.rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH;
8020 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ, &ptys,
8021 1.1 jmcneill sizeof(ptys)) != 0) {
8022 1.1 jmcneill printf("%s: unable to read port type/speed\n", DEVNAME(sc));
8023 1.1 jmcneill return;
8024 1.1 jmcneill }
8025 1.1 jmcneill
8026 1.1 jmcneill proto_cap = be32toh(ptys.rp_eth_proto_cap);
8027 1.1 jmcneill for (i = 0; i < __arraycount(mcx_eth_cap_map); i++) {
8028 1.13 jmcneill const struct mcx_eth_proto_capability *cap;
8029 1.13 jmcneill if (!ISSET(proto_cap, 1U << i))
8030 1.13 jmcneill continue;
8031 1.13 jmcneill
8032 1.13 jmcneill cap = &mcx_eth_cap_map[i];
8033 1.13 jmcneill if (cap->cap_media == 0)
8034 1.13 jmcneill continue;
8035 1.13 jmcneill
8036 1.13 jmcneill ifmedia_add(&sc->sc_media, IFM_ETHER | cap->cap_media, 0, NULL);
8037 1.1 jmcneill }
8038 1.1 jmcneill }
8039 1.1 jmcneill
8040 1.1 jmcneill static void
8041 1.1 jmcneill mcx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
8042 1.1 jmcneill {
8043 1.1 jmcneill struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc;
8044 1.1 jmcneill struct mcx_reg_ptys ptys;
8045 1.1 jmcneill int i;
8046 1.13 jmcneill uint32_t proto_oper;
8047 1.1 jmcneill uint64_t media_oper;
8048 1.1 jmcneill
8049 1.1 jmcneill memset(&ptys, 0, sizeof(ptys));
8050 1.1 jmcneill ptys.rp_local_port = 1;
8051 1.1 jmcneill ptys.rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH;
8052 1.1 jmcneill
8053 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ, &ptys,
8054 1.1 jmcneill sizeof(ptys)) != 0) {
8055 1.1 jmcneill printf("%s: unable to read port type/speed\n", DEVNAME(sc));
8056 1.1 jmcneill return;
8057 1.1 jmcneill }
8058 1.1 jmcneill
8059 1.1 jmcneill proto_oper = be32toh(ptys.rp_eth_proto_oper);
8060 1.1 jmcneill
8061 1.1 jmcneill media_oper = 0;
8062 1.13 jmcneill
8063 1.1 jmcneill for (i = 0; i < __arraycount(mcx_eth_cap_map); i++) {
8064 1.13 jmcneill const struct mcx_eth_proto_capability *cap;
8065 1.13 jmcneill if (!ISSET(proto_oper, 1U << i))
8066 1.13 jmcneill continue;
8067 1.13 jmcneill
8068 1.13 jmcneill cap = &mcx_eth_cap_map[i];
8069 1.13 jmcneill
8070 1.13 jmcneill if (cap->cap_media != 0)
8071 1.13 jmcneill media_oper = cap->cap_media;
8072 1.1 jmcneill }
8073 1.1 jmcneill
8074 1.1 jmcneill ifmr->ifm_status = IFM_AVALID;
8075 1.1 jmcneill if (proto_oper != 0) {
8076 1.1 jmcneill ifmr->ifm_status |= IFM_ACTIVE;
8077 1.1 jmcneill ifmr->ifm_active = IFM_ETHER | IFM_AUTO | media_oper;
8078 1.1 jmcneill /* txpause, rxpause, duplex? */
8079 1.1 jmcneill }
8080 1.1 jmcneill }
8081 1.1 jmcneill
8082 1.1 jmcneill static int
8083 1.1 jmcneill mcx_media_change(struct ifnet *ifp)
8084 1.1 jmcneill {
8085 1.1 jmcneill struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc;
8086 1.1 jmcneill struct mcx_reg_ptys ptys;
8087 1.1 jmcneill struct mcx_reg_paos paos;
8088 1.1 jmcneill uint32_t media;
8089 1.1 jmcneill int i, error;
8090 1.1 jmcneill
8091 1.1 jmcneill if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
8092 1.1 jmcneill return EINVAL;
8093 1.1 jmcneill
8094 1.1 jmcneill error = 0;
8095 1.1 jmcneill
8096 1.1 jmcneill if (IFM_SUBTYPE(sc->sc_media.ifm_media) == IFM_AUTO) {
8097 1.1 jmcneill /* read ptys to get supported media */
8098 1.1 jmcneill memset(&ptys, 0, sizeof(ptys));
8099 1.1 jmcneill ptys.rp_local_port = 1;
8100 1.1 jmcneill ptys.rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH;
8101 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ,
8102 1.1 jmcneill &ptys, sizeof(ptys)) != 0) {
8103 1.1 jmcneill printf("%s: unable to read port type/speed\n",
8104 1.1 jmcneill DEVNAME(sc));
8105 1.1 jmcneill return EIO;
8106 1.1 jmcneill }
8107 1.1 jmcneill
8108 1.1 jmcneill media = be32toh(ptys.rp_eth_proto_cap);
8109 1.1 jmcneill } else {
8110 1.1 jmcneill /* map media type */
8111 1.1 jmcneill media = 0;
8112 1.1 jmcneill for (i = 0; i < __arraycount(mcx_eth_cap_map); i++) {
8113 1.13 jmcneill const struct mcx_eth_proto_capability *cap;
8114 1.13 jmcneill
8115 1.13 jmcneill cap = &mcx_eth_cap_map[i];
8116 1.13 jmcneill if (cap->cap_media ==
8117 1.1 jmcneill IFM_SUBTYPE(sc->sc_media.ifm_media)) {
8118 1.1 jmcneill media = (1 << i);
8119 1.1 jmcneill break;
8120 1.1 jmcneill }
8121 1.1 jmcneill }
8122 1.1 jmcneill }
8123 1.1 jmcneill
8124 1.1 jmcneill /* disable the port */
8125 1.1 jmcneill memset(&paos, 0, sizeof(paos));
8126 1.1 jmcneill paos.rp_local_port = 1;
8127 1.1 jmcneill paos.rp_admin_status = MCX_REG_PAOS_ADMIN_STATUS_DOWN;
8128 1.1 jmcneill paos.rp_admin_state_update = MCX_REG_PAOS_ADMIN_STATE_UPDATE_EN;
8129 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PAOS, MCX_REG_OP_WRITE, &paos,
8130 1.1 jmcneill sizeof(paos)) != 0) {
8131 1.1 jmcneill printf("%s: unable to set port state to down\n", DEVNAME(sc));
8132 1.1 jmcneill return EIO;
8133 1.1 jmcneill }
8134 1.1 jmcneill
8135 1.1 jmcneill memset(&ptys, 0, sizeof(ptys));
8136 1.1 jmcneill ptys.rp_local_port = 1;
8137 1.1 jmcneill ptys.rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH;
8138 1.1 jmcneill ptys.rp_eth_proto_admin = htobe32(media);
8139 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_WRITE, &ptys,
8140 1.1 jmcneill sizeof(ptys)) != 0) {
8141 1.1 jmcneill printf("%s: unable to set port media type/speed\n",
8142 1.1 jmcneill DEVNAME(sc));
8143 1.1 jmcneill error = EIO;
8144 1.1 jmcneill }
8145 1.1 jmcneill
8146 1.1 jmcneill /* re-enable the port to start negotiation */
8147 1.1 jmcneill memset(&paos, 0, sizeof(paos));
8148 1.1 jmcneill paos.rp_local_port = 1;
8149 1.1 jmcneill paos.rp_admin_status = MCX_REG_PAOS_ADMIN_STATUS_UP;
8150 1.1 jmcneill paos.rp_admin_state_update = MCX_REG_PAOS_ADMIN_STATE_UPDATE_EN;
8151 1.1 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PAOS, MCX_REG_OP_WRITE, &paos,
8152 1.1 jmcneill sizeof(paos)) != 0) {
8153 1.1 jmcneill printf("%s: unable to set port state to up\n", DEVNAME(sc));
8154 1.1 jmcneill error = EIO;
8155 1.1 jmcneill }
8156 1.1 jmcneill
8157 1.1 jmcneill return error;
8158 1.1 jmcneill }
8159 1.1 jmcneill
8160 1.1 jmcneill static void
8161 1.1 jmcneill mcx_port_change(struct work *wk, void *xsc)
8162 1.1 jmcneill {
8163 1.1 jmcneill struct mcx_softc *sc = xsc;
8164 1.1 jmcneill struct ifnet *ifp = &sc->sc_ec.ec_if;
8165 1.13 jmcneill struct mcx_reg_ptys ptys = {
8166 1.13 jmcneill .rp_local_port = 1,
8167 1.13 jmcneill .rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH,
8168 1.13 jmcneill };
8169 1.1 jmcneill int link_state = LINK_STATE_DOWN;
8170 1.1 jmcneill
8171 1.13 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ, &ptys,
8172 1.13 jmcneill sizeof(ptys)) == 0) {
8173 1.13 jmcneill uint32_t proto_oper = be32toh(ptys.rp_eth_proto_oper);
8174 1.13 jmcneill uint64_t baudrate = 0;
8175 1.13 jmcneill unsigned int i;
8176 1.13 jmcneill
8177 1.15 jmcneill if (proto_oper != 0)
8178 1.15 jmcneill link_state = LINK_STATE_UP;
8179 1.15 jmcneill
8180 1.13 jmcneill for (i = 0; i < __arraycount(mcx_eth_cap_map); i++) {
8181 1.13 jmcneill const struct mcx_eth_proto_capability *cap;
8182 1.13 jmcneill if (!ISSET(proto_oper, 1U << i))
8183 1.13 jmcneill continue;
8184 1.13 jmcneill
8185 1.13 jmcneill cap = &mcx_eth_cap_map[i];
8186 1.13 jmcneill if (cap->cap_baudrate == 0)
8187 1.13 jmcneill continue;
8188 1.13 jmcneill
8189 1.13 jmcneill baudrate = cap->cap_baudrate;
8190 1.13 jmcneill break;
8191 1.13 jmcneill }
8192 1.13 jmcneill
8193 1.13 jmcneill ifp->if_baudrate = baudrate;
8194 1.1 jmcneill }
8195 1.1 jmcneill
8196 1.1 jmcneill if (link_state != ifp->if_link_state) {
8197 1.1 jmcneill if_link_state_change(ifp, link_state);
8198 1.1 jmcneill }
8199 1.1 jmcneill }
8200 1.1 jmcneill
8201 1.1 jmcneill
8202 1.1 jmcneill static inline uint32_t
8203 1.1 jmcneill mcx_rd(struct mcx_softc *sc, bus_size_t r)
8204 1.1 jmcneill {
8205 1.1 jmcneill uint32_t word;
8206 1.1 jmcneill
8207 1.1 jmcneill word = bus_space_read_4(sc->sc_memt, sc->sc_memh, r);
8208 1.1 jmcneill
8209 1.1 jmcneill return (be32toh(word));
8210 1.1 jmcneill }
8211 1.1 jmcneill
8212 1.1 jmcneill static inline void
8213 1.1 jmcneill mcx_wr(struct mcx_softc *sc, bus_size_t r, uint32_t v)
8214 1.1 jmcneill {
8215 1.1 jmcneill bus_space_write_4(sc->sc_memt, sc->sc_memh, r, htobe32(v));
8216 1.1 jmcneill }
8217 1.1 jmcneill
8218 1.1 jmcneill static inline void
8219 1.1 jmcneill mcx_bar(struct mcx_softc *sc, bus_size_t r, bus_size_t l, int f)
8220 1.1 jmcneill {
8221 1.21 jmcneill #ifndef __NetBSD__
8222 1.1 jmcneill bus_space_barrier(sc->sc_memt, sc->sc_memh, r, l, f);
8223 1.21 jmcneill #endif
8224 1.1 jmcneill }
8225 1.1 jmcneill
8226 1.1 jmcneill static uint64_t
8227 1.1 jmcneill mcx_timer(struct mcx_softc *sc)
8228 1.1 jmcneill {
8229 1.1 jmcneill uint32_t hi, lo, ni;
8230 1.1 jmcneill
8231 1.1 jmcneill hi = mcx_rd(sc, MCX_INTERNAL_TIMER_H);
8232 1.1 jmcneill for (;;) {
8233 1.1 jmcneill lo = mcx_rd(sc, MCX_INTERNAL_TIMER_L);
8234 1.1 jmcneill mcx_bar(sc, MCX_INTERNAL_TIMER_L, 8, BUS_SPACE_BARRIER_READ);
8235 1.1 jmcneill ni = mcx_rd(sc, MCX_INTERNAL_TIMER_H);
8236 1.1 jmcneill
8237 1.1 jmcneill if (ni == hi)
8238 1.1 jmcneill break;
8239 1.1 jmcneill
8240 1.1 jmcneill hi = ni;
8241 1.1 jmcneill }
8242 1.1 jmcneill
8243 1.1 jmcneill return (((uint64_t)hi << 32) | (uint64_t)lo);
8244 1.1 jmcneill }
8245 1.1 jmcneill
8246 1.1 jmcneill static int
8247 1.1 jmcneill mcx_dmamem_alloc(struct mcx_softc *sc, struct mcx_dmamem *mxm,
8248 1.1 jmcneill bus_size_t size, u_int align)
8249 1.1 jmcneill {
8250 1.1 jmcneill mxm->mxm_size = size;
8251 1.1 jmcneill
8252 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, mxm->mxm_size, 1,
8253 1.1 jmcneill mxm->mxm_size, 0,
8254 1.1 jmcneill BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
8255 1.1 jmcneill &mxm->mxm_map) != 0)
8256 1.1 jmcneill return (1);
8257 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, mxm->mxm_size,
8258 1.1 jmcneill align, 0, &mxm->mxm_seg, 1, &mxm->mxm_nsegs,
8259 1.1 jmcneill BUS_DMA_WAITOK) != 0)
8260 1.1 jmcneill goto destroy;
8261 1.1 jmcneill if (bus_dmamem_map(sc->sc_dmat, &mxm->mxm_seg, mxm->mxm_nsegs,
8262 1.19 jmcneill mxm->mxm_size, &mxm->mxm_kva,
8263 1.19 jmcneill BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
8264 1.1 jmcneill goto free;
8265 1.1 jmcneill if (bus_dmamap_load(sc->sc_dmat, mxm->mxm_map, mxm->mxm_kva,
8266 1.1 jmcneill mxm->mxm_size, NULL, BUS_DMA_WAITOK) != 0)
8267 1.1 jmcneill goto unmap;
8268 1.1 jmcneill
8269 1.1 jmcneill mcx_dmamem_zero(mxm);
8270 1.1 jmcneill
8271 1.1 jmcneill return (0);
8272 1.1 jmcneill unmap:
8273 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
8274 1.1 jmcneill free:
8275 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
8276 1.1 jmcneill destroy:
8277 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
8278 1.1 jmcneill return (1);
8279 1.1 jmcneill }
8280 1.1 jmcneill
8281 1.1 jmcneill static void
8282 1.1 jmcneill mcx_dmamem_zero(struct mcx_dmamem *mxm)
8283 1.1 jmcneill {
8284 1.1 jmcneill memset(MCX_DMA_KVA(mxm), 0, MCX_DMA_LEN(mxm));
8285 1.1 jmcneill }
8286 1.1 jmcneill
8287 1.1 jmcneill static void
8288 1.1 jmcneill mcx_dmamem_free(struct mcx_softc *sc, struct mcx_dmamem *mxm)
8289 1.1 jmcneill {
8290 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map);
8291 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
8292 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
8293 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
8294 1.1 jmcneill }
8295 1.1 jmcneill
8296 1.1 jmcneill static int
8297 1.1 jmcneill mcx_hwmem_alloc(struct mcx_softc *sc, struct mcx_hwmem *mhm, unsigned int pages)
8298 1.1 jmcneill {
8299 1.1 jmcneill bus_dma_segment_t *segs;
8300 1.1 jmcneill bus_size_t len = pages * MCX_PAGE_SIZE;
8301 1.1 jmcneill size_t seglen;
8302 1.1 jmcneill
8303 1.1 jmcneill segs = kmem_alloc(sizeof(*segs) * pages, KM_SLEEP);
8304 1.1 jmcneill seglen = sizeof(*segs) * pages;
8305 1.1 jmcneill
8306 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, len, MCX_PAGE_SIZE, 0,
8307 1.1 jmcneill segs, pages, &mhm->mhm_seg_count, BUS_DMA_NOWAIT) != 0)
8308 1.1 jmcneill goto free_segs;
8309 1.1 jmcneill
8310 1.1 jmcneill if (mhm->mhm_seg_count < pages) {
8311 1.1 jmcneill size_t nseglen;
8312 1.1 jmcneill
8313 1.1 jmcneill mhm->mhm_segs = kmem_alloc(
8314 1.1 jmcneill sizeof(*mhm->mhm_segs) * mhm->mhm_seg_count, KM_SLEEP);
8315 1.1 jmcneill
8316 1.1 jmcneill nseglen = sizeof(*mhm->mhm_segs) * mhm->mhm_seg_count;
8317 1.1 jmcneill
8318 1.1 jmcneill memcpy(mhm->mhm_segs, segs, nseglen);
8319 1.1 jmcneill
8320 1.1 jmcneill kmem_free(segs, seglen);
8321 1.1 jmcneill
8322 1.1 jmcneill segs = mhm->mhm_segs;
8323 1.1 jmcneill seglen = nseglen;
8324 1.1 jmcneill } else
8325 1.1 jmcneill mhm->mhm_segs = segs;
8326 1.1 jmcneill
8327 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, len, pages, MCX_PAGE_SIZE,
8328 1.1 jmcneill MCX_PAGE_SIZE, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW /*|BUS_DMA_64BIT*/,
8329 1.1 jmcneill &mhm->mhm_map) != 0)
8330 1.1 jmcneill goto free_dmamem;
8331 1.1 jmcneill
8332 1.1 jmcneill if (bus_dmamap_load_raw(sc->sc_dmat, mhm->mhm_map,
8333 1.1 jmcneill mhm->mhm_segs, mhm->mhm_seg_count, len, BUS_DMA_NOWAIT) != 0)
8334 1.1 jmcneill goto destroy;
8335 1.1 jmcneill
8336 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, mhm->mhm_map,
8337 1.1 jmcneill 0, mhm->mhm_map->dm_mapsize, BUS_DMASYNC_PRERW);
8338 1.1 jmcneill
8339 1.1 jmcneill mhm->mhm_npages = pages;
8340 1.1 jmcneill
8341 1.1 jmcneill return (0);
8342 1.1 jmcneill
8343 1.1 jmcneill destroy:
8344 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, mhm->mhm_map);
8345 1.1 jmcneill free_dmamem:
8346 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, mhm->mhm_segs, mhm->mhm_seg_count);
8347 1.1 jmcneill free_segs:
8348 1.1 jmcneill kmem_free(segs, seglen);
8349 1.1 jmcneill mhm->mhm_segs = NULL;
8350 1.1 jmcneill
8351 1.1 jmcneill return (-1);
8352 1.1 jmcneill }
8353 1.1 jmcneill
8354 1.1 jmcneill static void
8355 1.1 jmcneill mcx_hwmem_free(struct mcx_softc *sc, struct mcx_hwmem *mhm)
8356 1.1 jmcneill {
8357 1.1 jmcneill if (mhm->mhm_npages == 0)
8358 1.1 jmcneill return;
8359 1.1 jmcneill
8360 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, mhm->mhm_map,
8361 1.1 jmcneill 0, mhm->mhm_map->dm_mapsize, BUS_DMASYNC_POSTRW);
8362 1.1 jmcneill
8363 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, mhm->mhm_map);
8364 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, mhm->mhm_map);
8365 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, mhm->mhm_segs, mhm->mhm_seg_count);
8366 1.1 jmcneill kmem_free(mhm->mhm_segs, sizeof(*mhm->mhm_segs) * mhm->mhm_seg_count);
8367 1.1 jmcneill
8368 1.1 jmcneill mhm->mhm_npages = 0;
8369 1.1 jmcneill }
8370 1.15 jmcneill
8371 1.15 jmcneill #if NKSTAT > 0
8372 1.15 jmcneill struct mcx_ppcnt {
8373 1.15 jmcneill char name[KSTAT_KV_NAMELEN];
8374 1.15 jmcneill enum kstat_kv_unit unit;
8375 1.15 jmcneill };
8376 1.15 jmcneill
8377 1.15 jmcneill static const struct mcx_ppcnt mcx_ppcnt_ieee8023_tpl[] = {
8378 1.15 jmcneill { "Good Tx", KSTAT_KV_U_PACKETS, },
8379 1.15 jmcneill { "Good Rx", KSTAT_KV_U_PACKETS, },
8380 1.15 jmcneill { "FCS errs", KSTAT_KV_U_PACKETS, },
8381 1.15 jmcneill { "Alignment Errs", KSTAT_KV_U_PACKETS, },
8382 1.15 jmcneill { "Good Tx", KSTAT_KV_U_BYTES, },
8383 1.15 jmcneill { "Good Rx", KSTAT_KV_U_BYTES, },
8384 1.15 jmcneill { "Multicast Tx", KSTAT_KV_U_PACKETS, },
8385 1.15 jmcneill { "Broadcast Tx", KSTAT_KV_U_PACKETS, },
8386 1.15 jmcneill { "Multicast Rx", KSTAT_KV_U_PACKETS, },
8387 1.15 jmcneill { "Broadcast Rx", KSTAT_KV_U_PACKETS, },
8388 1.15 jmcneill { "In Range Len", KSTAT_KV_U_PACKETS, },
8389 1.15 jmcneill { "Out Of Range Len", KSTAT_KV_U_PACKETS, },
8390 1.15 jmcneill { "Frame Too Long", KSTAT_KV_U_PACKETS, },
8391 1.15 jmcneill { "Symbol Errs", KSTAT_KV_U_PACKETS, },
8392 1.15 jmcneill { "MAC Ctrl Tx", KSTAT_KV_U_PACKETS, },
8393 1.15 jmcneill { "MAC Ctrl Rx", KSTAT_KV_U_PACKETS, },
8394 1.15 jmcneill { "MAC Ctrl Unsup", KSTAT_KV_U_PACKETS, },
8395 1.15 jmcneill { "Pause Rx", KSTAT_KV_U_PACKETS, },
8396 1.15 jmcneill { "Pause Tx", KSTAT_KV_U_PACKETS, },
8397 1.15 jmcneill };
8398 1.15 jmcneill CTASSERT(__arraycount(mcx_ppcnt_ieee8023_tpl) == mcx_ppcnt_ieee8023_count);
8399 1.15 jmcneill
8400 1.15 jmcneill static const struct mcx_ppcnt mcx_ppcnt_rfc2863_tpl[] = {
8401 1.15 jmcneill { "Rx Bytes", KSTAT_KV_U_BYTES, },
8402 1.15 jmcneill { "Rx Unicast", KSTAT_KV_U_PACKETS, },
8403 1.15 jmcneill { "Rx Discards", KSTAT_KV_U_PACKETS, },
8404 1.15 jmcneill { "Rx Errors", KSTAT_KV_U_PACKETS, },
8405 1.15 jmcneill { "Rx Unknown Proto", KSTAT_KV_U_PACKETS, },
8406 1.15 jmcneill { "Tx Bytes", KSTAT_KV_U_BYTES, },
8407 1.15 jmcneill { "Tx Unicast", KSTAT_KV_U_PACKETS, },
8408 1.15 jmcneill { "Tx Discards", KSTAT_KV_U_PACKETS, },
8409 1.15 jmcneill { "Tx Errors", KSTAT_KV_U_PACKETS, },
8410 1.15 jmcneill { "Rx Multicast", KSTAT_KV_U_PACKETS, },
8411 1.15 jmcneill { "Rx Broadcast", KSTAT_KV_U_PACKETS, },
8412 1.15 jmcneill { "Tx Multicast", KSTAT_KV_U_PACKETS, },
8413 1.15 jmcneill { "Tx Broadcast", KSTAT_KV_U_PACKETS, },
8414 1.15 jmcneill };
8415 1.15 jmcneill CTASSERT(__arraycount(mcx_ppcnt_rfc2863_tpl) == mcx_ppcnt_rfc2863_count);
8416 1.15 jmcneill
8417 1.15 jmcneill static const struct mcx_ppcnt mcx_ppcnt_rfc2819_tpl[] = {
8418 1.15 jmcneill { "Drop Events", KSTAT_KV_U_PACKETS, },
8419 1.15 jmcneill { "Octets", KSTAT_KV_U_BYTES, },
8420 1.15 jmcneill { "Packets", KSTAT_KV_U_PACKETS, },
8421 1.15 jmcneill { "Broadcasts", KSTAT_KV_U_PACKETS, },
8422 1.15 jmcneill { "Multicasts", KSTAT_KV_U_PACKETS, },
8423 1.15 jmcneill { "CRC Align Errs", KSTAT_KV_U_PACKETS, },
8424 1.15 jmcneill { "Undersize", KSTAT_KV_U_PACKETS, },
8425 1.15 jmcneill { "Oversize", KSTAT_KV_U_PACKETS, },
8426 1.15 jmcneill { "Fragments", KSTAT_KV_U_PACKETS, },
8427 1.15 jmcneill { "Jabbers", KSTAT_KV_U_PACKETS, },
8428 1.15 jmcneill { "Collisions", KSTAT_KV_U_NONE, },
8429 1.15 jmcneill { "64B", KSTAT_KV_U_PACKETS, },
8430 1.15 jmcneill { "65-127B", KSTAT_KV_U_PACKETS, },
8431 1.15 jmcneill { "128-255B", KSTAT_KV_U_PACKETS, },
8432 1.15 jmcneill { "256-511B", KSTAT_KV_U_PACKETS, },
8433 1.15 jmcneill { "512-1023B", KSTAT_KV_U_PACKETS, },
8434 1.15 jmcneill { "1024-1518B", KSTAT_KV_U_PACKETS, },
8435 1.15 jmcneill { "1519-2047B", KSTAT_KV_U_PACKETS, },
8436 1.15 jmcneill { "2048-4095B", KSTAT_KV_U_PACKETS, },
8437 1.15 jmcneill { "4096-8191B", KSTAT_KV_U_PACKETS, },
8438 1.15 jmcneill { "8192-10239B", KSTAT_KV_U_PACKETS, },
8439 1.15 jmcneill };
8440 1.15 jmcneill CTASSERT(__arraycount(mcx_ppcnt_rfc2819_tpl) == mcx_ppcnt_rfc2819_count);
8441 1.15 jmcneill
8442 1.15 jmcneill static const struct mcx_ppcnt mcx_ppcnt_rfc3635_tpl[] = {
8443 1.15 jmcneill { "Alignment Errs", KSTAT_KV_U_PACKETS, },
8444 1.15 jmcneill { "FCS Errs", KSTAT_KV_U_PACKETS, },
8445 1.15 jmcneill { "Single Colls", KSTAT_KV_U_PACKETS, },
8446 1.15 jmcneill { "Multiple Colls", KSTAT_KV_U_PACKETS, },
8447 1.15 jmcneill { "SQE Test Errs", KSTAT_KV_U_NONE, },
8448 1.15 jmcneill { "Deferred Tx", KSTAT_KV_U_PACKETS, },
8449 1.15 jmcneill { "Late Colls", KSTAT_KV_U_NONE, },
8450 1.15 jmcneill { "Exess Colls", KSTAT_KV_U_NONE, },
8451 1.15 jmcneill { "Int MAC Tx Errs", KSTAT_KV_U_PACKETS, },
8452 1.15 jmcneill { "CSM Sense Errs", KSTAT_KV_U_NONE, },
8453 1.15 jmcneill { "Too Long", KSTAT_KV_U_PACKETS, },
8454 1.15 jmcneill { "Int MAC Rx Errs", KSTAT_KV_U_PACKETS, },
8455 1.15 jmcneill { "Symbol Errs", KSTAT_KV_U_NONE, },
8456 1.15 jmcneill { "Unknown Control", KSTAT_KV_U_PACKETS, },
8457 1.15 jmcneill { "Pause Rx", KSTAT_KV_U_PACKETS, },
8458 1.15 jmcneill { "Pause Tx", KSTAT_KV_U_PACKETS, },
8459 1.15 jmcneill };
8460 1.15 jmcneill CTASSERT(__arraycount(mcx_ppcnt_rfc3635_tpl) == mcx_ppcnt_rfc3635_count);
8461 1.15 jmcneill
8462 1.15 jmcneill struct mcx_kstat_ppcnt {
8463 1.15 jmcneill const char *ksp_name;
8464 1.15 jmcneill const struct mcx_ppcnt *ksp_tpl;
8465 1.15 jmcneill unsigned int ksp_n;
8466 1.15 jmcneill uint8_t ksp_grp;
8467 1.15 jmcneill };
8468 1.15 jmcneill
8469 1.15 jmcneill static const struct mcx_kstat_ppcnt mcx_kstat_ppcnt_ieee8023 = {
8470 1.15 jmcneill .ksp_name = "ieee802.3",
8471 1.15 jmcneill .ksp_tpl = mcx_ppcnt_ieee8023_tpl,
8472 1.15 jmcneill .ksp_n = __arraycount(mcx_ppcnt_ieee8023_tpl),
8473 1.15 jmcneill .ksp_grp = MCX_REG_PPCNT_GRP_IEEE8023,
8474 1.15 jmcneill };
8475 1.15 jmcneill
8476 1.15 jmcneill static const struct mcx_kstat_ppcnt mcx_kstat_ppcnt_rfc2863 = {
8477 1.15 jmcneill .ksp_name = "rfc2863",
8478 1.15 jmcneill .ksp_tpl = mcx_ppcnt_rfc2863_tpl,
8479 1.15 jmcneill .ksp_n = __arraycount(mcx_ppcnt_rfc2863_tpl),
8480 1.15 jmcneill .ksp_grp = MCX_REG_PPCNT_GRP_RFC2863,
8481 1.15 jmcneill };
8482 1.15 jmcneill
8483 1.15 jmcneill static const struct mcx_kstat_ppcnt mcx_kstat_ppcnt_rfc2819 = {
8484 1.15 jmcneill .ksp_name = "rfc2819",
8485 1.15 jmcneill .ksp_tpl = mcx_ppcnt_rfc2819_tpl,
8486 1.15 jmcneill .ksp_n = __arraycount(mcx_ppcnt_rfc2819_tpl),
8487 1.15 jmcneill .ksp_grp = MCX_REG_PPCNT_GRP_RFC2819,
8488 1.15 jmcneill };
8489 1.15 jmcneill
8490 1.15 jmcneill static const struct mcx_kstat_ppcnt mcx_kstat_ppcnt_rfc3635 = {
8491 1.15 jmcneill .ksp_name = "rfc3635",
8492 1.15 jmcneill .ksp_tpl = mcx_ppcnt_rfc3635_tpl,
8493 1.15 jmcneill .ksp_n = __arraycount(mcx_ppcnt_rfc3635_tpl),
8494 1.15 jmcneill .ksp_grp = MCX_REG_PPCNT_GRP_RFC3635,
8495 1.15 jmcneill };
8496 1.15 jmcneill
8497 1.15 jmcneill static int mcx_kstat_ppcnt_read(struct kstat *);
8498 1.15 jmcneill
8499 1.15 jmcneill static void mcx_kstat_attach_tmps(struct mcx_softc *sc);
8500 1.15 jmcneill static void mcx_kstat_attach_queues(struct mcx_softc *sc);
8501 1.15 jmcneill
8502 1.15 jmcneill static struct kstat *
8503 1.15 jmcneill mcx_kstat_attach_ppcnt(struct mcx_softc *sc,
8504 1.15 jmcneill const struct mcx_kstat_ppcnt *ksp)
8505 1.15 jmcneill {
8506 1.15 jmcneill struct kstat *ks;
8507 1.15 jmcneill struct kstat_kv *kvs;
8508 1.15 jmcneill unsigned int i;
8509 1.15 jmcneill
8510 1.15 jmcneill ks = kstat_create(DEVNAME(sc), 0, ksp->ksp_name, 0, KSTAT_T_KV, 0);
8511 1.15 jmcneill if (ks == NULL)
8512 1.15 jmcneill return (NULL);
8513 1.15 jmcneill
8514 1.15 jmcneill kvs = mallocarray(ksp->ksp_n, sizeof(*kvs),
8515 1.15 jmcneill M_DEVBUF, M_WAITOK);
8516 1.15 jmcneill
8517 1.15 jmcneill for (i = 0; i < ksp->ksp_n; i++) {
8518 1.15 jmcneill const struct mcx_ppcnt *tpl = &ksp->ksp_tpl[i];
8519 1.15 jmcneill
8520 1.15 jmcneill kstat_kv_unit_init(&kvs[i], tpl->name,
8521 1.15 jmcneill KSTAT_KV_T_COUNTER64, tpl->unit);
8522 1.15 jmcneill }
8523 1.15 jmcneill
8524 1.15 jmcneill ks->ks_softc = sc;
8525 1.15 jmcneill ks->ks_ptr = (void *)ksp;
8526 1.15 jmcneill ks->ks_data = kvs;
8527 1.15 jmcneill ks->ks_datalen = ksp->ksp_n * sizeof(*kvs);
8528 1.15 jmcneill ks->ks_read = mcx_kstat_ppcnt_read;
8529 1.15 jmcneill
8530 1.15 jmcneill kstat_install(ks);
8531 1.15 jmcneill
8532 1.15 jmcneill return (ks);
8533 1.15 jmcneill }
8534 1.15 jmcneill
8535 1.15 jmcneill static void
8536 1.15 jmcneill mcx_kstat_attach(struct mcx_softc *sc)
8537 1.15 jmcneill {
8538 1.15 jmcneill sc->sc_kstat_ieee8023 = mcx_kstat_attach_ppcnt(sc,
8539 1.15 jmcneill &mcx_kstat_ppcnt_ieee8023);
8540 1.15 jmcneill sc->sc_kstat_rfc2863 = mcx_kstat_attach_ppcnt(sc,
8541 1.15 jmcneill &mcx_kstat_ppcnt_rfc2863);
8542 1.15 jmcneill sc->sc_kstat_rfc2819 = mcx_kstat_attach_ppcnt(sc,
8543 1.15 jmcneill &mcx_kstat_ppcnt_rfc2819);
8544 1.15 jmcneill sc->sc_kstat_rfc3635 = mcx_kstat_attach_ppcnt(sc,
8545 1.15 jmcneill &mcx_kstat_ppcnt_rfc3635);
8546 1.15 jmcneill
8547 1.15 jmcneill mcx_kstat_attach_tmps(sc);
8548 1.15 jmcneill mcx_kstat_attach_queues(sc);
8549 1.15 jmcneill }
8550 1.15 jmcneill
8551 1.15 jmcneill static int
8552 1.15 jmcneill mcx_kstat_ppcnt_read(struct kstat *ks)
8553 1.15 jmcneill {
8554 1.15 jmcneill struct mcx_softc *sc = ks->ks_softc;
8555 1.15 jmcneill struct mcx_kstat_ppcnt *ksp = ks->ks_ptr;
8556 1.15 jmcneill struct mcx_reg_ppcnt ppcnt = {
8557 1.15 jmcneill .ppcnt_grp = ksp->ksp_grp,
8558 1.15 jmcneill .ppcnt_local_port = 1,
8559 1.15 jmcneill };
8560 1.15 jmcneill struct kstat_kv *kvs = ks->ks_data;
8561 1.15 jmcneill uint64_t *vs = (uint64_t *)&ppcnt.ppcnt_counter_set;
8562 1.15 jmcneill unsigned int i;
8563 1.15 jmcneill int rv;
8564 1.15 jmcneill
8565 1.15 jmcneill KERNEL_LOCK(); /* XXX */
8566 1.15 jmcneill rv = mcx_access_hca_reg(sc, MCX_REG_PPCNT, MCX_REG_OP_READ,
8567 1.15 jmcneill &ppcnt, sizeof(ppcnt));
8568 1.15 jmcneill KERNEL_UNLOCK();
8569 1.15 jmcneill if (rv != 0)
8570 1.15 jmcneill return (EIO);
8571 1.15 jmcneill
8572 1.15 jmcneill nanouptime(&ks->ks_updated);
8573 1.15 jmcneill
8574 1.15 jmcneill for (i = 0; i < ksp->ksp_n; i++)
8575 1.15 jmcneill kstat_kv_u64(&kvs[i]) = bemtoh64(&vs[i]);
8576 1.15 jmcneill
8577 1.15 jmcneill return (0);
8578 1.15 jmcneill }
8579 1.15 jmcneill
8580 1.15 jmcneill struct mcx_kstat_mtmp {
8581 1.15 jmcneill struct kstat_kv ktmp_name;
8582 1.15 jmcneill struct kstat_kv ktmp_temperature;
8583 1.15 jmcneill struct kstat_kv ktmp_threshold_lo;
8584 1.15 jmcneill struct kstat_kv ktmp_threshold_hi;
8585 1.15 jmcneill };
8586 1.15 jmcneill
8587 1.15 jmcneill static const struct mcx_kstat_mtmp mcx_kstat_mtmp_tpl = {
8588 1.15 jmcneill KSTAT_KV_INITIALIZER("name", KSTAT_KV_T_ISTR),
8589 1.15 jmcneill KSTAT_KV_INITIALIZER("temperature", KSTAT_KV_T_TEMP),
8590 1.15 jmcneill KSTAT_KV_INITIALIZER("lo threshold", KSTAT_KV_T_TEMP),
8591 1.15 jmcneill KSTAT_KV_INITIALIZER("hi threshold", KSTAT_KV_T_TEMP),
8592 1.15 jmcneill };
8593 1.15 jmcneill
8594 1.15 jmcneill static const struct timeval mcx_kstat_mtmp_rate = { 1, 0 };
8595 1.15 jmcneill
8596 1.15 jmcneill static int mcx_kstat_mtmp_read(struct kstat *);
8597 1.15 jmcneill
8598 1.15 jmcneill static void
8599 1.15 jmcneill mcx_kstat_attach_tmps(struct mcx_softc *sc)
8600 1.15 jmcneill {
8601 1.15 jmcneill struct kstat *ks;
8602 1.15 jmcneill struct mcx_reg_mcam mcam;
8603 1.15 jmcneill struct mcx_reg_mtcap mtcap;
8604 1.15 jmcneill struct mcx_kstat_mtmp *ktmp;
8605 1.15 jmcneill uint64_t map;
8606 1.15 jmcneill unsigned int i, n;
8607 1.15 jmcneill
8608 1.15 jmcneill memset(&mtcap, 0, sizeof(mtcap));
8609 1.15 jmcneill memset(&mcam, 0, sizeof(mcam));
8610 1.15 jmcneill
8611 1.15 jmcneill if (sc->sc_mcam_reg == 0) {
8612 1.15 jmcneill /* no management capabilities */
8613 1.15 jmcneill return;
8614 1.15 jmcneill }
8615 1.15 jmcneill
8616 1.15 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_MCAM, MCX_REG_OP_READ,
8617 1.15 jmcneill &mcam, sizeof(mcam)) != 0) {
8618 1.15 jmcneill /* unable to check management capabilities? */
8619 1.15 jmcneill return;
8620 1.15 jmcneill }
8621 1.15 jmcneill
8622 1.15 jmcneill if (MCX_BITFIELD_BIT(mcam.mcam_feature_cap_mask,
8623 1.15 jmcneill MCX_MCAM_FEATURE_CAP_SENSOR_MAP) == 0) {
8624 1.15 jmcneill /* no sensor map */
8625 1.15 jmcneill return;
8626 1.15 jmcneill }
8627 1.15 jmcneill
8628 1.15 jmcneill if (mcx_access_hca_reg(sc, MCX_REG_MTCAP, MCX_REG_OP_READ,
8629 1.15 jmcneill &mtcap, sizeof(mtcap)) != 0) {
8630 1.15 jmcneill /* unable to find temperature sensors */
8631 1.15 jmcneill return;
8632 1.15 jmcneill }
8633 1.15 jmcneill
8634 1.15 jmcneill sc->sc_kstat_mtmp_count = mtcap.mtcap_sensor_count;
8635 1.15 jmcneill sc->sc_kstat_mtmp = mallocarray(sc->sc_kstat_mtmp_count,
8636 1.15 jmcneill sizeof(*sc->sc_kstat_mtmp), M_DEVBUF, M_WAITOK);
8637 1.15 jmcneill
8638 1.15 jmcneill n = 0;
8639 1.15 jmcneill map = bemtoh64(&mtcap.mtcap_sensor_map);
8640 1.15 jmcneill for (i = 0; i < sizeof(map) * NBBY; i++) {
8641 1.15 jmcneill if (!ISSET(map, (1ULL << i)))
8642 1.15 jmcneill continue;
8643 1.15 jmcneill
8644 1.15 jmcneill ks = kstat_create(DEVNAME(sc), 0, "temperature", i,
8645 1.15 jmcneill KSTAT_T_KV, 0);
8646 1.15 jmcneill if (ks == NULL) {
8647 1.15 jmcneill /* unable to attach temperature sensor %u, i */
8648 1.15 jmcneill continue;
8649 1.15 jmcneill }
8650 1.15 jmcneill
8651 1.15 jmcneill ktmp = malloc(sizeof(*ktmp), M_DEVBUF, M_WAITOK|M_ZERO);
8652 1.15 jmcneill *ktmp = mcx_kstat_mtmp_tpl;
8653 1.15 jmcneill
8654 1.15 jmcneill ks->ks_data = ktmp;
8655 1.15 jmcneill ks->ks_datalen = sizeof(*ktmp);
8656 1.15 jmcneill TIMEVAL_TO_TIMESPEC(&mcx_kstat_mtmp_rate, &ks->ks_interval);
8657 1.15 jmcneill ks->ks_read = mcx_kstat_mtmp_read;
8658 1.15 jmcneill
8659 1.15 jmcneill ks->ks_softc = sc;
8660 1.15 jmcneill kstat_install(ks);
8661 1.15 jmcneill
8662 1.15 jmcneill sc->sc_kstat_mtmp[n++] = ks;
8663 1.15 jmcneill if (n >= sc->sc_kstat_mtmp_count)
8664 1.15 jmcneill break;
8665 1.15 jmcneill }
8666 1.15 jmcneill }
8667 1.15 jmcneill
8668 1.15 jmcneill static uint64_t
8669 1.15 jmcneill mcx_tmp_to_uK(uint16_t *t)
8670 1.15 jmcneill {
8671 1.15 jmcneill int64_t mt = (int16_t)bemtoh16(t); /* 0.125 C units */
8672 1.15 jmcneill mt *= 1000000 / 8; /* convert to uC */
8673 1.15 jmcneill mt += 273150000; /* convert to uK */
8674 1.15 jmcneill
8675 1.15 jmcneill return (mt);
8676 1.15 jmcneill }
8677 1.15 jmcneill
8678 1.15 jmcneill static int
8679 1.15 jmcneill mcx_kstat_mtmp_read(struct kstat *ks)
8680 1.15 jmcneill {
8681 1.15 jmcneill struct mcx_softc *sc = ks->ks_softc;
8682 1.15 jmcneill struct mcx_kstat_mtmp *ktmp = ks->ks_data;
8683 1.15 jmcneill struct mcx_reg_mtmp mtmp;
8684 1.15 jmcneill int rv;
8685 1.15 jmcneill struct timeval updated;
8686 1.15 jmcneill
8687 1.15 jmcneill TIMESPEC_TO_TIMEVAL(&updated, &ks->ks_updated);
8688 1.15 jmcneill
8689 1.15 jmcneill if (!ratecheck(&updated, &mcx_kstat_mtmp_rate))
8690 1.15 jmcneill return (0);
8691 1.15 jmcneill
8692 1.15 jmcneill memset(&mtmp, 0, sizeof(mtmp));
8693 1.15 jmcneill htobem16(&mtmp.mtmp_sensor_index, ks->ks_unit);
8694 1.15 jmcneill
8695 1.15 jmcneill KERNEL_LOCK(); /* XXX */
8696 1.15 jmcneill rv = mcx_access_hca_reg(sc, MCX_REG_MTMP, MCX_REG_OP_READ,
8697 1.15 jmcneill &mtmp, sizeof(mtmp));
8698 1.15 jmcneill KERNEL_UNLOCK();
8699 1.15 jmcneill if (rv != 0)
8700 1.15 jmcneill return (EIO);
8701 1.15 jmcneill
8702 1.15 jmcneill memset(kstat_kv_istr(&ktmp->ktmp_name), 0,
8703 1.15 jmcneill sizeof(kstat_kv_istr(&ktmp->ktmp_name)));
8704 1.15 jmcneill memcpy(kstat_kv_istr(&ktmp->ktmp_name),
8705 1.15 jmcneill mtmp.mtmp_sensor_name, sizeof(mtmp.mtmp_sensor_name));
8706 1.15 jmcneill kstat_kv_temp(&ktmp->ktmp_temperature) =
8707 1.15 jmcneill mcx_tmp_to_uK(&mtmp.mtmp_temperature);
8708 1.15 jmcneill kstat_kv_temp(&ktmp->ktmp_threshold_lo) =
8709 1.15 jmcneill mcx_tmp_to_uK(&mtmp.mtmp_temperature_threshold_lo);
8710 1.15 jmcneill kstat_kv_temp(&ktmp->ktmp_threshold_hi) =
8711 1.15 jmcneill mcx_tmp_to_uK(&mtmp.mtmp_temperature_threshold_hi);
8712 1.15 jmcneill
8713 1.15 jmcneill TIMEVAL_TO_TIMESPEC(&updated, &ks->ks_updated);
8714 1.15 jmcneill
8715 1.15 jmcneill return (0);
8716 1.15 jmcneill }
8717 1.15 jmcneill
8718 1.15 jmcneill struct mcx_queuestat {
8719 1.15 jmcneill char name[KSTAT_KV_NAMELEN];
8720 1.15 jmcneill enum kstat_kv_type type;
8721 1.15 jmcneill };
8722 1.15 jmcneill
8723 1.15 jmcneill static const struct mcx_queuestat mcx_queue_kstat_tpl[] = {
8724 1.15 jmcneill { "RQ SW prod", KSTAT_KV_T_COUNTER64 },
8725 1.15 jmcneill { "RQ HW prod", KSTAT_KV_T_COUNTER64 },
8726 1.15 jmcneill { "RQ HW cons", KSTAT_KV_T_COUNTER64 },
8727 1.15 jmcneill { "RQ HW state", KSTAT_KV_T_ISTR },
8728 1.15 jmcneill
8729 1.15 jmcneill { "SQ SW prod", KSTAT_KV_T_COUNTER64 },
8730 1.15 jmcneill { "SQ SW cons", KSTAT_KV_T_COUNTER64 },
8731 1.15 jmcneill { "SQ HW prod", KSTAT_KV_T_COUNTER64 },
8732 1.15 jmcneill { "SQ HW cons", KSTAT_KV_T_COUNTER64 },
8733 1.15 jmcneill { "SQ HW state", KSTAT_KV_T_ISTR },
8734 1.15 jmcneill
8735 1.15 jmcneill { "CQ SW cons", KSTAT_KV_T_COUNTER64 },
8736 1.15 jmcneill { "CQ HW prod", KSTAT_KV_T_COUNTER64 },
8737 1.15 jmcneill { "CQ HW cons", KSTAT_KV_T_COUNTER64 },
8738 1.15 jmcneill { "CQ HW notify", KSTAT_KV_T_COUNTER64 },
8739 1.15 jmcneill { "CQ HW solicit", KSTAT_KV_T_COUNTER64 },
8740 1.15 jmcneill { "CQ HW status", KSTAT_KV_T_ISTR },
8741 1.15 jmcneill { "CQ HW state", KSTAT_KV_T_ISTR },
8742 1.15 jmcneill
8743 1.15 jmcneill { "EQ SW cons", KSTAT_KV_T_COUNTER64 },
8744 1.15 jmcneill { "EQ HW prod", KSTAT_KV_T_COUNTER64 },
8745 1.15 jmcneill { "EQ HW cons", KSTAT_KV_T_COUNTER64 },
8746 1.15 jmcneill { "EQ HW status", KSTAT_KV_T_ISTR },
8747 1.15 jmcneill { "EQ HW state", KSTAT_KV_T_ISTR },
8748 1.15 jmcneill };
8749 1.15 jmcneill
8750 1.15 jmcneill static int mcx_kstat_queue_read(struct kstat *);
8751 1.15 jmcneill
8752 1.15 jmcneill static void
8753 1.15 jmcneill mcx_kstat_attach_queues(struct mcx_softc *sc)
8754 1.15 jmcneill {
8755 1.15 jmcneill struct kstat *ks;
8756 1.15 jmcneill struct kstat_kv *kvs;
8757 1.15 jmcneill int q, i;
8758 1.15 jmcneill
8759 1.15 jmcneill for (q = 0; q < sc->sc_nqueues; q++) {
8760 1.15 jmcneill ks = kstat_create(DEVNAME(sc), 0, "mcx-queues", q,
8761 1.15 jmcneill KSTAT_T_KV, 0);
8762 1.15 jmcneill if (ks == NULL) {
8763 1.15 jmcneill /* unable to attach queue stats %u, q */
8764 1.15 jmcneill continue;
8765 1.15 jmcneill }
8766 1.15 jmcneill
8767 1.15 jmcneill kvs = mallocarray(nitems(mcx_queue_kstat_tpl),
8768 1.15 jmcneill sizeof(*kvs), M_DEVBUF, M_WAITOK);
8769 1.15 jmcneill
8770 1.15 jmcneill for (i = 0; i < nitems(mcx_queue_kstat_tpl); i++) {
8771 1.15 jmcneill const struct mcx_queuestat *tpl =
8772 1.15 jmcneill &mcx_queue_kstat_tpl[i];
8773 1.15 jmcneill
8774 1.15 jmcneill kstat_kv_init(&kvs[i], tpl->name, tpl->type);
8775 1.15 jmcneill }
8776 1.15 jmcneill
8777 1.15 jmcneill ks->ks_softc = &sc->sc_queues[q];
8778 1.15 jmcneill ks->ks_data = kvs;
8779 1.15 jmcneill ks->ks_datalen = nitems(mcx_queue_kstat_tpl) * sizeof(*kvs);
8780 1.15 jmcneill ks->ks_read = mcx_kstat_queue_read;
8781 1.15 jmcneill
8782 1.15 jmcneill sc->sc_queues[q].q_kstat = ks;
8783 1.15 jmcneill kstat_install(ks);
8784 1.15 jmcneill }
8785 1.15 jmcneill }
8786 1.15 jmcneill
8787 1.15 jmcneill static int
8788 1.15 jmcneill mcx_kstat_queue_read(struct kstat *ks)
8789 1.15 jmcneill {
8790 1.15 jmcneill struct mcx_queues *q = ks->ks_softc;
8791 1.15 jmcneill struct mcx_softc *sc = q->q_sc;
8792 1.15 jmcneill struct kstat_kv *kvs = ks->ks_data;
8793 1.15 jmcneill union {
8794 1.15 jmcneill struct mcx_rq_ctx rq;
8795 1.15 jmcneill struct mcx_sq_ctx sq;
8796 1.15 jmcneill struct mcx_cq_ctx cq;
8797 1.15 jmcneill struct mcx_eq_ctx eq;
8798 1.15 jmcneill } u;
8799 1.15 jmcneill const char *text;
8800 1.15 jmcneill int error = 0;
8801 1.15 jmcneill
8802 1.15 jmcneill KERNEL_LOCK();
8803 1.15 jmcneill
8804 1.15 jmcneill if (mcx_query_rq(sc, &q->q_rx, &u.rq) != 0) {
8805 1.15 jmcneill error = EIO;
8806 1.15 jmcneill goto out;
8807 1.15 jmcneill }
8808 1.15 jmcneill
8809 1.15 jmcneill kstat_kv_u64(kvs++) = q->q_rx.rx_prod;
8810 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.rq.rq_wq.wq_sw_counter);
8811 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.rq.rq_wq.wq_hw_counter);
8812 1.15 jmcneill switch ((bemtoh32(&u.rq.rq_flags) & MCX_RQ_CTX_STATE_MASK) >>
8813 1.15 jmcneill MCX_RQ_CTX_STATE_SHIFT) {
8814 1.15 jmcneill case MCX_RQ_CTX_STATE_RST:
8815 1.15 jmcneill text = "RST";
8816 1.15 jmcneill break;
8817 1.15 jmcneill case MCX_RQ_CTX_STATE_RDY:
8818 1.15 jmcneill text = "RDY";
8819 1.15 jmcneill break;
8820 1.15 jmcneill case MCX_RQ_CTX_STATE_ERR:
8821 1.15 jmcneill text = "ERR";
8822 1.15 jmcneill break;
8823 1.15 jmcneill default:
8824 1.15 jmcneill text = "unknown";
8825 1.15 jmcneill break;
8826 1.15 jmcneill }
8827 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8828 1.15 jmcneill kvs++;
8829 1.15 jmcneill
8830 1.15 jmcneill if (mcx_query_sq(sc, &q->q_tx, &u.sq) != 0) {
8831 1.15 jmcneill error = EIO;
8832 1.15 jmcneill goto out;
8833 1.15 jmcneill }
8834 1.15 jmcneill
8835 1.15 jmcneill kstat_kv_u64(kvs++) = q->q_tx.tx_prod;
8836 1.15 jmcneill kstat_kv_u64(kvs++) = q->q_tx.tx_cons;
8837 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.sq.sq_wq.wq_sw_counter);
8838 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.sq.sq_wq.wq_hw_counter);
8839 1.15 jmcneill switch ((bemtoh32(&u.sq.sq_flags) & MCX_SQ_CTX_STATE_MASK) >>
8840 1.15 jmcneill MCX_SQ_CTX_STATE_SHIFT) {
8841 1.15 jmcneill case MCX_SQ_CTX_STATE_RST:
8842 1.15 jmcneill text = "RST";
8843 1.15 jmcneill break;
8844 1.15 jmcneill case MCX_SQ_CTX_STATE_RDY:
8845 1.15 jmcneill text = "RDY";
8846 1.15 jmcneill break;
8847 1.15 jmcneill case MCX_SQ_CTX_STATE_ERR:
8848 1.15 jmcneill text = "ERR";
8849 1.15 jmcneill break;
8850 1.15 jmcneill default:
8851 1.15 jmcneill text = "unknown";
8852 1.15 jmcneill break;
8853 1.15 jmcneill }
8854 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8855 1.15 jmcneill kvs++;
8856 1.15 jmcneill
8857 1.15 jmcneill if (mcx_query_cq(sc, &q->q_cq, &u.cq) != 0) {
8858 1.15 jmcneill error = EIO;
8859 1.15 jmcneill goto out;
8860 1.15 jmcneill }
8861 1.15 jmcneill
8862 1.15 jmcneill kstat_kv_u64(kvs++) = q->q_cq.cq_cons;
8863 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.cq.cq_producer_counter);
8864 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.cq.cq_consumer_counter);
8865 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.cq.cq_last_notified);
8866 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.cq.cq_last_solicit);
8867 1.15 jmcneill
8868 1.15 jmcneill switch ((bemtoh32(&u.cq.cq_status) & MCX_CQ_CTX_STATUS_MASK) >>
8869 1.15 jmcneill MCX_CQ_CTX_STATUS_SHIFT) {
8870 1.15 jmcneill case MCX_CQ_CTX_STATUS_OK:
8871 1.15 jmcneill text = "OK";
8872 1.15 jmcneill break;
8873 1.15 jmcneill case MCX_CQ_CTX_STATUS_OVERFLOW:
8874 1.15 jmcneill text = "overflow";
8875 1.15 jmcneill break;
8876 1.15 jmcneill case MCX_CQ_CTX_STATUS_WRITE_FAIL:
8877 1.15 jmcneill text = "write fail";
8878 1.15 jmcneill break;
8879 1.15 jmcneill default:
8880 1.15 jmcneill text = "unknown";
8881 1.15 jmcneill break;
8882 1.15 jmcneill }
8883 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8884 1.15 jmcneill kvs++;
8885 1.15 jmcneill
8886 1.15 jmcneill switch ((bemtoh32(&u.cq.cq_status) & MCX_CQ_CTX_STATE_MASK) >>
8887 1.15 jmcneill MCX_CQ_CTX_STATE_SHIFT) {
8888 1.15 jmcneill case MCX_CQ_CTX_STATE_SOLICITED:
8889 1.15 jmcneill text = "solicited";
8890 1.15 jmcneill break;
8891 1.15 jmcneill case MCX_CQ_CTX_STATE_ARMED:
8892 1.15 jmcneill text = "armed";
8893 1.15 jmcneill break;
8894 1.15 jmcneill case MCX_CQ_CTX_STATE_FIRED:
8895 1.15 jmcneill text = "fired";
8896 1.15 jmcneill break;
8897 1.15 jmcneill default:
8898 1.15 jmcneill text = "unknown";
8899 1.15 jmcneill break;
8900 1.15 jmcneill }
8901 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8902 1.15 jmcneill kvs++;
8903 1.15 jmcneill
8904 1.15 jmcneill if (mcx_query_eq(sc, &q->q_eq, &u.eq) != 0) {
8905 1.15 jmcneill error = EIO;
8906 1.15 jmcneill goto out;
8907 1.15 jmcneill }
8908 1.15 jmcneill
8909 1.15 jmcneill kstat_kv_u64(kvs++) = q->q_eq.eq_cons;
8910 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.eq.eq_producer_counter);
8911 1.15 jmcneill kstat_kv_u64(kvs++) = bemtoh32(&u.eq.eq_consumer_counter);
8912 1.15 jmcneill
8913 1.15 jmcneill switch ((bemtoh32(&u.eq.eq_status) & MCX_EQ_CTX_STATUS_MASK) >>
8914 1.15 jmcneill MCX_EQ_CTX_STATUS_SHIFT) {
8915 1.15 jmcneill case MCX_EQ_CTX_STATUS_EQ_WRITE_FAILURE:
8916 1.15 jmcneill text = "write fail";
8917 1.15 jmcneill break;
8918 1.15 jmcneill case MCX_EQ_CTX_STATUS_OK:
8919 1.15 jmcneill text = "OK";
8920 1.15 jmcneill break;
8921 1.15 jmcneill default:
8922 1.15 jmcneill text = "unknown";
8923 1.15 jmcneill break;
8924 1.15 jmcneill }
8925 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8926 1.15 jmcneill kvs++;
8927 1.15 jmcneill
8928 1.15 jmcneill switch ((bemtoh32(&u.eq.eq_status) & MCX_EQ_CTX_STATE_MASK) >>
8929 1.15 jmcneill MCX_EQ_CTX_STATE_SHIFT) {
8930 1.15 jmcneill case MCX_EQ_CTX_STATE_ARMED:
8931 1.15 jmcneill text = "armed";
8932 1.15 jmcneill break;
8933 1.15 jmcneill case MCX_EQ_CTX_STATE_FIRED:
8934 1.15 jmcneill text = "fired";
8935 1.15 jmcneill break;
8936 1.15 jmcneill default:
8937 1.15 jmcneill text = "unknown";
8938 1.15 jmcneill break;
8939 1.15 jmcneill }
8940 1.15 jmcneill strlcpy(kstat_kv_istr(kvs), text, sizeof(kstat_kv_istr(kvs)));
8941 1.15 jmcneill kvs++;
8942 1.15 jmcneill
8943 1.15 jmcneill nanouptime(&ks->ks_updated);
8944 1.15 jmcneill out:
8945 1.15 jmcneill KERNEL_UNLOCK();
8946 1.15 jmcneill return (error);
8947 1.15 jmcneill }
8948 1.15 jmcneill
8949 1.15 jmcneill #endif /* NKSTAT > 0 */
8950 1.15 jmcneill
8951 1.15 jmcneill static unsigned int
8952 1.15 jmcneill mcx_timecounter_read(struct timecounter *tc)
8953 1.15 jmcneill {
8954 1.15 jmcneill struct mcx_softc *sc = tc->tc_priv;
8955 1.15 jmcneill
8956 1.15 jmcneill return (mcx_rd(sc, MCX_INTERNAL_TIMER_L));
8957 1.15 jmcneill }
8958 1.15 jmcneill
8959 1.15 jmcneill static void
8960 1.15 jmcneill mcx_timecounter_attach(struct mcx_softc *sc)
8961 1.15 jmcneill {
8962 1.15 jmcneill struct timecounter *tc = &sc->sc_timecounter;
8963 1.15 jmcneill
8964 1.15 jmcneill tc->tc_get_timecount = mcx_timecounter_read;
8965 1.15 jmcneill tc->tc_counter_mask = ~0U;
8966 1.15 jmcneill tc->tc_frequency = sc->sc_khz * 1000;
8967 1.15 jmcneill tc->tc_name = device_xname(sc->sc_dev);
8968 1.15 jmcneill tc->tc_quality = -100;
8969 1.15 jmcneill tc->tc_priv = sc;
8970 1.15 jmcneill
8971 1.15 jmcneill tc_init(tc);
8972 1.15 jmcneill }
8973