1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore  * Copyright (c) 2009-2015 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore  * All rights reserved.
4*49ef7e06SGarrett D'Amore  *
5*49ef7e06SGarrett D'Amore  * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore  * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore  *
8*49ef7e06SGarrett D'Amore  * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore  * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore  *    and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore  *
14*49ef7e06SGarrett D'Amore  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore  *
26*49ef7e06SGarrett D'Amore  * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore  * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore  * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore  */
30*49ef7e06SGarrett D'Amore 
31*49ef7e06SGarrett D'Amore #include "efx.h"
32*49ef7e06SGarrett D'Amore #include "efx_impl.h"
33*49ef7e06SGarrett D'Amore 
34*49ef7e06SGarrett D'Amore #if EFSYS_OPT_WOL
35*49ef7e06SGarrett D'Amore 
36*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_wol_init(__in efx_nic_t * enp)37*49ef7e06SGarrett D'Amore efx_wol_init(
38*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
39*49ef7e06SGarrett D'Amore {
40*49ef7e06SGarrett D'Amore 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
41*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
42*49ef7e06SGarrett D'Amore 
43*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
44*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
45*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_WOL));
46*49ef7e06SGarrett D'Amore 
47*49ef7e06SGarrett D'Amore 	if (~(encp->enc_features) & EFX_FEATURE_WOL) {
48*49ef7e06SGarrett D'Amore 		rc = ENOTSUP;
49*49ef7e06SGarrett D'Amore 		goto fail1;
50*49ef7e06SGarrett D'Amore 	}
51*49ef7e06SGarrett D'Amore 
52*49ef7e06SGarrett D'Amore 	/* Current implementation is Siena specific */
53*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
54*49ef7e06SGarrett D'Amore 
55*49ef7e06SGarrett D'Amore 	enp->en_mod_flags |= EFX_MOD_WOL;
56*49ef7e06SGarrett D'Amore 
57*49ef7e06SGarrett D'Amore 	return (0);
58*49ef7e06SGarrett D'Amore 
59*49ef7e06SGarrett D'Amore fail1:
60*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
61*49ef7e06SGarrett D'Amore 
62*49ef7e06SGarrett D'Amore 	return (rc);
63*49ef7e06SGarrett D'Amore }
64*49ef7e06SGarrett D'Amore 
65*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_wol_filter_clear(__in efx_nic_t * enp)66*49ef7e06SGarrett D'Amore efx_wol_filter_clear(
67*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
68*49ef7e06SGarrett D'Amore {
69*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
70*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_WOL_FILTER_RESET_IN_LEN,
71*49ef7e06SGarrett D'Amore 			    MC_CMD_WOL_FILTER_RESET_OUT_LEN)];
72*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
73*49ef7e06SGarrett D'Amore 
74*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
75*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
76*49ef7e06SGarrett D'Amore 
77*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
78*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_WOL_FILTER_RESET;
79*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
80*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_WOL_FILTER_RESET_IN_LEN;
81*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
82*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_WOL_FILTER_RESET_OUT_LEN;
83*49ef7e06SGarrett D'Amore 
84*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, WOL_FILTER_RESET_IN_MASK,
85*49ef7e06SGarrett D'Amore 			    MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS |
86*49ef7e06SGarrett D'Amore 			    MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS);
87*49ef7e06SGarrett D'Amore 
88*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
89*49ef7e06SGarrett D'Amore 
90*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
91*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
92*49ef7e06SGarrett D'Amore 		goto fail1;
93*49ef7e06SGarrett D'Amore 	}
94*49ef7e06SGarrett D'Amore 
95*49ef7e06SGarrett D'Amore 	return (0);
96*49ef7e06SGarrett D'Amore 
97*49ef7e06SGarrett D'Amore fail1:
98*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
99*49ef7e06SGarrett D'Amore 
100*49ef7e06SGarrett D'Amore 	return (rc);
101*49ef7e06SGarrett D'Amore }
102*49ef7e06SGarrett D'Amore 
103*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_wol_filter_add(__in efx_nic_t * enp,__in efx_wol_type_t type,__in efx_wol_param_t * paramp,__out uint32_t * filter_idp)104*49ef7e06SGarrett D'Amore efx_wol_filter_add(
105*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp,
106*49ef7e06SGarrett D'Amore 	__in		efx_wol_type_t type,
107*49ef7e06SGarrett D'Amore 	__in		efx_wol_param_t *paramp,
108*49ef7e06SGarrett D'Amore 	__out		uint32_t *filter_idp)
109*49ef7e06SGarrett D'Amore {
110*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
111*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_WOL_FILTER_SET_IN_LEN,
112*49ef7e06SGarrett D'Amore 			    MC_CMD_WOL_FILTER_SET_OUT_LEN)];
113*49ef7e06SGarrett D'Amore 	efx_byte_t link_mask;
114*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
115*49ef7e06SGarrett D'Amore 
116*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
117*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
118*49ef7e06SGarrett D'Amore 
119*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
120*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_WOL_FILTER_SET;
121*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
122*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_WOL_FILTER_SET_IN_LEN;
123*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
124*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_WOL_FILTER_SET_OUT_LEN;
125*49ef7e06SGarrett D'Amore 
126*49ef7e06SGarrett D'Amore 	switch (type) {
127*49ef7e06SGarrett D'Amore 	case EFX_WOL_TYPE_MAGIC:
128*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
129*49ef7e06SGarrett D'Amore 				    MC_CMD_FILTER_MODE_SIMPLE);
130*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
131*49ef7e06SGarrett D'Amore 				    MC_CMD_WOL_TYPE_MAGIC);
132*49ef7e06SGarrett D'Amore 		EFX_MAC_ADDR_COPY(
133*49ef7e06SGarrett D'Amore 			MCDI_IN2(req, uint8_t, WOL_FILTER_SET_IN_MAGIC_MAC),
134*49ef7e06SGarrett D'Amore 			paramp->ewp_magic.mac_addr);
135*49ef7e06SGarrett D'Amore 		break;
136*49ef7e06SGarrett D'Amore 
137*49ef7e06SGarrett D'Amore 	case EFX_WOL_TYPE_BITMAP: {
138*49ef7e06SGarrett D'Amore 		uint32_t swapped = 0;
139*49ef7e06SGarrett D'Amore 		efx_dword_t *dwordp;
140*49ef7e06SGarrett D'Amore 		unsigned int pos, bit;
141*49ef7e06SGarrett D'Amore 
142*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
143*49ef7e06SGarrett D'Amore 				    MC_CMD_FILTER_MODE_SIMPLE);
144*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
145*49ef7e06SGarrett D'Amore 				    MC_CMD_WOL_TYPE_BITMAP);
146*49ef7e06SGarrett D'Amore 
147*49ef7e06SGarrett D'Amore 		/*
148*49ef7e06SGarrett D'Amore 		 * MC bitmask is supposed to be bit swapped
149*49ef7e06SGarrett D'Amore 		 * amongst 32 bit words(!)
150*49ef7e06SGarrett D'Amore 		 */
151*49ef7e06SGarrett D'Amore 
152*49ef7e06SGarrett D'Amore 		dwordp = MCDI_IN2(req, efx_dword_t,
153*49ef7e06SGarrett D'Amore 				    WOL_FILTER_SET_IN_BITMAP_MASK);
154*49ef7e06SGarrett D'Amore 
155*49ef7e06SGarrett D'Amore 		EFSYS_ASSERT3U(EFX_WOL_BITMAP_MASK_SIZE % 4, ==, 0);
156*49ef7e06SGarrett D'Amore 
157*49ef7e06SGarrett D'Amore 		for (pos = 0; pos < EFX_WOL_BITMAP_MASK_SIZE; ++pos) {
158*49ef7e06SGarrett D'Amore 			uint8_t native = paramp->ewp_bitmap.mask[pos];
159*49ef7e06SGarrett D'Amore 
160*49ef7e06SGarrett D'Amore 			for (bit = 0; bit < 8; ++bit) {
161*49ef7e06SGarrett D'Amore 				swapped <<= 1;
162*49ef7e06SGarrett D'Amore 				swapped |= (native & 0x1);
163*49ef7e06SGarrett D'Amore 				native >>= 1;
164*49ef7e06SGarrett D'Amore 			}
165*49ef7e06SGarrett D'Amore 
166*49ef7e06SGarrett D'Amore 			if ((pos & 3) == 3) {
167*49ef7e06SGarrett D'Amore 				EFX_POPULATE_DWORD_1(dwordp[pos >> 2],
168*49ef7e06SGarrett D'Amore 				    EFX_DWORD_0, swapped);
169*49ef7e06SGarrett D'Amore 				swapped = 0;
170*49ef7e06SGarrett D'Amore 			}
171*49ef7e06SGarrett D'Amore 		}
172*49ef7e06SGarrett D'Amore 
173*49ef7e06SGarrett D'Amore 		(void) memcpy(MCDI_IN2(req, uint8_t,
174*49ef7e06SGarrett D'Amore 		    WOL_FILTER_SET_IN_BITMAP_BITMAP),
175*49ef7e06SGarrett D'Amore 		    paramp->ewp_bitmap.value,
176*49ef7e06SGarrett D'Amore 		    sizeof (paramp->ewp_bitmap.value));
177*49ef7e06SGarrett D'Amore 
178*49ef7e06SGarrett D'Amore 		EFSYS_ASSERT3U(paramp->ewp_bitmap.value_len, <=,
179*49ef7e06SGarrett D'Amore 				    sizeof (paramp->ewp_bitmap.value));
180*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_BITMAP_LEN,
181*49ef7e06SGarrett D'Amore 				    paramp->ewp_bitmap.value_len);
182*49ef7e06SGarrett D'Amore 		}
183*49ef7e06SGarrett D'Amore 		break;
184*49ef7e06SGarrett D'Amore 
185*49ef7e06SGarrett D'Amore 	case EFX_WOL_TYPE_LINK:
186*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
187*49ef7e06SGarrett D'Amore 				    MC_CMD_FILTER_MODE_SIMPLE);
188*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
189*49ef7e06SGarrett D'Amore 				    MC_CMD_WOL_TYPE_LINK);
190*49ef7e06SGarrett D'Amore 
191*49ef7e06SGarrett D'Amore 		EFX_ZERO_BYTE(link_mask);
192*49ef7e06SGarrett D'Amore 		EFX_SET_BYTE_FIELD(link_mask, MC_CMD_WOL_FILTER_SET_IN_LINK_UP,
193*49ef7e06SGarrett D'Amore 		    1);
194*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_BYTE(req, WOL_FILTER_SET_IN_LINK_MASK,
195*49ef7e06SGarrett D'Amore 		    link_mask.eb_u8[0]);
196*49ef7e06SGarrett D'Amore 		break;
197*49ef7e06SGarrett D'Amore 
198*49ef7e06SGarrett D'Amore 	default:
199*49ef7e06SGarrett D'Amore 		EFSYS_ASSERT3U(type, !=, type);
200*49ef7e06SGarrett D'Amore 	}
201*49ef7e06SGarrett D'Amore 
202*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
203*49ef7e06SGarrett D'Amore 
204*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
205*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
206*49ef7e06SGarrett D'Amore 		goto fail1;
207*49ef7e06SGarrett D'Amore 	}
208*49ef7e06SGarrett D'Amore 
209*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
210*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
211*49ef7e06SGarrett D'Amore 		goto fail2;
212*49ef7e06SGarrett D'Amore 	}
213*49ef7e06SGarrett D'Amore 
214*49ef7e06SGarrett D'Amore 	*filter_idp = MCDI_OUT_DWORD(req, WOL_FILTER_SET_OUT_FILTER_ID);
215*49ef7e06SGarrett D'Amore 
216*49ef7e06SGarrett D'Amore 	return (0);
217*49ef7e06SGarrett D'Amore 
218*49ef7e06SGarrett D'Amore fail2:
219*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
220*49ef7e06SGarrett D'Amore fail1:
221*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
222*49ef7e06SGarrett D'Amore 
223*49ef7e06SGarrett D'Amore 	return (rc);
224*49ef7e06SGarrett D'Amore }
225*49ef7e06SGarrett D'Amore 
226*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_wol_filter_remove(__in efx_nic_t * enp,__in uint32_t filter_id)227*49ef7e06SGarrett D'Amore efx_wol_filter_remove(
228*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp,
229*49ef7e06SGarrett D'Amore 	__in		uint32_t filter_id)
230*49ef7e06SGarrett D'Amore {
231*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
232*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_WOL_FILTER_REMOVE_IN_LEN,
233*49ef7e06SGarrett D'Amore 			    MC_CMD_WOL_FILTER_REMOVE_OUT_LEN)];
234*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
235*49ef7e06SGarrett D'Amore 
236*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
237*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
238*49ef7e06SGarrett D'Amore 
239*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
240*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_WOL_FILTER_REMOVE;
241*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
242*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_WOL_FILTER_REMOVE_IN_LEN;
243*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
244*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_WOL_FILTER_REMOVE_OUT_LEN;
245*49ef7e06SGarrett D'Amore 
246*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, WOL_FILTER_REMOVE_IN_FILTER_ID, filter_id);
247*49ef7e06SGarrett D'Amore 
248*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
249*49ef7e06SGarrett D'Amore 
250*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
251*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
252*49ef7e06SGarrett D'Amore 		goto fail1;
253*49ef7e06SGarrett D'Amore 	}
254*49ef7e06SGarrett D'Amore 
255*49ef7e06SGarrett D'Amore 	return (0);
256*49ef7e06SGarrett D'Amore 
257*49ef7e06SGarrett D'Amore fail1:
258*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
259*49ef7e06SGarrett D'Amore 
260*49ef7e06SGarrett D'Amore 	return (rc);
261*49ef7e06SGarrett D'Amore }
262*49ef7e06SGarrett D'Amore 
263*49ef7e06SGarrett D'Amore 
264*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_lightsout_offload_add(__in efx_nic_t * enp,__in efx_lightsout_offload_type_t type,__in efx_lightsout_offload_param_t * paramp,__out uint32_t * filter_idp)265*49ef7e06SGarrett D'Amore efx_lightsout_offload_add(
266*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp,
267*49ef7e06SGarrett D'Amore 	__in		efx_lightsout_offload_type_t type,
268*49ef7e06SGarrett D'Amore 	__in		efx_lightsout_offload_param_t *paramp,
269*49ef7e06SGarrett D'Amore 	__out		uint32_t *filter_idp)
270*49ef7e06SGarrett D'Amore {
271*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
272*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MAX(MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN,
273*49ef7e06SGarrett D'Amore 				MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN),
274*49ef7e06SGarrett D'Amore 			    MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN)];
275*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
276*49ef7e06SGarrett D'Amore 
277*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
278*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
279*49ef7e06SGarrett D'Amore 
280*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
281*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_ADD_LIGHTSOUT_OFFLOAD;
282*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
283*49ef7e06SGarrett D'Amore 	req.emr_in_length = sizeof (type);
284*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
285*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN;
286*49ef7e06SGarrett D'Amore 
287*49ef7e06SGarrett D'Amore 	switch (type) {
288*49ef7e06SGarrett D'Amore 	case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
289*49ef7e06SGarrett D'Amore 		req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN;
290*49ef7e06SGarrett D'Amore 
291*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
292*49ef7e06SGarrett D'Amore 				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
293*49ef7e06SGarrett D'Amore 		EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
294*49ef7e06SGarrett D'Amore 					    ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC),
295*49ef7e06SGarrett D'Amore 				    paramp->elop_arp.mac_addr);
296*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP,
297*49ef7e06SGarrett D'Amore 				    paramp->elop_arp.ip);
298*49ef7e06SGarrett D'Amore 		break;
299*49ef7e06SGarrett D'Amore 	case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
300*49ef7e06SGarrett D'Amore 		req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN;
301*49ef7e06SGarrett D'Amore 
302*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
303*49ef7e06SGarrett D'Amore 				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
304*49ef7e06SGarrett D'Amore 		EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
305*49ef7e06SGarrett D'Amore 					    ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC),
306*49ef7e06SGarrett D'Amore 				    paramp->elop_ns.mac_addr);
307*49ef7e06SGarrett D'Amore 		(void) memcpy(MCDI_IN2(req, uint8_t,
308*49ef7e06SGarrett D'Amore 		    ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6),
309*49ef7e06SGarrett D'Amore 		    paramp->elop_ns.solicited_node,
310*49ef7e06SGarrett D'Amore 		    sizeof (paramp->elop_ns.solicited_node));
311*49ef7e06SGarrett D'Amore 		(void) memcpy(MCDI_IN2(req, uint8_t,
312*49ef7e06SGarrett D'Amore 		    ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6),
313*49ef7e06SGarrett D'Amore 		    paramp->elop_ns.ip, sizeof (paramp->elop_ns.ip));
314*49ef7e06SGarrett D'Amore 		break;
315*49ef7e06SGarrett D'Amore 	default:
316*49ef7e06SGarrett D'Amore 		rc = EINVAL;
317*49ef7e06SGarrett D'Amore 		goto fail1;
318*49ef7e06SGarrett D'Amore 	}
319*49ef7e06SGarrett D'Amore 
320*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
321*49ef7e06SGarrett D'Amore 
322*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
323*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
324*49ef7e06SGarrett D'Amore 		goto fail2;
325*49ef7e06SGarrett D'Amore 	}
326*49ef7e06SGarrett D'Amore 
327*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN) {
328*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
329*49ef7e06SGarrett D'Amore 		goto fail3;
330*49ef7e06SGarrett D'Amore 	}
331*49ef7e06SGarrett D'Amore 
332*49ef7e06SGarrett D'Amore 	*filter_idp = MCDI_OUT_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID);
333*49ef7e06SGarrett D'Amore 
334*49ef7e06SGarrett D'Amore 	return (0);
335*49ef7e06SGarrett D'Amore 
336*49ef7e06SGarrett D'Amore fail3:
337*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
338*49ef7e06SGarrett D'Amore fail2:
339*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
340*49ef7e06SGarrett D'Amore fail1:
341*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
342*49ef7e06SGarrett D'Amore 
343*49ef7e06SGarrett D'Amore 	return (rc);
344*49ef7e06SGarrett D'Amore }
345*49ef7e06SGarrett D'Amore 
346*49ef7e06SGarrett D'Amore 
347*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_lightsout_offload_remove(__in efx_nic_t * enp,__in efx_lightsout_offload_type_t type,__in uint32_t filter_id)348*49ef7e06SGarrett D'Amore efx_lightsout_offload_remove(
349*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp,
350*49ef7e06SGarrett D'Amore 	__in		efx_lightsout_offload_type_t type,
351*49ef7e06SGarrett D'Amore 	__in		uint32_t filter_id)
352*49ef7e06SGarrett D'Amore {
353*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
354*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN,
355*49ef7e06SGarrett D'Amore 			    MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN)];
356*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
357*49ef7e06SGarrett D'Amore 
358*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
359*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
360*49ef7e06SGarrett D'Amore 
361*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
362*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD;
363*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
364*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN;
365*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
366*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN;
367*49ef7e06SGarrett D'Amore 
368*49ef7e06SGarrett D'Amore 	switch (type) {
369*49ef7e06SGarrett D'Amore 	case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
370*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
371*49ef7e06SGarrett D'Amore 				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
372*49ef7e06SGarrett D'Amore 		break;
373*49ef7e06SGarrett D'Amore 	case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
374*49ef7e06SGarrett D'Amore 		MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
375*49ef7e06SGarrett D'Amore 				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
376*49ef7e06SGarrett D'Amore 		break;
377*49ef7e06SGarrett D'Amore 	default:
378*49ef7e06SGarrett D'Amore 		rc = EINVAL;
379*49ef7e06SGarrett D'Amore 		goto fail1;
380*49ef7e06SGarrett D'Amore 	}
381*49ef7e06SGarrett D'Amore 
382*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID,
383*49ef7e06SGarrett D'Amore 			    filter_id);
384*49ef7e06SGarrett D'Amore 
385*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
386*49ef7e06SGarrett D'Amore 
387*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
388*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
389*49ef7e06SGarrett D'Amore 		goto fail2;
390*49ef7e06SGarrett D'Amore 	}
391*49ef7e06SGarrett D'Amore 
392*49ef7e06SGarrett D'Amore 	return (0);
393*49ef7e06SGarrett D'Amore 
394*49ef7e06SGarrett D'Amore fail2:
395*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
396*49ef7e06SGarrett D'Amore fail1:
397*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
398*49ef7e06SGarrett D'Amore 
399*49ef7e06SGarrett D'Amore 	return (rc);
400*49ef7e06SGarrett D'Amore }
401*49ef7e06SGarrett D'Amore 
402*49ef7e06SGarrett D'Amore 
403*49ef7e06SGarrett D'Amore 			void
efx_wol_fini(__in efx_nic_t * enp)404*49ef7e06SGarrett D'Amore efx_wol_fini(
405*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
406*49ef7e06SGarrett D'Amore {
407*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
408*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
409*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
410*49ef7e06SGarrett D'Amore 
411*49ef7e06SGarrett D'Amore 	enp->en_mod_flags &= ~EFX_MOD_WOL;
412*49ef7e06SGarrett D'Amore }
413*49ef7e06SGarrett D'Amore 
414*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_WOL */
415