16f443ebcSRyan Zezeski /*
26f443ebcSRyan Zezeski * This file and its contents are supplied under the terms of the
36f443ebcSRyan Zezeski * Common Development and Distribution License ("CDDL"), version 1.0.
46f443ebcSRyan Zezeski * You may only use this file in accordance with the terms of version
56f443ebcSRyan Zezeski * 1.0 of the CDDL.
66f443ebcSRyan Zezeski *
76f443ebcSRyan Zezeski * A full copy of the text of the CDDL should have accompanied this
86f443ebcSRyan Zezeski * source. A copy of the CDDL is also available via the Internet at
96f443ebcSRyan Zezeski * http://www.illumos.org/license/CDDL.
106f443ebcSRyan Zezeski */
116f443ebcSRyan Zezeski
126f443ebcSRyan Zezeski /*
13*c46e4de3SAndy Fiddaman * Copyright 2024 Oxide Computer Company
146f443ebcSRyan Zezeski */
156f443ebcSRyan Zezeski
166f443ebcSRyan Zezeski #include "ena_hw.h"
176f443ebcSRyan Zezeski #include "ena.h"
186f443ebcSRyan Zezeski
196f443ebcSRyan Zezeski uint32_t
ena_hw_bar_read32(const ena_t * ena,const uint16_t offset)206f443ebcSRyan Zezeski ena_hw_bar_read32(const ena_t *ena, const uint16_t offset)
216f443ebcSRyan Zezeski {
226f443ebcSRyan Zezeski caddr_t addr = ena->ena_reg_base + offset;
236f443ebcSRyan Zezeski return (ena_hw_abs_read32(ena, (uint32_t *)addr));
246f443ebcSRyan Zezeski }
256f443ebcSRyan Zezeski
266f443ebcSRyan Zezeski uint32_t
ena_hw_abs_read32(const ena_t * ena,uint32_t * addr)276f443ebcSRyan Zezeski ena_hw_abs_read32(const ena_t *ena, uint32_t *addr)
286f443ebcSRyan Zezeski {
296f443ebcSRyan Zezeski VERIFY3U(addr, >=, ena->ena_reg_base);
306f443ebcSRyan Zezeski VERIFY3U(addr, <, ena->ena_reg_base + (ena->ena_reg_size - 4));
316f443ebcSRyan Zezeski
326f443ebcSRyan Zezeski return (ddi_get32(ena->ena_reg_hdl, addr));
336f443ebcSRyan Zezeski }
346f443ebcSRyan Zezeski
356f443ebcSRyan Zezeski void
ena_hw_bar_write32(const ena_t * ena,const uint16_t offset,const uint32_t val)366f443ebcSRyan Zezeski ena_hw_bar_write32(const ena_t *ena, const uint16_t offset, const uint32_t val)
376f443ebcSRyan Zezeski {
386f443ebcSRyan Zezeski caddr_t addr = ena->ena_reg_base + offset;
396f443ebcSRyan Zezeski ena_hw_abs_write32(ena, (uint32_t *)addr, val);
406f443ebcSRyan Zezeski }
416f443ebcSRyan Zezeski
426f443ebcSRyan Zezeski void
ena_hw_abs_write32(const ena_t * ena,uint32_t * addr,const uint32_t val)436f443ebcSRyan Zezeski ena_hw_abs_write32(const ena_t *ena, uint32_t *addr, const uint32_t val)
446f443ebcSRyan Zezeski {
456f443ebcSRyan Zezeski VERIFY3P(ena, !=, NULL);
466f443ebcSRyan Zezeski VERIFY3P(addr, !=, NULL);
476f443ebcSRyan Zezeski VERIFY3U(addr, >=, ena->ena_reg_base);
486f443ebcSRyan Zezeski VERIFY3U(addr, <, ena->ena_reg_base + (ena->ena_reg_size - 4));
496f443ebcSRyan Zezeski
506f443ebcSRyan Zezeski ddi_put32(ena->ena_reg_hdl, addr, val);
516f443ebcSRyan Zezeski }
526f443ebcSRyan Zezeski
536f443ebcSRyan Zezeski int
enahw_resp_status_to_errno(ena_t * ena,enahw_resp_status_t status)546f443ebcSRyan Zezeski enahw_resp_status_to_errno(ena_t *ena, enahw_resp_status_t status)
556f443ebcSRyan Zezeski {
566f443ebcSRyan Zezeski int ret = 0;
576f443ebcSRyan Zezeski
586f443ebcSRyan Zezeski switch (status) {
596f443ebcSRyan Zezeski case ENAHW_RESP_SUCCESS:
606f443ebcSRyan Zezeski break;
616f443ebcSRyan Zezeski
626f443ebcSRyan Zezeski case ENAHW_RESP_RESOURCE_ALLOCATION_FAILURE:
636f443ebcSRyan Zezeski ret = ENOMEM;
646f443ebcSRyan Zezeski break;
656f443ebcSRyan Zezeski
666f443ebcSRyan Zezeski case ENAHW_RESP_UNSUPPORTED_OPCODE:
676f443ebcSRyan Zezeski ret = ENOTSUP;
686f443ebcSRyan Zezeski break;
696f443ebcSRyan Zezeski
706f443ebcSRyan Zezeski case ENAHW_RESP_BAD_OPCODE:
716f443ebcSRyan Zezeski case ENAHW_RESP_MALFORMED_REQUEST:
726f443ebcSRyan Zezeski case ENAHW_RESP_ILLEGAL_PARAMETER:
736f443ebcSRyan Zezeski ret = EINVAL;
746f443ebcSRyan Zezeski break;
756f443ebcSRyan Zezeski
766f443ebcSRyan Zezeski case ENAHW_RESP_RESOURCE_BUSY:
776f443ebcSRyan Zezeski ret = EAGAIN;
786f443ebcSRyan Zezeski break;
796f443ebcSRyan Zezeski
806f443ebcSRyan Zezeski case ENAHW_RESP_UNKNOWN_ERROR:
816f443ebcSRyan Zezeski default:
826f443ebcSRyan Zezeski /*
83*c46e4de3SAndy Fiddaman * If the device presents us with an "unknown error"
846f443ebcSRyan Zezeski * code, or the status code is undefined, then we log
856f443ebcSRyan Zezeski * an error and convert it to EIO.
866f443ebcSRyan Zezeski */
876f443ebcSRyan Zezeski ena_err(ena, "unexpected status code: %d", status);
886f443ebcSRyan Zezeski ret = EIO;
896f443ebcSRyan Zezeski break;
906f443ebcSRyan Zezeski }
916f443ebcSRyan Zezeski
926f443ebcSRyan Zezeski return (ret);
936f443ebcSRyan Zezeski }
94*c46e4de3SAndy Fiddaman
95*c46e4de3SAndy Fiddaman const char *
enahw_reset_reason(enahw_reset_reason_t reason)96*c46e4de3SAndy Fiddaman enahw_reset_reason(enahw_reset_reason_t reason)
97*c46e4de3SAndy Fiddaman {
98*c46e4de3SAndy Fiddaman switch (reason) {
99*c46e4de3SAndy Fiddaman case ENAHW_RESET_NORMAL:
100*c46e4de3SAndy Fiddaman return ("normal");
101*c46e4de3SAndy Fiddaman case ENAHW_RESET_KEEP_ALIVE_TO:
102*c46e4de3SAndy Fiddaman return ("keep-alive timeout");
103*c46e4de3SAndy Fiddaman case ENAHW_RESET_ADMIN_TO:
104*c46e4de3SAndy Fiddaman return ("admin timeout");
105*c46e4de3SAndy Fiddaman case ENAHW_RESET_MISS_TX_CMPL:
106*c46e4de3SAndy Fiddaman return ("missed TX completion");
107*c46e4de3SAndy Fiddaman case ENAHW_RESET_INV_RX_REQ_ID:
108*c46e4de3SAndy Fiddaman return ("invalid RX request ID");
109*c46e4de3SAndy Fiddaman case ENAHW_RESET_INV_TX_REQ_ID:
110*c46e4de3SAndy Fiddaman return ("invalid TX request ID");
111*c46e4de3SAndy Fiddaman case ENAHW_RESET_TOO_MANY_RX_DESCS:
112*c46e4de3SAndy Fiddaman return ("too many RX descs");
113*c46e4de3SAndy Fiddaman case ENAHW_RESET_INIT_ERR:
114*c46e4de3SAndy Fiddaman return ("initialization error");
115*c46e4de3SAndy Fiddaman case ENAHW_RESET_DRIVER_INVALID_STATE:
116*c46e4de3SAndy Fiddaman return ("invalid driver state");
117*c46e4de3SAndy Fiddaman case ENAHW_RESET_OS_TRIGGER:
118*c46e4de3SAndy Fiddaman return ("OS trigger");
119*c46e4de3SAndy Fiddaman case ENAHW_RESET_OS_NETDEV_WD:
120*c46e4de3SAndy Fiddaman return ("netdev watchdog");
121*c46e4de3SAndy Fiddaman case ENAHW_RESET_SHUTDOWN:
122*c46e4de3SAndy Fiddaman return ("shutdown");
123*c46e4de3SAndy Fiddaman case ENAHW_RESET_USER_TRIGGER:
124*c46e4de3SAndy Fiddaman return ("user trigger");
125*c46e4de3SAndy Fiddaman case ENAHW_RESET_GENERIC:
126*c46e4de3SAndy Fiddaman return ("generic");
127*c46e4de3SAndy Fiddaman case ENAHW_RESET_MISS_INTERRUPT:
128*c46e4de3SAndy Fiddaman return ("missed interrupt");
129*c46e4de3SAndy Fiddaman case ENAHW_RESET_SUSPECTED_POLL_STARVATION:
130*c46e4de3SAndy Fiddaman return ("suspected poll starvation");
131*c46e4de3SAndy Fiddaman case ENAHW_RESET_RX_DESCRIPTOR_MALFORMED:
132*c46e4de3SAndy Fiddaman return ("malformed RX descriptor");
133*c46e4de3SAndy Fiddaman case ENAHW_RESET_TX_DESCRIPTOR_MALFORMED:
134*c46e4de3SAndy Fiddaman return ("malformed TX descriptor");
135*c46e4de3SAndy Fiddaman case ENAHW_RESET_MISSING_ADMIN_INTERRUPT:
136*c46e4de3SAndy Fiddaman return ("missing admin interrupt");
137*c46e4de3SAndy Fiddaman case ENAHW_RESET_DEVICE_REQUEST:
138*c46e4de3SAndy Fiddaman return ("device request");
139*c46e4de3SAndy Fiddaman default:
140*c46e4de3SAndy Fiddaman return ("unknown");
141*c46e4de3SAndy Fiddaman }
142*c46e4de3SAndy Fiddaman }
143*c46e4de3SAndy Fiddaman
144*c46e4de3SAndy Fiddaman #ifdef DEBUG
145*c46e4de3SAndy Fiddaman static const ena_reg_t reg_cache_template[ENAHW_NUM_REGS] = {
146*c46e4de3SAndy Fiddaman {
147*c46e4de3SAndy Fiddaman .er_name = "Version",
148*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_VERSION
149*c46e4de3SAndy Fiddaman },
150*c46e4de3SAndy Fiddaman {
151*c46e4de3SAndy Fiddaman .er_name = "Controller Version",
152*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_CONTROLLER_VERSION
153*c46e4de3SAndy Fiddaman },
154*c46e4de3SAndy Fiddaman {
155*c46e4de3SAndy Fiddaman .er_name = "Caps",
156*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_CAPS
157*c46e4de3SAndy Fiddaman },
158*c46e4de3SAndy Fiddaman {
159*c46e4de3SAndy Fiddaman .er_name = "Extended Caps",
160*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_CAPS_EXT
161*c46e4de3SAndy Fiddaman },
162*c46e4de3SAndy Fiddaman {
163*c46e4de3SAndy Fiddaman .er_name = "Admin SQ Base Low",
164*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ASQ_BASE_LO
165*c46e4de3SAndy Fiddaman },
166*c46e4de3SAndy Fiddaman {
167*c46e4de3SAndy Fiddaman .er_name = "Admin SQ Base High",
168*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ASQ_BASE_HI
169*c46e4de3SAndy Fiddaman },
170*c46e4de3SAndy Fiddaman {
171*c46e4de3SAndy Fiddaman .er_name = "Admin SQ Caps",
172*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ASQ_CAPS
173*c46e4de3SAndy Fiddaman },
174*c46e4de3SAndy Fiddaman {
175*c46e4de3SAndy Fiddaman .er_name = "Gap 0x1C",
176*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_GAP_1C
177*c46e4de3SAndy Fiddaman },
178*c46e4de3SAndy Fiddaman {
179*c46e4de3SAndy Fiddaman .er_name = "Admin CQ Base Low",
180*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ACQ_BASE_LO
181*c46e4de3SAndy Fiddaman },
182*c46e4de3SAndy Fiddaman {
183*c46e4de3SAndy Fiddaman .er_name = "Admin CQ Base High",
184*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ACQ_BASE_HI
185*c46e4de3SAndy Fiddaman },
186*c46e4de3SAndy Fiddaman {
187*c46e4de3SAndy Fiddaman .er_name = "Admin CQ Caps",
188*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ACQ_CAPS
189*c46e4de3SAndy Fiddaman },
190*c46e4de3SAndy Fiddaman {
191*c46e4de3SAndy Fiddaman .er_name = "Admin SQ Doorbell",
192*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ASQ_DB
193*c46e4de3SAndy Fiddaman },
194*c46e4de3SAndy Fiddaman {
195*c46e4de3SAndy Fiddaman .er_name = "Admin CQ Tail",
196*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_ACQ_TAIL
197*c46e4de3SAndy Fiddaman },
198*c46e4de3SAndy Fiddaman {
199*c46e4de3SAndy Fiddaman .er_name = "Admin Event Notification Queue Caps",
200*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_AENQ_CAPS
201*c46e4de3SAndy Fiddaman },
202*c46e4de3SAndy Fiddaman {
203*c46e4de3SAndy Fiddaman .er_name = "Admin Event Notification Queue Base Low",
204*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_AENQ_BASE_LO
205*c46e4de3SAndy Fiddaman },
206*c46e4de3SAndy Fiddaman {
207*c46e4de3SAndy Fiddaman .er_name = "Admin Event Notification Queue Base High",
208*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_AENQ_BASE_HI
209*c46e4de3SAndy Fiddaman },
210*c46e4de3SAndy Fiddaman {
211*c46e4de3SAndy Fiddaman .er_name = "Admin Event Notification Queue Head Doorbell",
212*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_AENQ_HEAD_DB
213*c46e4de3SAndy Fiddaman },
214*c46e4de3SAndy Fiddaman {
215*c46e4de3SAndy Fiddaman .er_name = "Admin Event Notification Queue Tail",
216*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_AENQ_TAIL
217*c46e4de3SAndy Fiddaman },
218*c46e4de3SAndy Fiddaman {
219*c46e4de3SAndy Fiddaman .er_name = "Gap 0x48",
220*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_GAP_48
221*c46e4de3SAndy Fiddaman },
222*c46e4de3SAndy Fiddaman {
223*c46e4de3SAndy Fiddaman .er_name = "Interrupt Mask (disable interrupts)",
224*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_INTERRUPT_MASK
225*c46e4de3SAndy Fiddaman },
226*c46e4de3SAndy Fiddaman {
227*c46e4de3SAndy Fiddaman .er_name = "Gap 0x50",
228*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_GAP_50
229*c46e4de3SAndy Fiddaman },
230*c46e4de3SAndy Fiddaman {
231*c46e4de3SAndy Fiddaman .er_name = "Device Control",
232*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_DEV_CTL
233*c46e4de3SAndy Fiddaman },
234*c46e4de3SAndy Fiddaman {
235*c46e4de3SAndy Fiddaman .er_name = "Device Status",
236*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_DEV_STS
237*c46e4de3SAndy Fiddaman },
238*c46e4de3SAndy Fiddaman {
239*c46e4de3SAndy Fiddaman .er_name = "MMIO Register Read",
240*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_MMIO_REG_READ
241*c46e4de3SAndy Fiddaman },
242*c46e4de3SAndy Fiddaman {
243*c46e4de3SAndy Fiddaman .er_name = "MMIO Response Address Low",
244*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_MMIO_RESP_LO
245*c46e4de3SAndy Fiddaman },
246*c46e4de3SAndy Fiddaman {
247*c46e4de3SAndy Fiddaman .er_name = "MMIO Response Address High",
248*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_MMIO_RESP_HI
249*c46e4de3SAndy Fiddaman },
250*c46e4de3SAndy Fiddaman {
251*c46e4de3SAndy Fiddaman .er_name = "RSS Indirection Entry Update",
252*c46e4de3SAndy Fiddaman .er_offset = ENAHW_REG_RSS_IND_ENTRY_UPDATE
253*c46e4de3SAndy Fiddaman },
254*c46e4de3SAndy Fiddaman };
255*c46e4de3SAndy Fiddaman
256*c46e4de3SAndy Fiddaman void
ena_update_regcache(ena_t * ena)257*c46e4de3SAndy Fiddaman ena_update_regcache(ena_t *ena)
258*c46e4de3SAndy Fiddaman {
259*c46e4de3SAndy Fiddaman for (uint_t i = 0; i < ENAHW_NUM_REGS; i++) {
260*c46e4de3SAndy Fiddaman ena_reg_t *r = &ena->ena_reg[i];
261*c46e4de3SAndy Fiddaman
262*c46e4de3SAndy Fiddaman r->er_value = ena_hw_bar_read32(ena, r->er_offset);
263*c46e4de3SAndy Fiddaman }
264*c46e4de3SAndy Fiddaman }
265*c46e4de3SAndy Fiddaman
266*c46e4de3SAndy Fiddaman void
ena_init_regcache(ena_t * ena)267*c46e4de3SAndy Fiddaman ena_init_regcache(ena_t *ena)
268*c46e4de3SAndy Fiddaman {
269*c46e4de3SAndy Fiddaman bcopy(reg_cache_template, ena->ena_reg, sizeof (ena->ena_reg));
270*c46e4de3SAndy Fiddaman ena_update_regcache(ena);
271*c46e4de3SAndy Fiddaman }
272*c46e4de3SAndy Fiddaman #endif /* DEBUG */
273