2 * Copyright (c) 2007-2016 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.
34 __checkReturn efx_rc_t
39 efx_port_t *epp = &(enp->en_port);
40 const efx_mac_ops_t *emop = epp->ep_emop;
44 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
45 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
46 EFSYS_ASSERT(emop != NULL);
48 if (pdu < EFX_MAC_PDU_MIN) {
53 if (pdu > EFX_MAC_PDU_MAX) {
58 old_pdu = epp->ep_mac_pdu;
59 epp->ep_mac_pdu = (uint32_t)pdu;
60 if ((rc = emop->emo_pdu_set(enp)) != 0)
68 epp->ep_mac_pdu = old_pdu;
73 EFSYS_PROBE1(fail1, efx_rc_t, rc);
78 __checkReturn efx_rc_t
83 efx_port_t *epp = &(enp->en_port);
84 const efx_mac_ops_t *emop = epp->ep_emop;
87 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
93 EFSYS_PROBE1(fail1, efx_rc_t, rc);
98 __checkReturn efx_rc_t
103 efx_port_t *epp = &(enp->en_port);
104 const efx_mac_ops_t *emop = epp->ep_emop;
109 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
110 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
112 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
117 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
118 if (oui == 0x000000) {
123 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
124 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
125 if ((rc = emop->emo_addr_set(enp)) != 0)
133 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
138 EFSYS_PROBE1(fail1, efx_rc_t, rc);
143 __checkReturn efx_rc_t
146 __in boolean_t all_unicst,
147 __in boolean_t mulcst,
148 __in boolean_t all_mulcst,
149 __in boolean_t brdcst)
151 efx_port_t *epp = &(enp->en_port);
152 const efx_mac_ops_t *emop = epp->ep_emop;
153 boolean_t old_all_unicst;
154 boolean_t old_mulcst;
155 boolean_t old_all_mulcst;
156 boolean_t old_brdcst;
159 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
160 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
162 old_all_unicst = epp->ep_all_unicst;
163 old_mulcst = epp->ep_mulcst;
164 old_all_mulcst = epp->ep_all_mulcst;
165 old_brdcst = epp->ep_brdcst;
167 epp->ep_all_unicst = all_unicst;
168 epp->ep_mulcst = mulcst;
169 epp->ep_all_mulcst = all_mulcst;
170 epp->ep_brdcst = brdcst;
172 if ((rc = emop->emo_reconfigure(enp)) != 0)
178 EFSYS_PROBE1(fail1, efx_rc_t, rc);
180 epp->ep_all_unicst = old_all_unicst;
181 epp->ep_mulcst = old_mulcst;
182 epp->ep_all_mulcst = old_all_mulcst;
183 epp->ep_brdcst = old_brdcst;
188 __checkReturn efx_rc_t
191 __in boolean_t enabled)
193 efx_port_t *epp = &(enp->en_port);
194 const efx_mac_ops_t *emop = epp->ep_emop;
197 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
198 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
199 EFSYS_ASSERT(emop != NULL);
201 if (epp->ep_mac_drain == enabled)
204 epp->ep_mac_drain = enabled;
206 if ((rc = emop->emo_reconfigure(enp)) != 0)
212 EFSYS_PROBE1(fail1, efx_rc_t, rc);
217 __checkReturn efx_rc_t
220 __out boolean_t *mac_upp)
222 efx_port_t *epp = &(enp->en_port);
223 const efx_mac_ops_t *emop = epp->ep_emop;
226 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
227 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
229 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
235 EFSYS_PROBE1(fail1, efx_rc_t, rc);
240 __checkReturn efx_rc_t
243 __in unsigned int fcntl,
244 __in boolean_t autoneg)
246 efx_port_t *epp = &(enp->en_port);
247 const efx_mac_ops_t *emop = epp->ep_emop;
248 const efx_phy_ops_t *epop = epp->ep_epop;
249 unsigned int old_fcntl;
250 boolean_t old_autoneg;
251 unsigned int old_adv_cap;
254 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
255 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
257 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
263 * Ignore a request to set flow control auto-negotiation
264 * if the PHY doesn't support it.
266 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
269 old_fcntl = epp->ep_fcntl;
270 old_autoneg = epp->ep_fcntl_autoneg;
271 old_adv_cap = epp->ep_adv_cap_mask;
273 epp->ep_fcntl = fcntl;
274 epp->ep_fcntl_autoneg = autoneg;
277 * Always encode the flow control settings in the advertised
278 * capabilities even if we are not trying to auto-negotiate
279 * them and reconfigure both the PHY and the MAC.
281 if (fcntl & EFX_FCNTL_RESPOND)
282 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
283 1 << EFX_PHY_CAP_ASYM);
285 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
286 1 << EFX_PHY_CAP_ASYM);
288 if (fcntl & EFX_FCNTL_GENERATE)
289 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
291 if ((rc = epop->epo_reconfigure(enp)) != 0)
294 if ((rc = emop->emo_reconfigure(enp)) != 0)
305 epp->ep_fcntl = old_fcntl;
306 epp->ep_fcntl_autoneg = old_autoneg;
307 epp->ep_adv_cap_mask = old_adv_cap;
310 EFSYS_PROBE1(fail1, efx_rc_t, rc);
318 __out unsigned int *fcntl_wantedp,
319 __out unsigned int *fcntl_linkp)
321 efx_port_t *epp = &(enp->en_port);
322 unsigned int wanted = 0;
324 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
325 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
328 * Decode the requested flow control settings from the PHY
329 * advertised capabilities.
331 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
332 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
333 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
334 wanted ^= EFX_FCNTL_GENERATE;
336 *fcntl_linkp = epp->ep_fcntl;
337 *fcntl_wantedp = wanted;
340 __checkReturn efx_rc_t
341 efx_mac_multicast_list_set(
343 __in_ecount(6*count) uint8_t const *addrs,
346 efx_port_t *epp = &(enp->en_port);
347 const efx_mac_ops_t *emop = epp->ep_emop;
348 uint8_t *old_mulcst_addr_list = NULL;
349 uint32_t old_mulcst_addr_count;
352 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
353 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
355 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
360 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
361 if (old_mulcst_addr_count > 0) {
362 /* Allocate memory to store old list (instead of using stack) */
363 EFSYS_KMEM_ALLOC(enp->en_esip,
364 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
365 old_mulcst_addr_list);
366 if (old_mulcst_addr_list == NULL) {
371 /* Save the old list in case we need to rollback */
372 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
373 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
376 /* Store the new list */
377 memcpy(epp->ep_mulcst_addr_list, addrs,
378 count * EFX_MAC_ADDR_LEN);
379 epp->ep_mulcst_addr_count = count;
381 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
384 if (old_mulcst_addr_count > 0) {
385 EFSYS_KMEM_FREE(enp->en_esip,
386 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
387 old_mulcst_addr_list);
395 /* Restore original list on failure */
396 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
397 if (old_mulcst_addr_count > 0) {
398 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
399 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
401 EFSYS_KMEM_FREE(enp->en_esip,
402 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
403 old_mulcst_addr_list);
410 EFSYS_PROBE1(fail1, efx_rc_t, rc);
416 __checkReturn efx_rc_t
417 efx_mac_filter_default_rxq_set(
420 __in boolean_t using_rss)
422 efx_port_t *epp = &(enp->en_port);
423 const efx_mac_ops_t *emop = epp->ep_emop;
426 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
427 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
429 if (emop->emo_filter_default_rxq_set != NULL) {
430 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
444 efx_mac_filter_default_rxq_clear(
447 efx_port_t *epp = &(enp->en_port);
448 const efx_mac_ops_t *emop = epp->ep_emop;
450 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
451 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
453 if (emop->emo_filter_default_rxq_clear != NULL)
454 emop->emo_filter_default_rxq_clear(enp);
458 __checkReturn efx_rc_t
462 efx_port_t *epp = &(enp->en_port);
463 efx_mac_type_t type = EFX_MAC_INVALID;
464 const efx_mac_ops_t *emop;
467 switch (enp->en_family) {
474 EFSYS_ASSERT(type != EFX_MAC_INVALID);
475 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
476 EFSYS_ASSERT(emop != NULL);
479 epp->ep_mac_type = type;
484 EFSYS_PROBE1(fail1, efx_rc_t, rc);