2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
36 #include "efx_types.h"
45 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
48 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
49 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
50 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_WOL));
52 if (~(encp->enc_features) & EFX_FEATURE_WOL) {
57 /* Current implementation is Siena specific */
58 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
60 enp->en_mod_flags |= EFX_MOD_WOL;
65 EFSYS_PROBE1(fail1, int, rc);
75 uint8_t payload[MAX(MC_CMD_WOL_FILTER_RESET_IN_LEN,
76 MC_CMD_WOL_FILTER_RESET_OUT_LEN)];
79 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
80 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
82 (void) memset(payload, 0, sizeof (payload));
83 req.emr_cmd = MC_CMD_WOL_FILTER_RESET;
84 req.emr_in_buf = payload;
85 req.emr_in_length = MC_CMD_WOL_FILTER_RESET_IN_LEN;
86 req.emr_out_buf = payload;
87 req.emr_out_length = MC_CMD_WOL_FILTER_RESET_OUT_LEN;
89 MCDI_IN_SET_DWORD(req, WOL_FILTER_RESET_IN_MASK,
90 MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS |
91 MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS);
93 efx_mcdi_execute(enp, &req);
95 if (req.emr_rc != 0) {
103 EFSYS_PROBE1(fail1, int, rc);
111 __in efx_wol_type_t type,
112 __in efx_wol_param_t *paramp,
113 __out uint32_t *filter_idp)
116 uint8_t payload[MAX(MC_CMD_WOL_FILTER_SET_IN_LEN,
117 MC_CMD_WOL_FILTER_SET_OUT_LEN)];
118 efx_byte_t link_mask;
121 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
122 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
124 (void) memset(payload, 0, sizeof (payload));
125 req.emr_cmd = MC_CMD_WOL_FILTER_SET;
126 req.emr_in_buf = payload;
127 req.emr_in_length = MC_CMD_WOL_FILTER_SET_IN_LEN;
128 req.emr_out_buf = payload;
129 req.emr_out_length = MC_CMD_WOL_FILTER_SET_OUT_LEN;
132 case EFX_WOL_TYPE_MAGIC:
133 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
134 MC_CMD_FILTER_MODE_SIMPLE);
135 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
136 MC_CMD_WOL_TYPE_MAGIC);
138 MCDI_IN2(req, uint8_t, WOL_FILTER_SET_IN_MAGIC_MAC),
139 paramp->ewp_magic.mac_addr);
142 case EFX_WOL_TYPE_BITMAP: {
143 uint32_t swapped = 0;
145 unsigned int pos, bit;
147 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
148 MC_CMD_FILTER_MODE_SIMPLE);
149 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
150 MC_CMD_WOL_TYPE_BITMAP);
153 * MC bitmask is supposed to be bit swapped
154 * amongst 32 bit words(!)
157 dwordp = MCDI_IN2(req, efx_dword_t,
158 WOL_FILTER_SET_IN_BITMAP_MASK);
160 EFSYS_ASSERT3U(EFX_WOL_BITMAP_MASK_SIZE % 4, ==, 0);
162 for (pos = 0; pos < EFX_WOL_BITMAP_MASK_SIZE; ++pos) {
163 uint8_t native = paramp->ewp_bitmap.mask[pos];
165 for (bit = 0; bit < 8; ++bit) {
167 swapped |= (native & 0x1);
171 if ((pos & 3) == 3) {
172 EFX_POPULATE_DWORD_1(dwordp[pos >> 2],
173 EFX_DWORD_0, swapped);
178 memcpy(MCDI_IN2(req, uint8_t, WOL_FILTER_SET_IN_BITMAP_BITMAP),
179 paramp->ewp_bitmap.value,
180 sizeof (paramp->ewp_bitmap.value));
182 EFSYS_ASSERT3U(paramp->ewp_bitmap.value_len, <=,
183 sizeof (paramp->ewp_bitmap.value));
184 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_BITMAP_LEN,
185 paramp->ewp_bitmap.value_len);
189 case EFX_WOL_TYPE_LINK:
190 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
191 MC_CMD_FILTER_MODE_SIMPLE);
192 MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
193 MC_CMD_WOL_TYPE_LINK);
195 EFX_ZERO_BYTE(link_mask);
196 EFX_SET_BYTE_FIELD(link_mask, MC_CMD_WOL_FILTER_SET_IN_LINK_UP,
198 MCDI_IN_SET_BYTE(req, WOL_FILTER_SET_IN_LINK_MASK,
203 EFSYS_ASSERT3U(type, !=, type);
206 efx_mcdi_execute(enp, &req);
208 if (req.emr_rc != 0) {
213 if (req.emr_out_length_used < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
218 *filter_idp = MCDI_OUT_DWORD(req, WOL_FILTER_SET_OUT_FILTER_ID);
225 EFSYS_PROBE1(fail1, int, rc);
231 efx_wol_filter_remove(
233 __in uint32_t filter_id)
236 uint8_t payload[MAX(MC_CMD_WOL_FILTER_REMOVE_IN_LEN,
237 MC_CMD_WOL_FILTER_REMOVE_OUT_LEN)];
240 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
241 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
243 (void) memset(payload, 0, sizeof (payload));
244 req.emr_cmd = MC_CMD_WOL_FILTER_REMOVE;
245 req.emr_in_buf = payload;
246 req.emr_in_length = MC_CMD_WOL_FILTER_REMOVE_IN_LEN;
247 req.emr_out_buf = payload;
248 req.emr_out_length = MC_CMD_WOL_FILTER_REMOVE_OUT_LEN;
250 MCDI_IN_SET_DWORD(req, WOL_FILTER_REMOVE_IN_FILTER_ID, filter_id);
252 efx_mcdi_execute(enp, &req);
254 if (req.emr_rc != 0) {
262 EFSYS_PROBE1(fail1, int, rc);
269 efx_lightsout_offload_add(
271 __in efx_lightsout_offload_type_t type,
272 __in efx_lightsout_offload_param_t *paramp,
273 __out uint32_t *filter_idp)
276 uint8_t payload[MAX(MAX(MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN,
277 MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN),
278 MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN)];
281 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
282 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
284 (void) memset(payload, 0, sizeof (payload));
285 req.emr_cmd = MC_CMD_ADD_LIGHTSOUT_OFFLOAD;
286 req.emr_in_buf = payload;
287 req.emr_in_length = sizeof (type);
288 req.emr_out_buf = payload;
289 req.emr_out_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN;
292 case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
293 req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN;
295 MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
296 MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
297 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
298 ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC),
299 paramp->elop_arp.mac_addr);
300 MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP,
301 paramp->elop_arp.ip);
303 case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
304 req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN;
306 MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
307 MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
308 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
309 ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC),
310 paramp->elop_ns.mac_addr);
311 memcpy(MCDI_IN2(req, uint8_t,
312 ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6),
313 paramp->elop_ns.solicited_node,
314 sizeof (paramp->elop_ns.solicited_node));
315 memcpy(MCDI_IN2(req, uint8_t, ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6),
316 paramp->elop_ns.ip, sizeof (paramp->elop_ns.ip));
323 efx_mcdi_execute(enp, &req);
325 if (req.emr_rc != 0) {
330 if (req.emr_out_length_used < MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN) {
335 *filter_idp = MCDI_OUT_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID);
344 EFSYS_PROBE1(fail1, int, rc);
351 efx_lightsout_offload_remove(
353 __in efx_lightsout_offload_type_t type,
354 __in uint32_t filter_id)
357 uint8_t payload[MAX(MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN,
358 MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN)];
361 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
362 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
364 (void) memset(payload, 0, sizeof (payload));
365 req.emr_cmd = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD;
366 req.emr_in_buf = payload;
367 req.emr_in_length = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN;
368 req.emr_out_buf = payload;
369 req.emr_out_length = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN;
372 case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
373 MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
374 MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
376 case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
377 MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
378 MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
385 MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID,
388 efx_mcdi_execute(enp, &req);
390 if (req.emr_rc != 0) {
400 EFSYS_PROBE1(fail1, int, rc);
410 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
411 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
412 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
414 enp->en_mod_flags &= ~EFX_MOD_WOL;
417 #endif /* EFSYS_OPT_WOL */