Deleted Added
full compact
siena_nic.c (258676) siena_nic.c (278839)
1/*-
2 * Copyright 2009 Solarflare Communications Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
1/*-
2 * Copyright 2009 Solarflare Communications Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 258676 2013-11-27 08:39:48Z pluknet $");
27__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 278839 2015-02-16 06:12:04Z arybchik $");
28
29#include "efsys.h"
30#include "efx.h"
31#include "efx_impl.h"
32
33#if EFSYS_OPT_SIENA
34
35static __checkReturn int
36siena_nic_get_partn_mask(
37 __in efx_nic_t *enp,
38 __out unsigned int *maskp)
39{
40 efx_mcdi_req_t req;
41 uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
42 int rc;
43
44 req.emr_cmd = MC_CMD_NVRAM_TYPES;
45 EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
46 req.emr_in_buf = NULL;
47 req.emr_in_length = 0;
48 req.emr_out_buf = outbuf;
49 req.emr_out_length = sizeof (outbuf);
50
51 efx_mcdi_execute(enp, &req);
52
53 if (req.emr_rc != 0) {
54 rc = req.emr_rc;
55 goto fail1;
56 }
57
58 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
59 rc = EMSGSIZE;
60 goto fail2;
61 }
62
63 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
64
65 return (0);
66
67fail2:
68 EFSYS_PROBE(fail2);
69fail1:
70 EFSYS_PROBE1(fail1, int, rc);
71
72 return (rc);
73}
74
75static __checkReturn int
76siena_nic_exit_assertion_handler(
77 __in efx_nic_t *enp)
78{
79 efx_mcdi_req_t req;
80 uint8_t payload[MC_CMD_REBOOT_IN_LEN];
81 int rc;
82
83 req.emr_cmd = MC_CMD_REBOOT;
84 req.emr_in_buf = payload;
85 req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
86 EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
87 req.emr_out_buf = NULL;
88 req.emr_out_length = 0;
89
90 MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
91 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
92
93 efx_mcdi_execute(enp, &req);
94
95 if (req.emr_rc != 0 && req.emr_rc != EIO) {
96 rc = req.emr_rc;
97 goto fail1;
98 }
99
100 return (0);
101
102fail1:
103 EFSYS_PROBE1(fail1, int, rc);
104
105 return (rc);
106}
107
108static __checkReturn int
109siena_nic_read_assertion(
110 __in efx_nic_t *enp)
111{
112 efx_mcdi_req_t req;
113 uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
114 MC_CMD_GET_ASSERTS_OUT_LEN)];
115 const char *reason;
116 unsigned int flags;
117 unsigned int index;
118 unsigned int ofst;
119 int retry;
120 int rc;
121
122 /*
123 * Before we attempt to chat to the MC, we should verify that the MC
124 * isn't in it's assertion handler, either due to a previous reboot,
125 * or because we're reinitializing due to an eec_exception().
126 *
127 * Use GET_ASSERTS to read any assertion state that may be present.
128 * Retry this command twice. Once because a boot-time assertion failure
129 * might cause the 1st MCDI request to fail. And once again because
130 * we might race with siena_nic_exit_assertion_handler() running on the
131 * other port.
132 */
133 retry = 2;
134 do {
135 req.emr_cmd = MC_CMD_GET_ASSERTS;
136 req.emr_in_buf = payload;
137 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
138 req.emr_out_buf = payload;
139 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
140
141 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
142 efx_mcdi_execute(enp, &req);
143
144 } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
145
146 if (req.emr_rc != 0) {
147 rc = req.emr_rc;
148 goto fail1;
149 }
150
151 if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
152 rc = EMSGSIZE;
153 goto fail2;
154 }
155
156 /* Print out any assertion state recorded */
157 flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
158 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
159 return (0);
160
161 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
162 ? "system-level assertion"
163 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
164 ? "thread-level assertion"
165 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
166 ? "watchdog reset"
167 : "unknown assertion";
168 EFSYS_PROBE3(mcpu_assertion,
169 const char *, reason, unsigned int,
170 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
171 unsigned int,
172 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
173
174 /* Print out the registers */
175 ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
176 for (index = 1; index < 32; index++) {
177 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
178 EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
179 EFX_DWORD_0));
180 ofst += sizeof (efx_dword_t);
181 }
182 EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
183
184 return (0);
185
186fail2:
187 EFSYS_PROBE(fail2);
188fail1:
189 EFSYS_PROBE1(fail1, int, rc);
190
191 return (rc);
192}
193
194static __checkReturn int
195siena_nic_attach(
196 __in efx_nic_t *enp,
197 __in boolean_t attach)
198{
199 efx_mcdi_req_t req;
200 uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
201 int rc;
202
203 req.emr_cmd = MC_CMD_DRV_ATTACH;
204 req.emr_in_buf = payload;
205 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
206 req.emr_out_buf = NULL;
207 req.emr_out_length = 0;
208
209 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
210 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
211
212 efx_mcdi_execute(enp, &req);
213
214 if (req.emr_rc != 0) {
215 rc = req.emr_rc;
216 goto fail1;
217 }
218
219 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
220 rc = EMSGSIZE;
221 goto fail2;
222 }
223
224 return (0);
225
226fail2:
227 EFSYS_PROBE(fail2);
228fail1:
229 EFSYS_PROBE1(fail1, int, rc);
230
231 return (rc);
232}
233
234#if EFSYS_OPT_PCIE_TUNE
235
236 __checkReturn int
237siena_nic_pcie_extended_sync(
238 __in efx_nic_t *enp)
239{
240 uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
241 efx_mcdi_req_t req;
242 int rc;
243
244 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
245
246 req.emr_cmd = MC_CMD_WORKAROUND;
247 req.emr_in_buf = inbuf;
248 req.emr_in_length = sizeof (inbuf);
249 EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
250 req.emr_out_buf = NULL;
251 req.emr_out_length = 0;
252
253 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
254 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
255
256 efx_mcdi_execute(enp, &req);
257
258 if (req.emr_rc != 0) {
259 rc = req.emr_rc;
260 goto fail1;
261 }
262
263 return (0);
264
265fail1:
266 EFSYS_PROBE1(fail1, int, rc);
267
268 return (rc);
269}
270
271#endif /* EFSYS_OPT_PCIE_TUNE */
272
273static __checkReturn int
274siena_board_cfg(
275 __in efx_nic_t *enp)
276{
277 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
278 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
279 uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LEN,
280 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281 efx_mcdi_req_t req;
282 uint8_t *src;
283 int rc;
284
285 /* Board configuration */
286 req.emr_cmd = MC_CMD_GET_BOARD_CFG;
287 EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
288 req.emr_in_buf = NULL;
289 req.emr_in_length = 0;
290 req.emr_out_buf = outbuf;
291 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN;
292
293 efx_mcdi_execute(enp, &req);
294
295 if (req.emr_rc != 0) {
296 rc = req.emr_rc;
297 goto fail1;
298 }
299
300 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
301 rc = EMSGSIZE;
302 goto fail2;
303 }
304
305 if (emip->emi_port == 1)
306 src = MCDI_OUT2(req, uint8_t,
307 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
308 else
309 src = MCDI_OUT2(req, uint8_t,
310 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
311 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src);
312
313 encp->enc_board_type = MCDI_OUT_DWORD(req,
314 GET_BOARD_CFG_OUT_BOARD_TYPE);
315
316 /* Resource limits */
317 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
318 EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
319 req.emr_in_buf = NULL;
320 req.emr_in_length = 0;
321 req.emr_out_buf = outbuf;
322 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
323
324 efx_mcdi_execute(enp, &req);
325
326 if (req.emr_rc == 0) {
28
29#include "efsys.h"
30#include "efx.h"
31#include "efx_impl.h"
32
33#if EFSYS_OPT_SIENA
34
35static __checkReturn int
36siena_nic_get_partn_mask(
37 __in efx_nic_t *enp,
38 __out unsigned int *maskp)
39{
40 efx_mcdi_req_t req;
41 uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
42 int rc;
43
44 req.emr_cmd = MC_CMD_NVRAM_TYPES;
45 EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
46 req.emr_in_buf = NULL;
47 req.emr_in_length = 0;
48 req.emr_out_buf = outbuf;
49 req.emr_out_length = sizeof (outbuf);
50
51 efx_mcdi_execute(enp, &req);
52
53 if (req.emr_rc != 0) {
54 rc = req.emr_rc;
55 goto fail1;
56 }
57
58 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
59 rc = EMSGSIZE;
60 goto fail2;
61 }
62
63 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
64
65 return (0);
66
67fail2:
68 EFSYS_PROBE(fail2);
69fail1:
70 EFSYS_PROBE1(fail1, int, rc);
71
72 return (rc);
73}
74
75static __checkReturn int
76siena_nic_exit_assertion_handler(
77 __in efx_nic_t *enp)
78{
79 efx_mcdi_req_t req;
80 uint8_t payload[MC_CMD_REBOOT_IN_LEN];
81 int rc;
82
83 req.emr_cmd = MC_CMD_REBOOT;
84 req.emr_in_buf = payload;
85 req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
86 EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
87 req.emr_out_buf = NULL;
88 req.emr_out_length = 0;
89
90 MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
91 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
92
93 efx_mcdi_execute(enp, &req);
94
95 if (req.emr_rc != 0 && req.emr_rc != EIO) {
96 rc = req.emr_rc;
97 goto fail1;
98 }
99
100 return (0);
101
102fail1:
103 EFSYS_PROBE1(fail1, int, rc);
104
105 return (rc);
106}
107
108static __checkReturn int
109siena_nic_read_assertion(
110 __in efx_nic_t *enp)
111{
112 efx_mcdi_req_t req;
113 uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
114 MC_CMD_GET_ASSERTS_OUT_LEN)];
115 const char *reason;
116 unsigned int flags;
117 unsigned int index;
118 unsigned int ofst;
119 int retry;
120 int rc;
121
122 /*
123 * Before we attempt to chat to the MC, we should verify that the MC
124 * isn't in it's assertion handler, either due to a previous reboot,
125 * or because we're reinitializing due to an eec_exception().
126 *
127 * Use GET_ASSERTS to read any assertion state that may be present.
128 * Retry this command twice. Once because a boot-time assertion failure
129 * might cause the 1st MCDI request to fail. And once again because
130 * we might race with siena_nic_exit_assertion_handler() running on the
131 * other port.
132 */
133 retry = 2;
134 do {
135 req.emr_cmd = MC_CMD_GET_ASSERTS;
136 req.emr_in_buf = payload;
137 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
138 req.emr_out_buf = payload;
139 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
140
141 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
142 efx_mcdi_execute(enp, &req);
143
144 } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
145
146 if (req.emr_rc != 0) {
147 rc = req.emr_rc;
148 goto fail1;
149 }
150
151 if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
152 rc = EMSGSIZE;
153 goto fail2;
154 }
155
156 /* Print out any assertion state recorded */
157 flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
158 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
159 return (0);
160
161 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
162 ? "system-level assertion"
163 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
164 ? "thread-level assertion"
165 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
166 ? "watchdog reset"
167 : "unknown assertion";
168 EFSYS_PROBE3(mcpu_assertion,
169 const char *, reason, unsigned int,
170 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
171 unsigned int,
172 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
173
174 /* Print out the registers */
175 ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
176 for (index = 1; index < 32; index++) {
177 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
178 EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
179 EFX_DWORD_0));
180 ofst += sizeof (efx_dword_t);
181 }
182 EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
183
184 return (0);
185
186fail2:
187 EFSYS_PROBE(fail2);
188fail1:
189 EFSYS_PROBE1(fail1, int, rc);
190
191 return (rc);
192}
193
194static __checkReturn int
195siena_nic_attach(
196 __in efx_nic_t *enp,
197 __in boolean_t attach)
198{
199 efx_mcdi_req_t req;
200 uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
201 int rc;
202
203 req.emr_cmd = MC_CMD_DRV_ATTACH;
204 req.emr_in_buf = payload;
205 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
206 req.emr_out_buf = NULL;
207 req.emr_out_length = 0;
208
209 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
210 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
211
212 efx_mcdi_execute(enp, &req);
213
214 if (req.emr_rc != 0) {
215 rc = req.emr_rc;
216 goto fail1;
217 }
218
219 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
220 rc = EMSGSIZE;
221 goto fail2;
222 }
223
224 return (0);
225
226fail2:
227 EFSYS_PROBE(fail2);
228fail1:
229 EFSYS_PROBE1(fail1, int, rc);
230
231 return (rc);
232}
233
234#if EFSYS_OPT_PCIE_TUNE
235
236 __checkReturn int
237siena_nic_pcie_extended_sync(
238 __in efx_nic_t *enp)
239{
240 uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
241 efx_mcdi_req_t req;
242 int rc;
243
244 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
245
246 req.emr_cmd = MC_CMD_WORKAROUND;
247 req.emr_in_buf = inbuf;
248 req.emr_in_length = sizeof (inbuf);
249 EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
250 req.emr_out_buf = NULL;
251 req.emr_out_length = 0;
252
253 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
254 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
255
256 efx_mcdi_execute(enp, &req);
257
258 if (req.emr_rc != 0) {
259 rc = req.emr_rc;
260 goto fail1;
261 }
262
263 return (0);
264
265fail1:
266 EFSYS_PROBE1(fail1, int, rc);
267
268 return (rc);
269}
270
271#endif /* EFSYS_OPT_PCIE_TUNE */
272
273static __checkReturn int
274siena_board_cfg(
275 __in efx_nic_t *enp)
276{
277 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
278 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
279 uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LEN,
280 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281 efx_mcdi_req_t req;
282 uint8_t *src;
283 int rc;
284
285 /* Board configuration */
286 req.emr_cmd = MC_CMD_GET_BOARD_CFG;
287 EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
288 req.emr_in_buf = NULL;
289 req.emr_in_length = 0;
290 req.emr_out_buf = outbuf;
291 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN;
292
293 efx_mcdi_execute(enp, &req);
294
295 if (req.emr_rc != 0) {
296 rc = req.emr_rc;
297 goto fail1;
298 }
299
300 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
301 rc = EMSGSIZE;
302 goto fail2;
303 }
304
305 if (emip->emi_port == 1)
306 src = MCDI_OUT2(req, uint8_t,
307 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
308 else
309 src = MCDI_OUT2(req, uint8_t,
310 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
311 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src);
312
313 encp->enc_board_type = MCDI_OUT_DWORD(req,
314 GET_BOARD_CFG_OUT_BOARD_TYPE);
315
316 /* Resource limits */
317 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
318 EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
319 req.emr_in_buf = NULL;
320 req.emr_in_length = 0;
321 req.emr_out_buf = outbuf;
322 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
323
324 efx_mcdi_execute(enp, &req);
325
326 if (req.emr_rc == 0) {
327 if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
327 if (req.emr_out_length_used <
328 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
328 rc = EMSGSIZE;
329 goto fail3;
330 }
331
332 encp->enc_evq_limit = MCDI_OUT_DWORD(req,
333 GET_RESOURCE_LIMITS_OUT_EVQ);
334 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
335 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
336 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
337 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
338 } else if (req.emr_rc == ENOTSUP) {
339 encp->enc_evq_limit = 1024;
340 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
341 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
342 } else {
343 rc = req.emr_rc;
344 goto fail4;
345 }
346
347 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
348 (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64);
349
350 return (0);
351
352fail4:
353 EFSYS_PROBE(fail4);
354fail3:
355 EFSYS_PROBE(fail3);
356fail2:
357 EFSYS_PROBE(fail2);
358fail1:
359 EFSYS_PROBE1(fail1, int, rc);
360
361 return (rc);
362}
363
364static __checkReturn int
365siena_phy_cfg(
366 __in efx_nic_t *enp)
367{
368 efx_port_t *epp = &(enp->en_port);
369 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
370 efx_mcdi_req_t req;
371 uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
372 int rc;
373
374 req.emr_cmd = MC_CMD_GET_PHY_CFG;
375 EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
376 req.emr_in_buf = NULL;
377 req.emr_in_length = 0;
378 req.emr_out_buf = outbuf;
379 req.emr_out_length = sizeof (outbuf);
380
381 efx_mcdi_execute(enp, &req);
382
383 if (req.emr_rc != 0) {
384 rc = req.emr_rc;
385 goto fail1;
386 }
387
388 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
389 rc = EMSGSIZE;
390 goto fail2;
391 }
392
393 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
394#if EFSYS_OPT_NAMES
395 (void) strncpy(encp->enc_phy_name,
396 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
397 MIN(sizeof (encp->enc_phy_name) - 1,
398 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
399#endif /* EFSYS_OPT_NAMES */
400 (void) memset(encp->enc_phy_revision, 0,
401 sizeof (encp->enc_phy_revision));
402 memcpy(encp->enc_phy_revision,
403 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
404 MIN(sizeof (encp->enc_phy_revision) - 1,
405 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
406#if EFSYS_OPT_PHY_LED_CONTROL
407 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
408 (1 << EFX_PHY_LED_OFF) |
409 (1 << EFX_PHY_LED_ON));
410#endif /* EFSYS_OPT_PHY_LED_CONTROL */
411
412#if EFSYS_OPT_PHY_PROPS
413 encp->enc_phy_nprops = 0;
414#endif /* EFSYS_OPT_PHY_PROPS */
415
416 /* Get the media type of the fixed port, if recognised. */
417 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
418 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
419 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
420 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
421 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
422 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
423 epp->ep_fixed_port_type =
424 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
425 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
426 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
427
428 epp->ep_phy_cap_mask =
429 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
430#if EFSYS_OPT_PHY_FLAGS
431 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
432#endif /* EFSYS_OPT_PHY_FLAGS */
433
434 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
435
436 /* Populate internal state */
437 encp->enc_siena_channel =
438 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
439
440#if EFSYS_OPT_PHY_STATS
441 encp->enc_siena_phy_stat_mask =
442 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
443
444 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
445 siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
446 NULL, &encp->enc_phy_stat_mask, NULL);
447#endif /* EFSYS_OPT_PHY_STATS */
448
449#if EFSYS_OPT_PHY_BIST
450 encp->enc_bist_mask = 0;
451 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
452 GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
453 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
454 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
455 GET_PHY_CFG_OUT_BIST_CABLE_LONG))
456 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
457 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
458 GET_PHY_CFG_OUT_BIST))
459 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
460#endif /* EFSYS_OPT_BIST */
461
462 return (0);
463
464fail2:
465 EFSYS_PROBE(fail2);
466fail1:
467 EFSYS_PROBE1(fail1, int, rc);
468
469 return (rc);
470}
471
472#if EFSYS_OPT_LOOPBACK
473
474static __checkReturn int
475siena_loopback_cfg(
476 __in efx_nic_t *enp)
477{
478 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
479 efx_mcdi_req_t req;
480 uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
481 int rc;
482
483 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
484 EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
485 req.emr_in_buf = NULL;
486 req.emr_in_length = 0;
487 req.emr_out_buf = outbuf;
488 req.emr_out_length = sizeof (outbuf);
489
490 efx_mcdi_execute(enp, &req);
491
492 if (req.emr_rc != 0) {
493 rc = req.emr_rc;
494 goto fail1;
495 }
496
497 if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
498 rc = EMSGSIZE;
499 goto fail2;
500 }
501
502 /*
503 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
504 * in siena_phy.c:siena_phy_get_link()
505 */
506 encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
507 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
508 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
509 encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
510 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
511 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
512 encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
513 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
514 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
515 encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
516 (1 << EFX_LOOPBACK_OFF) |
517 encp->enc_loopback_types[EFX_LINK_100FDX] |
518 encp->enc_loopback_types[EFX_LINK_1000FDX] |
519 encp->enc_loopback_types[EFX_LINK_10000FDX];
520
521 return (0);
522
523fail2:
524 EFSYS_PROBE(fail2);
525fail1:
526 EFSYS_PROBE1(fail1, int, rc);
527
528 return (rc);
529}
530
531#endif /* EFSYS_OPT_LOOPBACK */
532
533#if EFSYS_OPT_MON_STATS
534
535static __checkReturn int
536siena_monitor_cfg(
537 __in efx_nic_t *enp)
538{
539 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
540 efx_mcdi_req_t req;
541 uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
542 int rc;
543
544 req.emr_cmd = MC_CMD_SENSOR_INFO;
545 EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
546 req.emr_in_buf = NULL;
547 req.emr_in_length = 0;
548 req.emr_out_buf = outbuf;
549 req.emr_out_length = sizeof (outbuf);
550
551 efx_mcdi_execute(enp, &req);
552
553 if (req.emr_rc != 0) {
554 rc = req.emr_rc;
555 goto fail1;
556 }
557
558 if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
559 rc = EMSGSIZE;
560 goto fail2;
561 }
562
563 encp->enc_siena_mon_stat_mask =
564 MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
565 encp->enc_mon_type = EFX_MON_SFC90X0;
566
567 siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
568 NULL, &(encp->enc_mon_stat_mask), NULL);
569
570 return (0);
571
572fail2:
573 EFSYS_PROBE(fail2);
574fail1:
575 EFSYS_PROBE1(fail1, int, rc);
576
577 return (rc);
578}
579
580#endif /* EFSYS_OPT_MON_STATS */
581
582 __checkReturn int
583siena_nic_probe(
584 __in efx_nic_t *enp)
585{
586 efx_port_t *epp = &(enp->en_port);
587 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
588 siena_link_state_t sls;
589 unsigned int mask;
590 int rc;
591
592 mask = 0; /* XXX: pacify gcc */
593 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
594
595 /* Read clear any assertion state */
596 if ((rc = siena_nic_read_assertion(enp)) != 0)
597 goto fail1;
598
599 /* Exit the assertion handler */
600 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
601 goto fail2;
602
603 /* Wrestle control from the BMC */
604 if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
605 goto fail3;
606
607 if ((rc = siena_board_cfg(enp)) != 0)
608 goto fail4;
609
610 encp->enc_evq_moderation_max =
611 EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH;
612
613 if ((rc = siena_phy_cfg(enp)) != 0)
614 goto fail5;
615
616 /* Obtain the default PHY advertised capabilities */
617 if ((rc = siena_nic_reset(enp)) != 0)
618 goto fail6;
619 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
620 goto fail7;
621 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
622 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
623
624#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
625 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
626 goto fail8;
627 enp->en_u.siena.enu_partn_mask = mask;
628#endif
629
630#if EFSYS_OPT_MAC_STATS
631 /* Wipe the MAC statistics */
632 if ((rc = siena_mac_stats_clear(enp)) != 0)
633 goto fail9;
634#endif
635
636#if EFSYS_OPT_LOOPBACK
637 if ((rc = siena_loopback_cfg(enp)) != 0)
638 goto fail10;
639#endif
640
641#if EFSYS_OPT_MON_STATS
642 if ((rc = siena_monitor_cfg(enp)) != 0)
643 goto fail11;
644#endif
645
646 encp->enc_features = enp->en_features;
647
648 return (0);
649
650#if EFSYS_OPT_MON_STATS
651fail11:
652 EFSYS_PROBE(fail11);
653#endif
654#if EFSYS_OPT_LOOPBACK
655fail10:
656 EFSYS_PROBE(fail10);
657#endif
658#if EFSYS_OPT_MAC_STATS
659fail9:
660 EFSYS_PROBE(fail9);
661#endif
662#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
663fail8:
664 EFSYS_PROBE(fail8);
665#endif
666fail7:
667 EFSYS_PROBE(fail7);
668fail6:
669 EFSYS_PROBE(fail6);
670fail5:
671 EFSYS_PROBE(fail5);
672fail4:
673 EFSYS_PROBE(fail4);
674fail3:
675 EFSYS_PROBE(fail3);
676fail2:
677 EFSYS_PROBE(fail2);
678fail1:
679 EFSYS_PROBE1(fail1, int, rc);
680
681 return (rc);
682}
683
684 __checkReturn int
685siena_nic_reset(
686 __in efx_nic_t *enp)
687{
688 efx_mcdi_req_t req;
689 int rc;
690
691 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
692
693 /* siena_nic_reset() is called to recover from BADASSERT failures. */
694 if ((rc = siena_nic_read_assertion(enp)) != 0)
695 goto fail1;
696 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
697 goto fail2;
698
699 req.emr_cmd = MC_CMD_PORT_RESET;
700 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
701 req.emr_in_buf = NULL;
702 req.emr_in_length = 0;
703 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
704 req.emr_out_buf = NULL;
705 req.emr_out_length = 0;
706
707 efx_mcdi_execute(enp, &req);
708
709 if (req.emr_rc != 0) {
710 rc = req.emr_rc;
711 goto fail3;
712 }
713
714 return (0);
715
716fail3:
717 EFSYS_PROBE(fail3);
718fail2:
719 EFSYS_PROBE(fail2);
720fail1:
721 EFSYS_PROBE1(fail1, int, rc);
722
723 return (0);
724}
725
726static __checkReturn int
727siena_nic_logging(
728 __in efx_nic_t *enp)
729{
730 efx_mcdi_req_t req;
731 uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
732 int rc;
733
734 req.emr_cmd = MC_CMD_LOG_CTRL;
735 req.emr_in_buf = payload;
736 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
737 EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
738 req.emr_out_buf = NULL;
739 req.emr_out_length = 0;
740
741 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
742 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
743 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
744
745 efx_mcdi_execute(enp, &req);
746
747 if (req.emr_rc != 0) {
748 rc = req.emr_rc;
749 goto fail1;
750 }
751
752 return (0);
753
754fail1:
755 EFSYS_PROBE1(fail1, int, rc);
756
757 return (rc);
758}
759
760static void
761siena_nic_rx_cfg(
762 __in efx_nic_t *enp)
763{
764 efx_oword_t oword;
765
766 /*
767 * RX_INGR_EN is always enabled on Siena, because we rely on
768 * the RX parser to be resiliant to missing SOP/EOP.
769 */
770 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
771 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
772 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
773
774 /* Disable parsing of additional 802.1Q in Q packets */
775 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
776 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
777 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
778}
779
780static void
781siena_nic_usrev_dis(
782 __in efx_nic_t *enp)
783{
784 efx_oword_t oword;
785
786 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
787 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
788}
789
790 __checkReturn int
791siena_nic_init(
792 __in efx_nic_t *enp)
793{
794 int rc;
795
796 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
797
798 if ((rc = siena_nic_logging(enp)) != 0)
799 goto fail1;
800
801 siena_sram_init(enp);
802
803 /* Configure Siena's RX block */
804 siena_nic_rx_cfg(enp);
805
806 /* Disable USR_EVents for now */
807 siena_nic_usrev_dis(enp);
808
809 /* bug17057: Ensure set_link is called */
810 if ((rc = siena_phy_reconfigure(enp)) != 0)
811 goto fail2;
812
813 return (0);
814
815fail2:
816 EFSYS_PROBE(fail2);
817fail1:
818 EFSYS_PROBE1(fail1, int, rc);
819
820 return (rc);
821}
822
823 void
824siena_nic_fini(
825 __in efx_nic_t *enp)
826{
827 _NOTE(ARGUNUSED(enp))
828}
829
830 void
831siena_nic_unprobe(
832 __in efx_nic_t *enp)
833{
834 (void) siena_nic_attach(enp, B_FALSE);
835}
836
837#if EFSYS_OPT_DIAG
838
839static efx_register_set_t __cs __siena_registers[] = {
840 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
841 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
842 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
843 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
844 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
845 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
846 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
847 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
848 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
849 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
850 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
851 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
852 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
853};
854
855static const uint32_t __cs __siena_register_masks[] = {
856 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
857 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
858 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
859 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
860 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
861 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
862 0x00000003, 0x00000000, 0x00000000, 0x00000000,
863 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
864 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
865 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
866 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
867 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
868 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
869};
870
871static efx_register_set_t __cs __siena_tables[] = {
872 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
873 FR_AZ_RX_FILTER_TBL0_ROWS },
874 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
875 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
876 { FR_AZ_RX_DESC_PTR_TBL_OFST,
877 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
878 { FR_AZ_TX_DESC_PTR_TBL_OFST,
879 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
880 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
881 { FR_CZ_TX_FILTER_TBL0_OFST,
882 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
883 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
884 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
885};
886
887static const uint32_t __cs __siena_table_masks[] = {
888 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
889 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
890 0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000,
891 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
892 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
893 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
894 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
895};
896
897 __checkReturn int
898siena_nic_register_test(
899 __in efx_nic_t *enp)
900{
901 efx_register_set_t *rsp;
902 const uint32_t *dwordp;
903 unsigned int nitems;
904 unsigned int count;
905 int rc;
906
907 /* Fill out the register mask entries */
908 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
909 == EFX_ARRAY_SIZE(__siena_registers) * 4);
910
911 nitems = EFX_ARRAY_SIZE(__siena_registers);
912 dwordp = __siena_register_masks;
913 for (count = 0; count < nitems; ++count) {
914 rsp = __siena_registers + count;
915 rsp->mask.eo_u32[0] = *dwordp++;
916 rsp->mask.eo_u32[1] = *dwordp++;
917 rsp->mask.eo_u32[2] = *dwordp++;
918 rsp->mask.eo_u32[3] = *dwordp++;
919 }
920
921 /* Fill out the register table entries */
922 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
923 == EFX_ARRAY_SIZE(__siena_tables) * 4);
924
925 nitems = EFX_ARRAY_SIZE(__siena_tables);
926 dwordp = __siena_table_masks;
927 for (count = 0; count < nitems; ++count) {
928 rsp = __siena_tables + count;
929 rsp->mask.eo_u32[0] = *dwordp++;
930 rsp->mask.eo_u32[1] = *dwordp++;
931 rsp->mask.eo_u32[2] = *dwordp++;
932 rsp->mask.eo_u32[3] = *dwordp++;
933 }
934
935 if ((rc = efx_nic_test_registers(enp, __siena_registers,
936 EFX_ARRAY_SIZE(__siena_registers))) != 0)
937 goto fail1;
938
939 if ((rc = efx_nic_test_tables(enp, __siena_tables,
940 EFX_PATTERN_BYTE_ALTERNATE,
941 EFX_ARRAY_SIZE(__siena_tables))) != 0)
942 goto fail2;
943
944 if ((rc = efx_nic_test_tables(enp, __siena_tables,
945 EFX_PATTERN_BYTE_CHANGING,
946 EFX_ARRAY_SIZE(__siena_tables))) != 0)
947 goto fail3;
948
949 if ((rc = efx_nic_test_tables(enp, __siena_tables,
950 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
951 goto fail4;
952
953 return (0);
954
955fail4:
956 EFSYS_PROBE(fail4);
957fail3:
958 EFSYS_PROBE(fail3);
959fail2:
960 EFSYS_PROBE(fail2);
961fail1:
962 EFSYS_PROBE1(fail1, int, rc);
963
964 return (rc);
965}
966
967#endif /* EFSYS_OPT_DIAG */
968
969#endif /* EFSYS_OPT_SIENA */
329 rc = EMSGSIZE;
330 goto fail3;
331 }
332
333 encp->enc_evq_limit = MCDI_OUT_DWORD(req,
334 GET_RESOURCE_LIMITS_OUT_EVQ);
335 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
336 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
337 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
338 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
339 } else if (req.emr_rc == ENOTSUP) {
340 encp->enc_evq_limit = 1024;
341 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
342 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
343 } else {
344 rc = req.emr_rc;
345 goto fail4;
346 }
347
348 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
349 (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64);
350
351 return (0);
352
353fail4:
354 EFSYS_PROBE(fail4);
355fail3:
356 EFSYS_PROBE(fail3);
357fail2:
358 EFSYS_PROBE(fail2);
359fail1:
360 EFSYS_PROBE1(fail1, int, rc);
361
362 return (rc);
363}
364
365static __checkReturn int
366siena_phy_cfg(
367 __in efx_nic_t *enp)
368{
369 efx_port_t *epp = &(enp->en_port);
370 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
371 efx_mcdi_req_t req;
372 uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
373 int rc;
374
375 req.emr_cmd = MC_CMD_GET_PHY_CFG;
376 EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
377 req.emr_in_buf = NULL;
378 req.emr_in_length = 0;
379 req.emr_out_buf = outbuf;
380 req.emr_out_length = sizeof (outbuf);
381
382 efx_mcdi_execute(enp, &req);
383
384 if (req.emr_rc != 0) {
385 rc = req.emr_rc;
386 goto fail1;
387 }
388
389 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
390 rc = EMSGSIZE;
391 goto fail2;
392 }
393
394 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
395#if EFSYS_OPT_NAMES
396 (void) strncpy(encp->enc_phy_name,
397 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
398 MIN(sizeof (encp->enc_phy_name) - 1,
399 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
400#endif /* EFSYS_OPT_NAMES */
401 (void) memset(encp->enc_phy_revision, 0,
402 sizeof (encp->enc_phy_revision));
403 memcpy(encp->enc_phy_revision,
404 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
405 MIN(sizeof (encp->enc_phy_revision) - 1,
406 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
407#if EFSYS_OPT_PHY_LED_CONTROL
408 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
409 (1 << EFX_PHY_LED_OFF) |
410 (1 << EFX_PHY_LED_ON));
411#endif /* EFSYS_OPT_PHY_LED_CONTROL */
412
413#if EFSYS_OPT_PHY_PROPS
414 encp->enc_phy_nprops = 0;
415#endif /* EFSYS_OPT_PHY_PROPS */
416
417 /* Get the media type of the fixed port, if recognised. */
418 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
419 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
420 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
421 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
422 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
423 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
424 epp->ep_fixed_port_type =
425 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
426 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
427 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
428
429 epp->ep_phy_cap_mask =
430 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
431#if EFSYS_OPT_PHY_FLAGS
432 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
433#endif /* EFSYS_OPT_PHY_FLAGS */
434
435 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
436
437 /* Populate internal state */
438 encp->enc_siena_channel =
439 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
440
441#if EFSYS_OPT_PHY_STATS
442 encp->enc_siena_phy_stat_mask =
443 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
444
445 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
446 siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
447 NULL, &encp->enc_phy_stat_mask, NULL);
448#endif /* EFSYS_OPT_PHY_STATS */
449
450#if EFSYS_OPT_PHY_BIST
451 encp->enc_bist_mask = 0;
452 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
453 GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
454 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
455 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
456 GET_PHY_CFG_OUT_BIST_CABLE_LONG))
457 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
458 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
459 GET_PHY_CFG_OUT_BIST))
460 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
461#endif /* EFSYS_OPT_BIST */
462
463 return (0);
464
465fail2:
466 EFSYS_PROBE(fail2);
467fail1:
468 EFSYS_PROBE1(fail1, int, rc);
469
470 return (rc);
471}
472
473#if EFSYS_OPT_LOOPBACK
474
475static __checkReturn int
476siena_loopback_cfg(
477 __in efx_nic_t *enp)
478{
479 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
480 efx_mcdi_req_t req;
481 uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
482 int rc;
483
484 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
485 EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
486 req.emr_in_buf = NULL;
487 req.emr_in_length = 0;
488 req.emr_out_buf = outbuf;
489 req.emr_out_length = sizeof (outbuf);
490
491 efx_mcdi_execute(enp, &req);
492
493 if (req.emr_rc != 0) {
494 rc = req.emr_rc;
495 goto fail1;
496 }
497
498 if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
499 rc = EMSGSIZE;
500 goto fail2;
501 }
502
503 /*
504 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
505 * in siena_phy.c:siena_phy_get_link()
506 */
507 encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
508 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
509 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
510 encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
511 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
512 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
513 encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
514 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
515 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
516 encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
517 (1 << EFX_LOOPBACK_OFF) |
518 encp->enc_loopback_types[EFX_LINK_100FDX] |
519 encp->enc_loopback_types[EFX_LINK_1000FDX] |
520 encp->enc_loopback_types[EFX_LINK_10000FDX];
521
522 return (0);
523
524fail2:
525 EFSYS_PROBE(fail2);
526fail1:
527 EFSYS_PROBE1(fail1, int, rc);
528
529 return (rc);
530}
531
532#endif /* EFSYS_OPT_LOOPBACK */
533
534#if EFSYS_OPT_MON_STATS
535
536static __checkReturn int
537siena_monitor_cfg(
538 __in efx_nic_t *enp)
539{
540 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
541 efx_mcdi_req_t req;
542 uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
543 int rc;
544
545 req.emr_cmd = MC_CMD_SENSOR_INFO;
546 EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
547 req.emr_in_buf = NULL;
548 req.emr_in_length = 0;
549 req.emr_out_buf = outbuf;
550 req.emr_out_length = sizeof (outbuf);
551
552 efx_mcdi_execute(enp, &req);
553
554 if (req.emr_rc != 0) {
555 rc = req.emr_rc;
556 goto fail1;
557 }
558
559 if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
560 rc = EMSGSIZE;
561 goto fail2;
562 }
563
564 encp->enc_siena_mon_stat_mask =
565 MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
566 encp->enc_mon_type = EFX_MON_SFC90X0;
567
568 siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
569 NULL, &(encp->enc_mon_stat_mask), NULL);
570
571 return (0);
572
573fail2:
574 EFSYS_PROBE(fail2);
575fail1:
576 EFSYS_PROBE1(fail1, int, rc);
577
578 return (rc);
579}
580
581#endif /* EFSYS_OPT_MON_STATS */
582
583 __checkReturn int
584siena_nic_probe(
585 __in efx_nic_t *enp)
586{
587 efx_port_t *epp = &(enp->en_port);
588 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
589 siena_link_state_t sls;
590 unsigned int mask;
591 int rc;
592
593 mask = 0; /* XXX: pacify gcc */
594 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
595
596 /* Read clear any assertion state */
597 if ((rc = siena_nic_read_assertion(enp)) != 0)
598 goto fail1;
599
600 /* Exit the assertion handler */
601 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
602 goto fail2;
603
604 /* Wrestle control from the BMC */
605 if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
606 goto fail3;
607
608 if ((rc = siena_board_cfg(enp)) != 0)
609 goto fail4;
610
611 encp->enc_evq_moderation_max =
612 EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH;
613
614 if ((rc = siena_phy_cfg(enp)) != 0)
615 goto fail5;
616
617 /* Obtain the default PHY advertised capabilities */
618 if ((rc = siena_nic_reset(enp)) != 0)
619 goto fail6;
620 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
621 goto fail7;
622 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
623 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
624
625#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
626 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
627 goto fail8;
628 enp->en_u.siena.enu_partn_mask = mask;
629#endif
630
631#if EFSYS_OPT_MAC_STATS
632 /* Wipe the MAC statistics */
633 if ((rc = siena_mac_stats_clear(enp)) != 0)
634 goto fail9;
635#endif
636
637#if EFSYS_OPT_LOOPBACK
638 if ((rc = siena_loopback_cfg(enp)) != 0)
639 goto fail10;
640#endif
641
642#if EFSYS_OPT_MON_STATS
643 if ((rc = siena_monitor_cfg(enp)) != 0)
644 goto fail11;
645#endif
646
647 encp->enc_features = enp->en_features;
648
649 return (0);
650
651#if EFSYS_OPT_MON_STATS
652fail11:
653 EFSYS_PROBE(fail11);
654#endif
655#if EFSYS_OPT_LOOPBACK
656fail10:
657 EFSYS_PROBE(fail10);
658#endif
659#if EFSYS_OPT_MAC_STATS
660fail9:
661 EFSYS_PROBE(fail9);
662#endif
663#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
664fail8:
665 EFSYS_PROBE(fail8);
666#endif
667fail7:
668 EFSYS_PROBE(fail7);
669fail6:
670 EFSYS_PROBE(fail6);
671fail5:
672 EFSYS_PROBE(fail5);
673fail4:
674 EFSYS_PROBE(fail4);
675fail3:
676 EFSYS_PROBE(fail3);
677fail2:
678 EFSYS_PROBE(fail2);
679fail1:
680 EFSYS_PROBE1(fail1, int, rc);
681
682 return (rc);
683}
684
685 __checkReturn int
686siena_nic_reset(
687 __in efx_nic_t *enp)
688{
689 efx_mcdi_req_t req;
690 int rc;
691
692 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
693
694 /* siena_nic_reset() is called to recover from BADASSERT failures. */
695 if ((rc = siena_nic_read_assertion(enp)) != 0)
696 goto fail1;
697 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
698 goto fail2;
699
700 req.emr_cmd = MC_CMD_PORT_RESET;
701 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
702 req.emr_in_buf = NULL;
703 req.emr_in_length = 0;
704 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
705 req.emr_out_buf = NULL;
706 req.emr_out_length = 0;
707
708 efx_mcdi_execute(enp, &req);
709
710 if (req.emr_rc != 0) {
711 rc = req.emr_rc;
712 goto fail3;
713 }
714
715 return (0);
716
717fail3:
718 EFSYS_PROBE(fail3);
719fail2:
720 EFSYS_PROBE(fail2);
721fail1:
722 EFSYS_PROBE1(fail1, int, rc);
723
724 return (0);
725}
726
727static __checkReturn int
728siena_nic_logging(
729 __in efx_nic_t *enp)
730{
731 efx_mcdi_req_t req;
732 uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
733 int rc;
734
735 req.emr_cmd = MC_CMD_LOG_CTRL;
736 req.emr_in_buf = payload;
737 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
738 EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
739 req.emr_out_buf = NULL;
740 req.emr_out_length = 0;
741
742 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
743 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
744 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
745
746 efx_mcdi_execute(enp, &req);
747
748 if (req.emr_rc != 0) {
749 rc = req.emr_rc;
750 goto fail1;
751 }
752
753 return (0);
754
755fail1:
756 EFSYS_PROBE1(fail1, int, rc);
757
758 return (rc);
759}
760
761static void
762siena_nic_rx_cfg(
763 __in efx_nic_t *enp)
764{
765 efx_oword_t oword;
766
767 /*
768 * RX_INGR_EN is always enabled on Siena, because we rely on
769 * the RX parser to be resiliant to missing SOP/EOP.
770 */
771 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
772 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
773 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
774
775 /* Disable parsing of additional 802.1Q in Q packets */
776 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
777 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
778 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
779}
780
781static void
782siena_nic_usrev_dis(
783 __in efx_nic_t *enp)
784{
785 efx_oword_t oword;
786
787 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
788 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
789}
790
791 __checkReturn int
792siena_nic_init(
793 __in efx_nic_t *enp)
794{
795 int rc;
796
797 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
798
799 if ((rc = siena_nic_logging(enp)) != 0)
800 goto fail1;
801
802 siena_sram_init(enp);
803
804 /* Configure Siena's RX block */
805 siena_nic_rx_cfg(enp);
806
807 /* Disable USR_EVents for now */
808 siena_nic_usrev_dis(enp);
809
810 /* bug17057: Ensure set_link is called */
811 if ((rc = siena_phy_reconfigure(enp)) != 0)
812 goto fail2;
813
814 return (0);
815
816fail2:
817 EFSYS_PROBE(fail2);
818fail1:
819 EFSYS_PROBE1(fail1, int, rc);
820
821 return (rc);
822}
823
824 void
825siena_nic_fini(
826 __in efx_nic_t *enp)
827{
828 _NOTE(ARGUNUSED(enp))
829}
830
831 void
832siena_nic_unprobe(
833 __in efx_nic_t *enp)
834{
835 (void) siena_nic_attach(enp, B_FALSE);
836}
837
838#if EFSYS_OPT_DIAG
839
840static efx_register_set_t __cs __siena_registers[] = {
841 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
842 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
843 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
844 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
845 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
846 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
847 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
848 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
849 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
850 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
851 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
852 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
853 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
854};
855
856static const uint32_t __cs __siena_register_masks[] = {
857 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
858 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
859 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
860 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
861 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
862 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
863 0x00000003, 0x00000000, 0x00000000, 0x00000000,
864 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
865 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
866 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
867 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
868 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
869 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
870};
871
872static efx_register_set_t __cs __siena_tables[] = {
873 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
874 FR_AZ_RX_FILTER_TBL0_ROWS },
875 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
876 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
877 { FR_AZ_RX_DESC_PTR_TBL_OFST,
878 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
879 { FR_AZ_TX_DESC_PTR_TBL_OFST,
880 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
881 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
882 { FR_CZ_TX_FILTER_TBL0_OFST,
883 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
884 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
885 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
886};
887
888static const uint32_t __cs __siena_table_masks[] = {
889 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
890 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
891 0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000,
892 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
893 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
894 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
895 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
896};
897
898 __checkReturn int
899siena_nic_register_test(
900 __in efx_nic_t *enp)
901{
902 efx_register_set_t *rsp;
903 const uint32_t *dwordp;
904 unsigned int nitems;
905 unsigned int count;
906 int rc;
907
908 /* Fill out the register mask entries */
909 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
910 == EFX_ARRAY_SIZE(__siena_registers) * 4);
911
912 nitems = EFX_ARRAY_SIZE(__siena_registers);
913 dwordp = __siena_register_masks;
914 for (count = 0; count < nitems; ++count) {
915 rsp = __siena_registers + count;
916 rsp->mask.eo_u32[0] = *dwordp++;
917 rsp->mask.eo_u32[1] = *dwordp++;
918 rsp->mask.eo_u32[2] = *dwordp++;
919 rsp->mask.eo_u32[3] = *dwordp++;
920 }
921
922 /* Fill out the register table entries */
923 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
924 == EFX_ARRAY_SIZE(__siena_tables) * 4);
925
926 nitems = EFX_ARRAY_SIZE(__siena_tables);
927 dwordp = __siena_table_masks;
928 for (count = 0; count < nitems; ++count) {
929 rsp = __siena_tables + count;
930 rsp->mask.eo_u32[0] = *dwordp++;
931 rsp->mask.eo_u32[1] = *dwordp++;
932 rsp->mask.eo_u32[2] = *dwordp++;
933 rsp->mask.eo_u32[3] = *dwordp++;
934 }
935
936 if ((rc = efx_nic_test_registers(enp, __siena_registers,
937 EFX_ARRAY_SIZE(__siena_registers))) != 0)
938 goto fail1;
939
940 if ((rc = efx_nic_test_tables(enp, __siena_tables,
941 EFX_PATTERN_BYTE_ALTERNATE,
942 EFX_ARRAY_SIZE(__siena_tables))) != 0)
943 goto fail2;
944
945 if ((rc = efx_nic_test_tables(enp, __siena_tables,
946 EFX_PATTERN_BYTE_CHANGING,
947 EFX_ARRAY_SIZE(__siena_tables))) != 0)
948 goto fail3;
949
950 if ((rc = efx_nic_test_tables(enp, __siena_tables,
951 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
952 goto fail4;
953
954 return (0);
955
956fail4:
957 EFSYS_PROBE(fail4);
958fail3:
959 EFSYS_PROBE(fail3);
960fail2:
961 EFSYS_PROBE(fail2);
962fail1:
963 EFSYS_PROBE1(fail1, int, rc);
964
965 return (rc);
966}
967
968#endif /* EFSYS_OPT_DIAG */
969
970#endif /* EFSYS_OPT_SIENA */