15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko *
3672386c1SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko * Copyright(c) 2007-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko */
65e111ed8SAndrew Rybchenko
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko
105e111ed8SAndrew Rybchenko
115e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_family(__in uint16_t venid,__in uint16_t devid,__out efx_family_t * efp,__out unsigned int * membarp)125e111ed8SAndrew Rybchenko efx_family(
135e111ed8SAndrew Rybchenko __in uint16_t venid,
145e111ed8SAndrew Rybchenko __in uint16_t devid,
155e111ed8SAndrew Rybchenko __out efx_family_t *efp,
165e111ed8SAndrew Rybchenko __out unsigned int *membarp)
175e111ed8SAndrew Rybchenko {
185e111ed8SAndrew Rybchenko if (venid == EFX_PCI_VENID_SFC) {
195e111ed8SAndrew Rybchenko switch (devid) {
205e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
215e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_SIENA_F1_UNINIT:
225e111ed8SAndrew Rybchenko /*
235e111ed8SAndrew Rybchenko * Hardware default for PF0 of uninitialised Siena.
245e111ed8SAndrew Rybchenko * manftest must be able to cope with this device id.
255e111ed8SAndrew Rybchenko */
265e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_BETHPAGE:
275e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_SIENA:
285e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_SIENA;
295e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_SIENA;
305e111ed8SAndrew Rybchenko return (0);
315e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
325e111ed8SAndrew Rybchenko
335e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
345e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
355e111ed8SAndrew Rybchenko /*
365e111ed8SAndrew Rybchenko * Hardware default for PF0 of uninitialised Huntington.
375e111ed8SAndrew Rybchenko * manftest must be able to cope with this device id.
385e111ed8SAndrew Rybchenko */
395e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_FARMINGDALE:
405e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_GREENPORT:
415e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_HUNTINGTON;
425e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_HUNTINGTON_PF;
435e111ed8SAndrew Rybchenko return (0);
445e111ed8SAndrew Rybchenko
455e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_FARMINGDALE_VF:
465e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_GREENPORT_VF:
475e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_HUNTINGTON;
485e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_HUNTINGTON_VF;
495e111ed8SAndrew Rybchenko return (0);
505e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
515e111ed8SAndrew Rybchenko
525e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
535e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
545e111ed8SAndrew Rybchenko /*
555e111ed8SAndrew Rybchenko * Hardware default for PF0 of uninitialised Medford.
565e111ed8SAndrew Rybchenko * manftest must be able to cope with this device id.
575e111ed8SAndrew Rybchenko */
585e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD:
595e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_MEDFORD;
605e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_MEDFORD_PF;
615e111ed8SAndrew Rybchenko return (0);
625e111ed8SAndrew Rybchenko
635e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD_VF:
645e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_MEDFORD;
655e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_MEDFORD_VF;
665e111ed8SAndrew Rybchenko return (0);
675e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
685e111ed8SAndrew Rybchenko
695e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
705e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT:
715e111ed8SAndrew Rybchenko /*
725e111ed8SAndrew Rybchenko * Hardware default for PF0 of uninitialised Medford2.
735e111ed8SAndrew Rybchenko * manftest must be able to cope with this device id.
745e111ed8SAndrew Rybchenko */
755e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD2:
765e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_MEDFORD2_VF:
775e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_MEDFORD2;
785e111ed8SAndrew Rybchenko *membarp = EFX_MEM_BAR_MEDFORD2;
795e111ed8SAndrew Rybchenko return (0);
805e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
815e111ed8SAndrew Rybchenko
825e111ed8SAndrew Rybchenko case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */
835e111ed8SAndrew Rybchenko default:
845e111ed8SAndrew Rybchenko break;
855e111ed8SAndrew Rybchenko }
865e111ed8SAndrew Rybchenko }
875e111ed8SAndrew Rybchenko
88206ef24fSAndrew Rybchenko if (venid == EFX_PCI_VENID_XILINX) {
89206ef24fSAndrew Rybchenko switch (devid) {
90206ef24fSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
91206ef24fSAndrew Rybchenko case EFX_PCI_DEVID_RIVERHEAD:
92206ef24fSAndrew Rybchenko case EFX_PCI_DEVID_RIVERHEAD_VF:
93206ef24fSAndrew Rybchenko *efp = EFX_FAMILY_RIVERHEAD;
94206ef24fSAndrew Rybchenko *membarp = EFX_MEM_BAR_RIVERHEAD;
95206ef24fSAndrew Rybchenko return (0);
96206ef24fSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
97206ef24fSAndrew Rybchenko default:
98206ef24fSAndrew Rybchenko break;
99206ef24fSAndrew Rybchenko }
100206ef24fSAndrew Rybchenko }
101206ef24fSAndrew Rybchenko
1025e111ed8SAndrew Rybchenko *efp = EFX_FAMILY_INVALID;
1035e111ed8SAndrew Rybchenko return (ENOTSUP);
1045e111ed8SAndrew Rybchenko }
1055e111ed8SAndrew Rybchenko
106a45edfceSIgor Romanov #if EFSYS_OPT_PCI
107a45edfceSIgor Romanov
108a45edfceSIgor Romanov __checkReturn efx_rc_t
efx_family_probe_bar(__in uint16_t venid,__in uint16_t devid,__in efsys_pci_config_t * espcp,__in const efx_pci_ops_t * epop,__out efx_family_t * efp,__out efx_bar_region_t * ebrp)109a45edfceSIgor Romanov efx_family_probe_bar(
110a45edfceSIgor Romanov __in uint16_t venid,
111a45edfceSIgor Romanov __in uint16_t devid,
112a45edfceSIgor Romanov __in efsys_pci_config_t *espcp,
11307999984SIgor Romanov __in const efx_pci_ops_t *epop,
114a45edfceSIgor Romanov __out efx_family_t *efp,
115a45edfceSIgor Romanov __out efx_bar_region_t *ebrp)
116a45edfceSIgor Romanov {
117a45edfceSIgor Romanov efx_rc_t rc;
118a45edfceSIgor Romanov unsigned int membar;
119a45edfceSIgor Romanov
120a45edfceSIgor Romanov if (venid == EFX_PCI_VENID_XILINX) {
121a45edfceSIgor Romanov switch (devid) {
122a45edfceSIgor Romanov #if EFSYS_OPT_RIVERHEAD
123a45edfceSIgor Romanov case EFX_PCI_DEVID_RIVERHEAD:
124a45edfceSIgor Romanov case EFX_PCI_DEVID_RIVERHEAD_VF:
12507999984SIgor Romanov rc = rhead_pci_nic_membar_lookup(espcp, epop, ebrp);
126a45edfceSIgor Romanov if (rc == 0)
127a45edfceSIgor Romanov *efp = EFX_FAMILY_RIVERHEAD;
128a45edfceSIgor Romanov
129a45edfceSIgor Romanov return (rc);
130a45edfceSIgor Romanov #endif /* EFSYS_OPT_RIVERHEAD */
131a45edfceSIgor Romanov default:
132a45edfceSIgor Romanov break;
133a45edfceSIgor Romanov }
134a45edfceSIgor Romanov }
135a45edfceSIgor Romanov
136a45edfceSIgor Romanov rc = efx_family(venid, devid, efp, &membar);
137a45edfceSIgor Romanov if (rc == 0) {
138a45edfceSIgor Romanov ebrp->ebr_type = EFX_BAR_TYPE_MEM;
139a45edfceSIgor Romanov ebrp->ebr_index = membar;
140a45edfceSIgor Romanov ebrp->ebr_offset = 0;
141a45edfceSIgor Romanov ebrp->ebr_length = 0;
142a45edfceSIgor Romanov }
143a45edfceSIgor Romanov
144a45edfceSIgor Romanov return (rc);
145a45edfceSIgor Romanov }
146a45edfceSIgor Romanov
147a45edfceSIgor Romanov #endif /* EFSYS_OPT_PCI */
1485e111ed8SAndrew Rybchenko
1495e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
1505e111ed8SAndrew Rybchenko
1515e111ed8SAndrew Rybchenko static const efx_nic_ops_t __efx_nic_siena_ops = {
1525e111ed8SAndrew Rybchenko siena_nic_probe, /* eno_probe */
1535e111ed8SAndrew Rybchenko NULL, /* eno_board_cfg */
1545e111ed8SAndrew Rybchenko NULL, /* eno_set_drv_limits */
1555e111ed8SAndrew Rybchenko siena_nic_reset, /* eno_reset */
1565e111ed8SAndrew Rybchenko siena_nic_init, /* eno_init */
1575e111ed8SAndrew Rybchenko NULL, /* eno_get_vi_pool */
1585e111ed8SAndrew Rybchenko NULL, /* eno_get_bar_region */
1595e111ed8SAndrew Rybchenko NULL, /* eno_hw_unavailable */
1605e111ed8SAndrew Rybchenko NULL, /* eno_set_hw_unavailable */
1615e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
1625e111ed8SAndrew Rybchenko siena_nic_register_test, /* eno_register_test */
1635e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
1645e111ed8SAndrew Rybchenko siena_nic_fini, /* eno_fini */
1655e111ed8SAndrew Rybchenko siena_nic_unprobe, /* eno_unprobe */
1665e111ed8SAndrew Rybchenko };
1675e111ed8SAndrew Rybchenko
1685e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
1695e111ed8SAndrew Rybchenko
1705e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1715e111ed8SAndrew Rybchenko
1725e111ed8SAndrew Rybchenko static const efx_nic_ops_t __efx_nic_hunt_ops = {
1735e111ed8SAndrew Rybchenko ef10_nic_probe, /* eno_probe */
1745e111ed8SAndrew Rybchenko hunt_board_cfg, /* eno_board_cfg */
1755e111ed8SAndrew Rybchenko ef10_nic_set_drv_limits, /* eno_set_drv_limits */
1765e111ed8SAndrew Rybchenko ef10_nic_reset, /* eno_reset */
1775e111ed8SAndrew Rybchenko ef10_nic_init, /* eno_init */
1785e111ed8SAndrew Rybchenko ef10_nic_get_vi_pool, /* eno_get_vi_pool */
1795e111ed8SAndrew Rybchenko ef10_nic_get_bar_region, /* eno_get_bar_region */
1805e111ed8SAndrew Rybchenko ef10_nic_hw_unavailable, /* eno_hw_unavailable */
1815e111ed8SAndrew Rybchenko ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */
1825e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
1835e111ed8SAndrew Rybchenko ef10_nic_register_test, /* eno_register_test */
1845e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
1855e111ed8SAndrew Rybchenko ef10_nic_fini, /* eno_fini */
1865e111ed8SAndrew Rybchenko ef10_nic_unprobe, /* eno_unprobe */
1875e111ed8SAndrew Rybchenko };
1885e111ed8SAndrew Rybchenko
1895e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
1905e111ed8SAndrew Rybchenko
1915e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
1925e111ed8SAndrew Rybchenko
1935e111ed8SAndrew Rybchenko static const efx_nic_ops_t __efx_nic_medford_ops = {
1945e111ed8SAndrew Rybchenko ef10_nic_probe, /* eno_probe */
1955e111ed8SAndrew Rybchenko medford_board_cfg, /* eno_board_cfg */
1965e111ed8SAndrew Rybchenko ef10_nic_set_drv_limits, /* eno_set_drv_limits */
1975e111ed8SAndrew Rybchenko ef10_nic_reset, /* eno_reset */
1985e111ed8SAndrew Rybchenko ef10_nic_init, /* eno_init */
1995e111ed8SAndrew Rybchenko ef10_nic_get_vi_pool, /* eno_get_vi_pool */
2005e111ed8SAndrew Rybchenko ef10_nic_get_bar_region, /* eno_get_bar_region */
2015e111ed8SAndrew Rybchenko ef10_nic_hw_unavailable, /* eno_hw_unavailable */
2025e111ed8SAndrew Rybchenko ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */
2035e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
2045e111ed8SAndrew Rybchenko ef10_nic_register_test, /* eno_register_test */
2055e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
2065e111ed8SAndrew Rybchenko ef10_nic_fini, /* eno_fini */
2075e111ed8SAndrew Rybchenko ef10_nic_unprobe, /* eno_unprobe */
2085e111ed8SAndrew Rybchenko };
2095e111ed8SAndrew Rybchenko
2105e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
2115e111ed8SAndrew Rybchenko
2125e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
2135e111ed8SAndrew Rybchenko
2145e111ed8SAndrew Rybchenko static const efx_nic_ops_t __efx_nic_medford2_ops = {
2155e111ed8SAndrew Rybchenko ef10_nic_probe, /* eno_probe */
2165e111ed8SAndrew Rybchenko medford2_board_cfg, /* eno_board_cfg */
2175e111ed8SAndrew Rybchenko ef10_nic_set_drv_limits, /* eno_set_drv_limits */
2185e111ed8SAndrew Rybchenko ef10_nic_reset, /* eno_reset */
2195e111ed8SAndrew Rybchenko ef10_nic_init, /* eno_init */
2205e111ed8SAndrew Rybchenko ef10_nic_get_vi_pool, /* eno_get_vi_pool */
2215e111ed8SAndrew Rybchenko ef10_nic_get_bar_region, /* eno_get_bar_region */
2225e111ed8SAndrew Rybchenko ef10_nic_hw_unavailable, /* eno_hw_unavailable */
2235e111ed8SAndrew Rybchenko ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */
2245e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
2255e111ed8SAndrew Rybchenko ef10_nic_register_test, /* eno_register_test */
2265e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
2275e111ed8SAndrew Rybchenko ef10_nic_fini, /* eno_fini */
2285e111ed8SAndrew Rybchenko ef10_nic_unprobe, /* eno_unprobe */
2295e111ed8SAndrew Rybchenko };
2305e111ed8SAndrew Rybchenko
2315e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
2325e111ed8SAndrew Rybchenko
2333c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
2343c1c5cc4SAndrew Rybchenko
2353c1c5cc4SAndrew Rybchenko static const efx_nic_ops_t __efx_nic_riverhead_ops = {
2363c1c5cc4SAndrew Rybchenko rhead_nic_probe, /* eno_probe */
2373c1c5cc4SAndrew Rybchenko rhead_board_cfg, /* eno_board_cfg */
2383c1c5cc4SAndrew Rybchenko rhead_nic_set_drv_limits, /* eno_set_drv_limits */
2393c1c5cc4SAndrew Rybchenko rhead_nic_reset, /* eno_reset */
2403c1c5cc4SAndrew Rybchenko rhead_nic_init, /* eno_init */
2413c1c5cc4SAndrew Rybchenko rhead_nic_get_vi_pool, /* eno_get_vi_pool */
2423c1c5cc4SAndrew Rybchenko rhead_nic_get_bar_region, /* eno_get_bar_region */
2433c1c5cc4SAndrew Rybchenko rhead_nic_hw_unavailable, /* eno_hw_unavailable */
2443c1c5cc4SAndrew Rybchenko rhead_nic_set_hw_unavailable, /* eno_set_hw_unavailable */
2453c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_DIAG
2463c1c5cc4SAndrew Rybchenko rhead_nic_register_test, /* eno_register_test */
2473c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
2483c1c5cc4SAndrew Rybchenko rhead_nic_fini, /* eno_fini */
2493c1c5cc4SAndrew Rybchenko rhead_nic_unprobe, /* eno_unprobe */
2503c1c5cc4SAndrew Rybchenko };
2513c1c5cc4SAndrew Rybchenko
2523c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
2533c1c5cc4SAndrew Rybchenko
2545e111ed8SAndrew Rybchenko
2555e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_create(__in efx_family_t family,__in efsys_identifier_t * esip,__in efsys_bar_t * esbp,__in uint32_t fcw_offset,__in efsys_lock_t * eslp,__deref_out efx_nic_t ** enpp)2565e111ed8SAndrew Rybchenko efx_nic_create(
2575e111ed8SAndrew Rybchenko __in efx_family_t family,
2585e111ed8SAndrew Rybchenko __in efsys_identifier_t *esip,
2595e111ed8SAndrew Rybchenko __in efsys_bar_t *esbp,
260341bd4e0SIgor Romanov __in uint32_t fcw_offset,
2615e111ed8SAndrew Rybchenko __in efsys_lock_t *eslp,
2625e111ed8SAndrew Rybchenko __deref_out efx_nic_t **enpp)
2635e111ed8SAndrew Rybchenko {
2645e111ed8SAndrew Rybchenko efx_nic_t *enp;
2655e111ed8SAndrew Rybchenko efx_rc_t rc;
2665e111ed8SAndrew Rybchenko
2675e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
2685e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
2695e111ed8SAndrew Rybchenko
2705e111ed8SAndrew Rybchenko /* Allocate a NIC object */
2715e111ed8SAndrew Rybchenko EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
2725e111ed8SAndrew Rybchenko
2735e111ed8SAndrew Rybchenko if (enp == NULL) {
2745e111ed8SAndrew Rybchenko rc = ENOMEM;
2755e111ed8SAndrew Rybchenko goto fail1;
2765e111ed8SAndrew Rybchenko }
2775e111ed8SAndrew Rybchenko
2785e111ed8SAndrew Rybchenko enp->en_magic = EFX_NIC_MAGIC;
2795e111ed8SAndrew Rybchenko
2805e111ed8SAndrew Rybchenko switch (family) {
2815e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
2825e111ed8SAndrew Rybchenko case EFX_FAMILY_SIENA:
2835e111ed8SAndrew Rybchenko enp->en_enop = &__efx_nic_siena_ops;
2845e111ed8SAndrew Rybchenko enp->en_features =
2855e111ed8SAndrew Rybchenko EFX_FEATURE_IPV6 |
2865e111ed8SAndrew Rybchenko EFX_FEATURE_LFSR_HASH_INSERT |
2875e111ed8SAndrew Rybchenko EFX_FEATURE_LINK_EVENTS |
2885e111ed8SAndrew Rybchenko EFX_FEATURE_PERIODIC_MAC_STATS |
2895e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI |
2905e111ed8SAndrew Rybchenko EFX_FEATURE_LOOKAHEAD_SPLIT |
2915e111ed8SAndrew Rybchenko EFX_FEATURE_MAC_HEADER_FILTERS |
2925e111ed8SAndrew Rybchenko EFX_FEATURE_TX_SRC_FILTERS;
2935e111ed8SAndrew Rybchenko break;
2945e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
2955e111ed8SAndrew Rybchenko
2965e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
2975e111ed8SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
2985e111ed8SAndrew Rybchenko enp->en_enop = &__efx_nic_hunt_ops;
2995e111ed8SAndrew Rybchenko enp->en_features =
3005e111ed8SAndrew Rybchenko EFX_FEATURE_IPV6 |
3015e111ed8SAndrew Rybchenko EFX_FEATURE_LINK_EVENTS |
3025e111ed8SAndrew Rybchenko EFX_FEATURE_PERIODIC_MAC_STATS |
3035e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI |
3045e111ed8SAndrew Rybchenko EFX_FEATURE_MAC_HEADER_FILTERS |
3055e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI_DMA |
3065e111ed8SAndrew Rybchenko EFX_FEATURE_PIO_BUFFERS |
3075e111ed8SAndrew Rybchenko EFX_FEATURE_FW_ASSISTED_TSO |
3085e111ed8SAndrew Rybchenko EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3095e111ed8SAndrew Rybchenko EFX_FEATURE_PACKED_STREAM |
3105e111ed8SAndrew Rybchenko EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3115e111ed8SAndrew Rybchenko break;
3125e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
3135e111ed8SAndrew Rybchenko
3145e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
3155e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
3165e111ed8SAndrew Rybchenko enp->en_enop = &__efx_nic_medford_ops;
3175e111ed8SAndrew Rybchenko /*
3185e111ed8SAndrew Rybchenko * FW_ASSISTED_TSO omitted as Medford only supports firmware
3195e111ed8SAndrew Rybchenko * assisted TSO version 2, not the v1 scheme used on Huntington.
3205e111ed8SAndrew Rybchenko */
3215e111ed8SAndrew Rybchenko enp->en_features =
3225e111ed8SAndrew Rybchenko EFX_FEATURE_IPV6 |
3235e111ed8SAndrew Rybchenko EFX_FEATURE_LINK_EVENTS |
3245e111ed8SAndrew Rybchenko EFX_FEATURE_PERIODIC_MAC_STATS |
3255e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI |
3265e111ed8SAndrew Rybchenko EFX_FEATURE_MAC_HEADER_FILTERS |
3275e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI_DMA |
3285e111ed8SAndrew Rybchenko EFX_FEATURE_PIO_BUFFERS |
3295e111ed8SAndrew Rybchenko EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3305e111ed8SAndrew Rybchenko EFX_FEATURE_PACKED_STREAM |
3315e111ed8SAndrew Rybchenko EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3325e111ed8SAndrew Rybchenko break;
3335e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
3345e111ed8SAndrew Rybchenko
3355e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
3365e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
3375e111ed8SAndrew Rybchenko enp->en_enop = &__efx_nic_medford2_ops;
3385e111ed8SAndrew Rybchenko enp->en_features =
3395e111ed8SAndrew Rybchenko EFX_FEATURE_IPV6 |
3405e111ed8SAndrew Rybchenko EFX_FEATURE_LINK_EVENTS |
3415e111ed8SAndrew Rybchenko EFX_FEATURE_PERIODIC_MAC_STATS |
3425e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI |
3435e111ed8SAndrew Rybchenko EFX_FEATURE_MAC_HEADER_FILTERS |
3445e111ed8SAndrew Rybchenko EFX_FEATURE_MCDI_DMA |
3455e111ed8SAndrew Rybchenko EFX_FEATURE_PIO_BUFFERS |
3465e111ed8SAndrew Rybchenko EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3475e111ed8SAndrew Rybchenko EFX_FEATURE_PACKED_STREAM |
3485e111ed8SAndrew Rybchenko EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3495e111ed8SAndrew Rybchenko break;
3505e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
3515e111ed8SAndrew Rybchenko
3523c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
3533c1c5cc4SAndrew Rybchenko case EFX_FAMILY_RIVERHEAD:
3543c1c5cc4SAndrew Rybchenko enp->en_enop = &__efx_nic_riverhead_ops;
3553c1c5cc4SAndrew Rybchenko enp->en_features =
3563c1c5cc4SAndrew Rybchenko EFX_FEATURE_IPV6 |
3573c1c5cc4SAndrew Rybchenko EFX_FEATURE_LINK_EVENTS |
3583c1c5cc4SAndrew Rybchenko EFX_FEATURE_PERIODIC_MAC_STATS |
3593c1c5cc4SAndrew Rybchenko EFX_FEATURE_MCDI |
3603c1c5cc4SAndrew Rybchenko EFX_FEATURE_MAC_HEADER_FILTERS |
3613c1c5cc4SAndrew Rybchenko EFX_FEATURE_MCDI_DMA;
362341bd4e0SIgor Romanov enp->en_arch.ef10.ena_fcw_base = fcw_offset;
3633c1c5cc4SAndrew Rybchenko break;
3643c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
3653c1c5cc4SAndrew Rybchenko
3665e111ed8SAndrew Rybchenko default:
3675e111ed8SAndrew Rybchenko rc = ENOTSUP;
3685e111ed8SAndrew Rybchenko goto fail2;
3695e111ed8SAndrew Rybchenko }
3705e111ed8SAndrew Rybchenko
371341bd4e0SIgor Romanov if ((family != EFX_FAMILY_RIVERHEAD) && (fcw_offset != 0)) {
372341bd4e0SIgor Romanov rc = EINVAL;
373341bd4e0SIgor Romanov goto fail3;
374341bd4e0SIgor Romanov }
375341bd4e0SIgor Romanov
3765e111ed8SAndrew Rybchenko enp->en_family = family;
3775e111ed8SAndrew Rybchenko enp->en_esip = esip;
3785e111ed8SAndrew Rybchenko enp->en_esbp = esbp;
3795e111ed8SAndrew Rybchenko enp->en_eslp = eslp;
3805e111ed8SAndrew Rybchenko
3815e111ed8SAndrew Rybchenko *enpp = enp;
3825e111ed8SAndrew Rybchenko
3835e111ed8SAndrew Rybchenko return (0);
3845e111ed8SAndrew Rybchenko
385341bd4e0SIgor Romanov fail3:
386341bd4e0SIgor Romanov EFSYS_PROBE(fail3);
3875e111ed8SAndrew Rybchenko fail2:
3885e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
3895e111ed8SAndrew Rybchenko
3905e111ed8SAndrew Rybchenko enp->en_magic = 0;
3915e111ed8SAndrew Rybchenko
3925e111ed8SAndrew Rybchenko /* Free the NIC object */
3935e111ed8SAndrew Rybchenko EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
3945e111ed8SAndrew Rybchenko
3955e111ed8SAndrew Rybchenko fail1:
3965e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3975e111ed8SAndrew Rybchenko
3985e111ed8SAndrew Rybchenko return (rc);
3995e111ed8SAndrew Rybchenko }
4005e111ed8SAndrew Rybchenko
4015e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_probe(__in efx_nic_t * enp,__in efx_fw_variant_t efv)4025e111ed8SAndrew Rybchenko efx_nic_probe(
4035e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
4045e111ed8SAndrew Rybchenko __in efx_fw_variant_t efv)
4055e111ed8SAndrew Rybchenko {
406538fd2acSAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
4075e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop;
4085e111ed8SAndrew Rybchenko efx_rc_t rc;
4095e111ed8SAndrew Rybchenko
4105e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4115e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI
4125e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
4135e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MCDI */
4145e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
4155e111ed8SAndrew Rybchenko
4165e111ed8SAndrew Rybchenko /* Ensure FW variant codes match with MC_CMD_FW codes */
4175e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_FULL_FEATURED ==
4185e111ed8SAndrew Rybchenko MC_CMD_FW_FULL_FEATURED);
4195e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_LOW_LATENCY ==
4205e111ed8SAndrew Rybchenko MC_CMD_FW_LOW_LATENCY);
4215e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM ==
4225e111ed8SAndrew Rybchenko MC_CMD_FW_PACKED_STREAM);
4235e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_HIGH_TX_RATE ==
4245e111ed8SAndrew Rybchenko MC_CMD_FW_HIGH_TX_RATE);
4255e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM_HASH_MODE_1 ==
4265e111ed8SAndrew Rybchenko MC_CMD_FW_PACKED_STREAM_HASH_MODE_1);
4275e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_RULES_ENGINE ==
4285e111ed8SAndrew Rybchenko MC_CMD_FW_RULES_ENGINE);
4295e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_DPDK ==
4305e111ed8SAndrew Rybchenko MC_CMD_FW_DPDK);
4315e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_FW_VARIANT_DONT_CARE ==
4325e111ed8SAndrew Rybchenko (int)MC_CMD_FW_DONT_CARE);
4335e111ed8SAndrew Rybchenko
4345e111ed8SAndrew Rybchenko enop = enp->en_enop;
4355e111ed8SAndrew Rybchenko enp->efv = efv;
4365e111ed8SAndrew Rybchenko
4375e111ed8SAndrew Rybchenko if ((rc = enop->eno_probe(enp)) != 0)
4385e111ed8SAndrew Rybchenko goto fail1;
4395e111ed8SAndrew Rybchenko
440538fd2acSAndrew Rybchenko encp->enc_features = enp->en_features;
441538fd2acSAndrew Rybchenko
4425e111ed8SAndrew Rybchenko if ((rc = efx_phy_probe(enp)) != 0)
4435e111ed8SAndrew Rybchenko goto fail2;
4445e111ed8SAndrew Rybchenko
4455e111ed8SAndrew Rybchenko enp->en_mod_flags |= EFX_MOD_PROBE;
4465e111ed8SAndrew Rybchenko
4475e111ed8SAndrew Rybchenko return (0);
4485e111ed8SAndrew Rybchenko
4495e111ed8SAndrew Rybchenko fail2:
4505e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
4515e111ed8SAndrew Rybchenko
4525e111ed8SAndrew Rybchenko enop->eno_unprobe(enp);
4535e111ed8SAndrew Rybchenko
4545e111ed8SAndrew Rybchenko fail1:
4555e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4565e111ed8SAndrew Rybchenko
4575e111ed8SAndrew Rybchenko return (rc);
4585e111ed8SAndrew Rybchenko }
4595e111ed8SAndrew Rybchenko
4605e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)4615e111ed8SAndrew Rybchenko efx_nic_set_drv_limits(
4625e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
4635e111ed8SAndrew Rybchenko __in efx_drv_limits_t *edlp)
4645e111ed8SAndrew Rybchenko {
4655e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
4665e111ed8SAndrew Rybchenko efx_rc_t rc;
4675e111ed8SAndrew Rybchenko
4685e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4695e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
4705e111ed8SAndrew Rybchenko
4715e111ed8SAndrew Rybchenko if (enop->eno_set_drv_limits != NULL) {
4725e111ed8SAndrew Rybchenko if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
4735e111ed8SAndrew Rybchenko goto fail1;
4745e111ed8SAndrew Rybchenko }
4755e111ed8SAndrew Rybchenko
4765e111ed8SAndrew Rybchenko return (0);
4775e111ed8SAndrew Rybchenko
4785e111ed8SAndrew Rybchenko fail1:
4795e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4805e111ed8SAndrew Rybchenko
4815e111ed8SAndrew Rybchenko return (rc);
4825e111ed8SAndrew Rybchenko }
4835e111ed8SAndrew Rybchenko
4845e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_set_drv_version(__inout efx_nic_t * enp,__in_ecount (length)char const * verp,__in size_t length)4855e111ed8SAndrew Rybchenko efx_nic_set_drv_version(
4865e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
4875e111ed8SAndrew Rybchenko __in_ecount(length) char const *verp,
4885e111ed8SAndrew Rybchenko __in size_t length)
4895e111ed8SAndrew Rybchenko {
4905e111ed8SAndrew Rybchenko efx_rc_t rc;
4915e111ed8SAndrew Rybchenko
4925e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4935e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
4945e111ed8SAndrew Rybchenko
4955e111ed8SAndrew Rybchenko /*
4965e111ed8SAndrew Rybchenko * length is the string content length in bytes.
4975e111ed8SAndrew Rybchenko * Accept any content which fits into the version
4985e111ed8SAndrew Rybchenko * buffer, excluding the last byte. This is reserved
4995e111ed8SAndrew Rybchenko * for an appended NUL terminator.
5005e111ed8SAndrew Rybchenko */
5015e111ed8SAndrew Rybchenko if (length >= sizeof (enp->en_drv_version)) {
5025e111ed8SAndrew Rybchenko rc = E2BIG;
5035e111ed8SAndrew Rybchenko goto fail1;
5045e111ed8SAndrew Rybchenko }
5055e111ed8SAndrew Rybchenko
5065e111ed8SAndrew Rybchenko (void) memset(enp->en_drv_version, 0,
5075e111ed8SAndrew Rybchenko sizeof (enp->en_drv_version));
5085e111ed8SAndrew Rybchenko memcpy(enp->en_drv_version, verp, length);
5095e111ed8SAndrew Rybchenko
5105e111ed8SAndrew Rybchenko return (0);
5115e111ed8SAndrew Rybchenko
5125e111ed8SAndrew Rybchenko fail1:
5135e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5145e111ed8SAndrew Rybchenko
5155e111ed8SAndrew Rybchenko return (rc);
5165e111ed8SAndrew Rybchenko }
5175e111ed8SAndrew Rybchenko
5185e111ed8SAndrew Rybchenko
5195e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_get_bar_region(__in efx_nic_t * enp,__in efx_nic_region_t region,__out uint32_t * offsetp,__out size_t * sizep)5205e111ed8SAndrew Rybchenko efx_nic_get_bar_region(
5215e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5225e111ed8SAndrew Rybchenko __in efx_nic_region_t region,
5235e111ed8SAndrew Rybchenko __out uint32_t *offsetp,
5245e111ed8SAndrew Rybchenko __out size_t *sizep)
5255e111ed8SAndrew Rybchenko {
5265e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
5275e111ed8SAndrew Rybchenko efx_rc_t rc;
5285e111ed8SAndrew Rybchenko
5295e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5305e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
5315e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
5325e111ed8SAndrew Rybchenko
5335e111ed8SAndrew Rybchenko if (enop->eno_get_bar_region == NULL) {
5345e111ed8SAndrew Rybchenko rc = ENOTSUP;
5355e111ed8SAndrew Rybchenko goto fail1;
5365e111ed8SAndrew Rybchenko }
5375e111ed8SAndrew Rybchenko if ((rc = (enop->eno_get_bar_region)(enp,
5385e111ed8SAndrew Rybchenko region, offsetp, sizep)) != 0) {
5395e111ed8SAndrew Rybchenko goto fail2;
5405e111ed8SAndrew Rybchenko }
5415e111ed8SAndrew Rybchenko
5425e111ed8SAndrew Rybchenko return (0);
5435e111ed8SAndrew Rybchenko
5445e111ed8SAndrew Rybchenko fail2:
5455e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5465e111ed8SAndrew Rybchenko
5475e111ed8SAndrew Rybchenko fail1:
5485e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5495e111ed8SAndrew Rybchenko
5505e111ed8SAndrew Rybchenko return (rc);
5515e111ed8SAndrew Rybchenko }
5525e111ed8SAndrew Rybchenko
5535e111ed8SAndrew Rybchenko
5545e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * evq_countp,__out uint32_t * rxq_countp,__out uint32_t * txq_countp)5555e111ed8SAndrew Rybchenko efx_nic_get_vi_pool(
5565e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5575e111ed8SAndrew Rybchenko __out uint32_t *evq_countp,
5585e111ed8SAndrew Rybchenko __out uint32_t *rxq_countp,
5595e111ed8SAndrew Rybchenko __out uint32_t *txq_countp)
5605e111ed8SAndrew Rybchenko {
5615e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
5625e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &enp->en_nic_cfg;
5635e111ed8SAndrew Rybchenko efx_rc_t rc;
5645e111ed8SAndrew Rybchenko
5655e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5665e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
5675e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
5685e111ed8SAndrew Rybchenko
5695e111ed8SAndrew Rybchenko if (enop->eno_get_vi_pool != NULL) {
5705e111ed8SAndrew Rybchenko uint32_t vi_count = 0;
5715e111ed8SAndrew Rybchenko
5725e111ed8SAndrew Rybchenko if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
5735e111ed8SAndrew Rybchenko goto fail1;
5745e111ed8SAndrew Rybchenko
5755e111ed8SAndrew Rybchenko *evq_countp = vi_count;
5765e111ed8SAndrew Rybchenko *rxq_countp = vi_count;
5775e111ed8SAndrew Rybchenko *txq_countp = vi_count;
5785e111ed8SAndrew Rybchenko } else {
5795e111ed8SAndrew Rybchenko /* Use NIC limits as default value */
5805e111ed8SAndrew Rybchenko *evq_countp = encp->enc_evq_limit;
5815e111ed8SAndrew Rybchenko *rxq_countp = encp->enc_rxq_limit;
5825e111ed8SAndrew Rybchenko *txq_countp = encp->enc_txq_limit;
5835e111ed8SAndrew Rybchenko }
5845e111ed8SAndrew Rybchenko
5855e111ed8SAndrew Rybchenko return (0);
5865e111ed8SAndrew Rybchenko
5875e111ed8SAndrew Rybchenko fail1:
5885e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5895e111ed8SAndrew Rybchenko
5905e111ed8SAndrew Rybchenko return (rc);
5915e111ed8SAndrew Rybchenko }
5925e111ed8SAndrew Rybchenko
5935e111ed8SAndrew Rybchenko
5945e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_init(__in efx_nic_t * enp)5955e111ed8SAndrew Rybchenko efx_nic_init(
5965e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
5975e111ed8SAndrew Rybchenko {
5985e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
5995e111ed8SAndrew Rybchenko efx_rc_t rc;
6005e111ed8SAndrew Rybchenko
6015e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6025e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
6035e111ed8SAndrew Rybchenko
6045e111ed8SAndrew Rybchenko if (enp->en_mod_flags & EFX_MOD_NIC) {
6055e111ed8SAndrew Rybchenko rc = EINVAL;
6065e111ed8SAndrew Rybchenko goto fail1;
6075e111ed8SAndrew Rybchenko }
6085e111ed8SAndrew Rybchenko
6095e111ed8SAndrew Rybchenko if ((rc = enop->eno_init(enp)) != 0)
6105e111ed8SAndrew Rybchenko goto fail2;
6115e111ed8SAndrew Rybchenko
6125e111ed8SAndrew Rybchenko enp->en_mod_flags |= EFX_MOD_NIC;
6135e111ed8SAndrew Rybchenko
6145e111ed8SAndrew Rybchenko return (0);
6155e111ed8SAndrew Rybchenko
6165e111ed8SAndrew Rybchenko fail2:
6175e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
6185e111ed8SAndrew Rybchenko fail1:
6195e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
6205e111ed8SAndrew Rybchenko
6215e111ed8SAndrew Rybchenko return (rc);
6225e111ed8SAndrew Rybchenko }
6235e111ed8SAndrew Rybchenko
6245e111ed8SAndrew Rybchenko void
efx_nic_fini(__in efx_nic_t * enp)6255e111ed8SAndrew Rybchenko efx_nic_fini(
6265e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6275e111ed8SAndrew Rybchenko {
6285e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
6295e111ed8SAndrew Rybchenko
6305e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6315e111ed8SAndrew Rybchenko EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
6325e111ed8SAndrew Rybchenko EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
6335e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
6345e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
6355e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
6365e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
6375e111ed8SAndrew Rybchenko
6385e111ed8SAndrew Rybchenko enop->eno_fini(enp);
6395e111ed8SAndrew Rybchenko
6405e111ed8SAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_NIC;
6415e111ed8SAndrew Rybchenko }
6425e111ed8SAndrew Rybchenko
6435e111ed8SAndrew Rybchenko void
efx_nic_unprobe(__in efx_nic_t * enp)6445e111ed8SAndrew Rybchenko efx_nic_unprobe(
6455e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6465e111ed8SAndrew Rybchenko {
6475e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
6485e111ed8SAndrew Rybchenko
6495e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6505e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI
6515e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
6525e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MCDI */
6535e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
6545e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
6555e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
6565e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
6575e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
6585e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
6595e111ed8SAndrew Rybchenko
6605e111ed8SAndrew Rybchenko efx_phy_unprobe(enp);
6615e111ed8SAndrew Rybchenko
6625e111ed8SAndrew Rybchenko enop->eno_unprobe(enp);
6635e111ed8SAndrew Rybchenko
6645e111ed8SAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_PROBE;
6655e111ed8SAndrew Rybchenko }
6665e111ed8SAndrew Rybchenko
6675e111ed8SAndrew Rybchenko void
efx_nic_destroy(__in efx_nic_t * enp)6685e111ed8SAndrew Rybchenko efx_nic_destroy(
6695e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6705e111ed8SAndrew Rybchenko {
6715e111ed8SAndrew Rybchenko efsys_identifier_t *esip = enp->en_esip;
6725e111ed8SAndrew Rybchenko
6735e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6745e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
6755e111ed8SAndrew Rybchenko
6765e111ed8SAndrew Rybchenko enp->en_family = EFX_FAMILY_INVALID;
6775e111ed8SAndrew Rybchenko enp->en_esip = NULL;
6785e111ed8SAndrew Rybchenko enp->en_esbp = NULL;
6795e111ed8SAndrew Rybchenko enp->en_eslp = NULL;
6805e111ed8SAndrew Rybchenko
6815e111ed8SAndrew Rybchenko enp->en_enop = NULL;
6825e111ed8SAndrew Rybchenko
6835e111ed8SAndrew Rybchenko enp->en_magic = 0;
6845e111ed8SAndrew Rybchenko
6855e111ed8SAndrew Rybchenko /* Free the NIC object */
6865e111ed8SAndrew Rybchenko EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
6875e111ed8SAndrew Rybchenko }
6885e111ed8SAndrew Rybchenko
6895e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_reset(__in efx_nic_t * enp)6905e111ed8SAndrew Rybchenko efx_nic_reset(
6915e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6925e111ed8SAndrew Rybchenko {
6935e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
6945e111ed8SAndrew Rybchenko unsigned int mod_flags;
6955e111ed8SAndrew Rybchenko efx_rc_t rc;
6965e111ed8SAndrew Rybchenko
6975e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6985e111ed8SAndrew Rybchenko EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
6995e111ed8SAndrew Rybchenko /*
7005e111ed8SAndrew Rybchenko * All modules except the MCDI, PROBE, NVRAM, VPD, MON, TUNNEL
7015e111ed8SAndrew Rybchenko * (which we do not reset here) must have been shut down or never
7025e111ed8SAndrew Rybchenko * initialized.
7035e111ed8SAndrew Rybchenko *
7045e111ed8SAndrew Rybchenko * A rule of thumb here is: If the controller or MC reboots, is *any*
7055e111ed8SAndrew Rybchenko * state lost. If it's lost and needs reapplying, then the module
7065e111ed8SAndrew Rybchenko * *must* not be initialised during the reset.
7075e111ed8SAndrew Rybchenko */
7085e111ed8SAndrew Rybchenko mod_flags = enp->en_mod_flags;
7095e111ed8SAndrew Rybchenko mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
7105e111ed8SAndrew Rybchenko EFX_MOD_VPD | EFX_MOD_MON);
7115e111ed8SAndrew Rybchenko #if EFSYS_OPT_TUNNEL
7125e111ed8SAndrew Rybchenko mod_flags &= ~EFX_MOD_TUNNEL;
7135e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_TUNNEL */
7145e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(mod_flags, ==, 0);
7155e111ed8SAndrew Rybchenko if (mod_flags != 0) {
7165e111ed8SAndrew Rybchenko rc = EINVAL;
7175e111ed8SAndrew Rybchenko goto fail1;
7185e111ed8SAndrew Rybchenko }
7195e111ed8SAndrew Rybchenko
7205e111ed8SAndrew Rybchenko if ((rc = enop->eno_reset(enp)) != 0)
7215e111ed8SAndrew Rybchenko goto fail2;
7225e111ed8SAndrew Rybchenko
7235e111ed8SAndrew Rybchenko return (0);
7245e111ed8SAndrew Rybchenko
7255e111ed8SAndrew Rybchenko fail2:
7265e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
7275e111ed8SAndrew Rybchenko fail1:
7285e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7295e111ed8SAndrew Rybchenko
7305e111ed8SAndrew Rybchenko return (rc);
7315e111ed8SAndrew Rybchenko }
7325e111ed8SAndrew Rybchenko
7335e111ed8SAndrew Rybchenko const efx_nic_cfg_t *
efx_nic_cfg_get(__in const efx_nic_t * enp)7345e111ed8SAndrew Rybchenko efx_nic_cfg_get(
7355e111ed8SAndrew Rybchenko __in const efx_nic_t *enp)
7365e111ed8SAndrew Rybchenko {
7375e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
7385e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
7395e111ed8SAndrew Rybchenko
7405e111ed8SAndrew Rybchenko return (&(enp->en_nic_cfg));
7415e111ed8SAndrew Rybchenko }
7425e111ed8SAndrew Rybchenko
7435e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_get_fw_version(__in efx_nic_t * enp,__out efx_nic_fw_info_t * enfip)7445e111ed8SAndrew Rybchenko efx_nic_get_fw_version(
7455e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
7465e111ed8SAndrew Rybchenko __out efx_nic_fw_info_t *enfip)
7475e111ed8SAndrew Rybchenko {
7485e111ed8SAndrew Rybchenko uint16_t mc_fw_version[4];
7495e111ed8SAndrew Rybchenko efx_rc_t rc;
7505e111ed8SAndrew Rybchenko
7515e111ed8SAndrew Rybchenko if (enfip == NULL) {
7525e111ed8SAndrew Rybchenko rc = EINVAL;
7535e111ed8SAndrew Rybchenko goto fail1;
7545e111ed8SAndrew Rybchenko }
7555e111ed8SAndrew Rybchenko
7565e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
7575e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
7585e111ed8SAndrew Rybchenko
7595e111ed8SAndrew Rybchenko /* Ensure RXDP_FW_ID codes match with MC_CMD_GET_CAPABILITIES codes */
7605e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_RXDP_FULL_FEATURED_FW_ID ==
7615e111ed8SAndrew Rybchenko MC_CMD_GET_CAPABILITIES_OUT_RXDP);
7625e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_RXDP_LOW_LATENCY_FW_ID ==
7635e111ed8SAndrew Rybchenko MC_CMD_GET_CAPABILITIES_OUT_RXDP_LOW_LATENCY);
7645e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_RXDP_PACKED_STREAM_FW_ID ==
7655e111ed8SAndrew Rybchenko MC_CMD_GET_CAPABILITIES_OUT_RXDP_PACKED_STREAM);
7665e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_RXDP_RULES_ENGINE_FW_ID ==
7675e111ed8SAndrew Rybchenko MC_CMD_GET_CAPABILITIES_OUT_RXDP_RULES_ENGINE);
7685e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_RXDP_DPDK_FW_ID ==
7695e111ed8SAndrew Rybchenko MC_CMD_GET_CAPABILITIES_OUT_RXDP_DPDK);
7705e111ed8SAndrew Rybchenko
7715e111ed8SAndrew Rybchenko rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL);
7725e111ed8SAndrew Rybchenko if (rc != 0)
7735e111ed8SAndrew Rybchenko goto fail2;
7745e111ed8SAndrew Rybchenko
7755e111ed8SAndrew Rybchenko rc = efx_mcdi_get_capabilities(enp, NULL,
7765e111ed8SAndrew Rybchenko &enfip->enfi_rx_dpcpu_fw_id,
7775e111ed8SAndrew Rybchenko &enfip->enfi_tx_dpcpu_fw_id,
7785e111ed8SAndrew Rybchenko NULL, NULL);
7795e111ed8SAndrew Rybchenko if (rc == 0) {
7805e111ed8SAndrew Rybchenko enfip->enfi_dpcpu_fw_ids_valid = B_TRUE;
7815e111ed8SAndrew Rybchenko } else if (rc == ENOTSUP) {
7825e111ed8SAndrew Rybchenko enfip->enfi_dpcpu_fw_ids_valid = B_FALSE;
7835e111ed8SAndrew Rybchenko enfip->enfi_rx_dpcpu_fw_id = 0;
7845e111ed8SAndrew Rybchenko enfip->enfi_tx_dpcpu_fw_id = 0;
7855e111ed8SAndrew Rybchenko } else {
7865e111ed8SAndrew Rybchenko goto fail3;
7875e111ed8SAndrew Rybchenko }
7885e111ed8SAndrew Rybchenko
7895e111ed8SAndrew Rybchenko memcpy(enfip->enfi_mc_fw_version, mc_fw_version,
7905e111ed8SAndrew Rybchenko sizeof (mc_fw_version));
7915e111ed8SAndrew Rybchenko
7925e111ed8SAndrew Rybchenko return (0);
7935e111ed8SAndrew Rybchenko
7945e111ed8SAndrew Rybchenko fail3:
7955e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
7965e111ed8SAndrew Rybchenko fail2:
7975e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
7985e111ed8SAndrew Rybchenko fail1:
7995e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8005e111ed8SAndrew Rybchenko
8015e111ed8SAndrew Rybchenko return (rc);
8025e111ed8SAndrew Rybchenko }
8035e111ed8SAndrew Rybchenko
804833cfcd5SIvan Malov __checkReturn efx_rc_t
efx_nic_get_board_info(__in efx_nic_t * enp,__out efx_nic_board_info_t * board_infop)805833cfcd5SIvan Malov efx_nic_get_board_info(
806833cfcd5SIvan Malov __in efx_nic_t *enp,
807833cfcd5SIvan Malov __out efx_nic_board_info_t *board_infop)
808833cfcd5SIvan Malov {
809833cfcd5SIvan Malov efx_mcdi_version_t ver;
810833cfcd5SIvan Malov efx_rc_t rc;
811833cfcd5SIvan Malov
812833cfcd5SIvan Malov EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
813833cfcd5SIvan Malov EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
814833cfcd5SIvan Malov
815833cfcd5SIvan Malov rc = efx_mcdi_get_version(enp, EFX_MCDI_VERSION_BOARD_INFO, &ver);
816833cfcd5SIvan Malov if (rc == EMSGSIZE) {
817833cfcd5SIvan Malov /*
818833cfcd5SIvan Malov * Typically, EMSGSIZE is returned by above call in the
819833cfcd5SIvan Malov * case when the NIC does not provide extra information.
820833cfcd5SIvan Malov */
821833cfcd5SIvan Malov rc = ENOTSUP;
822833cfcd5SIvan Malov goto fail1;
823833cfcd5SIvan Malov } else if (rc != 0) {
824833cfcd5SIvan Malov goto fail2;
825833cfcd5SIvan Malov }
826833cfcd5SIvan Malov
827833cfcd5SIvan Malov if ((ver.emv_flags & EFX_MCDI_VERSION_BOARD_INFO) == 0) {
828833cfcd5SIvan Malov rc = ENOTSUP;
829833cfcd5SIvan Malov goto fail3;
830833cfcd5SIvan Malov }
831833cfcd5SIvan Malov
832833cfcd5SIvan Malov memcpy(board_infop, &ver.emv_board_info, sizeof (*board_infop));
833833cfcd5SIvan Malov
834833cfcd5SIvan Malov /* MCDI should provide NUL-terminated strings, but stay vigilant. */
835833cfcd5SIvan Malov board_infop->enbi_serial[sizeof (board_infop->enbi_serial) - 1] = '\0';
836833cfcd5SIvan Malov board_infop->enbi_name[sizeof (board_infop->enbi_name) - 1] = '\0';
837833cfcd5SIvan Malov
838833cfcd5SIvan Malov return (0);
839833cfcd5SIvan Malov
840833cfcd5SIvan Malov fail3:
841833cfcd5SIvan Malov EFSYS_PROBE(fail3);
842833cfcd5SIvan Malov fail2:
843833cfcd5SIvan Malov EFSYS_PROBE(fail2);
844833cfcd5SIvan Malov fail1:
845833cfcd5SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
846833cfcd5SIvan Malov
847833cfcd5SIvan Malov return (rc);
848833cfcd5SIvan Malov }
849833cfcd5SIvan Malov
8505e111ed8SAndrew Rybchenko __checkReturn boolean_t
efx_nic_hw_unavailable(__in efx_nic_t * enp)8515e111ed8SAndrew Rybchenko efx_nic_hw_unavailable(
8525e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
8535e111ed8SAndrew Rybchenko {
8545e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
8555e111ed8SAndrew Rybchenko
8565e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8575e111ed8SAndrew Rybchenko /* NOTE: can be used by MCDI before NIC probe */
8585e111ed8SAndrew Rybchenko
8595e111ed8SAndrew Rybchenko if (enop->eno_hw_unavailable != NULL) {
8605e111ed8SAndrew Rybchenko if ((enop->eno_hw_unavailable)(enp) != B_FALSE)
8615e111ed8SAndrew Rybchenko goto unavail;
8625e111ed8SAndrew Rybchenko }
8635e111ed8SAndrew Rybchenko
8645e111ed8SAndrew Rybchenko return (B_FALSE);
8655e111ed8SAndrew Rybchenko
8665e111ed8SAndrew Rybchenko unavail:
8675e111ed8SAndrew Rybchenko return (B_TRUE);
8685e111ed8SAndrew Rybchenko }
8695e111ed8SAndrew Rybchenko
8705e111ed8SAndrew Rybchenko void
efx_nic_set_hw_unavailable(__in efx_nic_t * enp)8715e111ed8SAndrew Rybchenko efx_nic_set_hw_unavailable(
8725e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
8735e111ed8SAndrew Rybchenko {
8745e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
8755e111ed8SAndrew Rybchenko
8765e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8775e111ed8SAndrew Rybchenko
8785e111ed8SAndrew Rybchenko if (enop->eno_set_hw_unavailable != NULL)
8795e111ed8SAndrew Rybchenko enop->eno_set_hw_unavailable(enp);
8805e111ed8SAndrew Rybchenko }
8815e111ed8SAndrew Rybchenko
8825e111ed8SAndrew Rybchenko
8835e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
8845e111ed8SAndrew Rybchenko
8855e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_register_test(__in efx_nic_t * enp)8865e111ed8SAndrew Rybchenko efx_nic_register_test(
8875e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
8885e111ed8SAndrew Rybchenko {
8895e111ed8SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
8905e111ed8SAndrew Rybchenko efx_rc_t rc;
8915e111ed8SAndrew Rybchenko
8925e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8935e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
8945e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
8955e111ed8SAndrew Rybchenko
8965e111ed8SAndrew Rybchenko if ((rc = enop->eno_register_test(enp)) != 0)
8975e111ed8SAndrew Rybchenko goto fail1;
8985e111ed8SAndrew Rybchenko
8995e111ed8SAndrew Rybchenko return (0);
9005e111ed8SAndrew Rybchenko
9015e111ed8SAndrew Rybchenko fail1:
9025e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
9035e111ed8SAndrew Rybchenko
9045e111ed8SAndrew Rybchenko return (rc);
9055e111ed8SAndrew Rybchenko }
9065e111ed8SAndrew Rybchenko
9075e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
9085e111ed8SAndrew Rybchenko
9095e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
9105e111ed8SAndrew Rybchenko
9115e111ed8SAndrew Rybchenko extern void
efx_loopback_mask(__in efx_loopback_kind_t loopback_kind,__out efx_qword_t * maskp)9125e111ed8SAndrew Rybchenko efx_loopback_mask(
9135e111ed8SAndrew Rybchenko __in efx_loopback_kind_t loopback_kind,
9145e111ed8SAndrew Rybchenko __out efx_qword_t *maskp)
9155e111ed8SAndrew Rybchenko {
9165e111ed8SAndrew Rybchenko efx_qword_t mask;
9175e111ed8SAndrew Rybchenko
9185e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
9195e111ed8SAndrew Rybchenko EFSYS_ASSERT(maskp != NULL);
9205e111ed8SAndrew Rybchenko
9215e111ed8SAndrew Rybchenko /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */
9225e111ed8SAndrew Rybchenko #define LOOPBACK_CHECK(_mcdi, _efx) \
9235e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx)
9245e111ed8SAndrew Rybchenko
9255e111ed8SAndrew Rybchenko LOOPBACK_CHECK(NONE, OFF);
9265e111ed8SAndrew Rybchenko LOOPBACK_CHECK(DATA, DATA);
9275e111ed8SAndrew Rybchenko LOOPBACK_CHECK(GMAC, GMAC);
9285e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XGMII, XGMII);
9295e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XGXS, XGXS);
9305e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XAUI, XAUI);
9315e111ed8SAndrew Rybchenko LOOPBACK_CHECK(GMII, GMII);
9325e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SGMII, SGMII);
9335e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XGBR, XGBR);
9345e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XFI, XFI);
9355e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR);
9365e111ed8SAndrew Rybchenko LOOPBACK_CHECK(GMII_FAR, GMII_FAR);
9375e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR);
9385e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XFI_FAR, XFI_FAR);
9395e111ed8SAndrew Rybchenko LOOPBACK_CHECK(GPHY, GPHY);
9405e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PHYXS, PHY_XS);
9415e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PCS, PCS);
9425e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PMAPMD, PMA_PMD);
9435e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XPORT, XPORT);
9445e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XGMII_WS, XGMII_WS);
9455e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XAUI_WS, XAUI_WS);
9465e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR);
9475e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR);
9485e111ed8SAndrew Rybchenko LOOPBACK_CHECK(GMII_WS, GMII_WS);
9495e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XFI_WS, XFI_WS);
9505e111ed8SAndrew Rybchenko LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR);
9515e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS);
9525e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PMA_INT, PMA_INT);
9535e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_NEAR, SD_NEAR);
9545e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_FAR, SD_FAR);
9555e111ed8SAndrew Rybchenko LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS);
9565e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS);
9575e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS);
9585e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS);
9595e111ed8SAndrew Rybchenko LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS);
9605e111ed8SAndrew Rybchenko LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR);
9615e111ed8SAndrew Rybchenko LOOPBACK_CHECK(DATA_WS, DATA_WS);
9625e111ed8SAndrew Rybchenko LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK);
9635e111ed8SAndrew Rybchenko #undef LOOPBACK_CHECK
9645e111ed8SAndrew Rybchenko
9655e111ed8SAndrew Rybchenko /* Build bitmask of possible loopback types */
9665e111ed8SAndrew Rybchenko EFX_ZERO_QWORD(mask);
9675e111ed8SAndrew Rybchenko
9685e111ed8SAndrew Rybchenko if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
9695e111ed8SAndrew Rybchenko (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
9705e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
9715e111ed8SAndrew Rybchenko }
9725e111ed8SAndrew Rybchenko
9735e111ed8SAndrew Rybchenko if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
9745e111ed8SAndrew Rybchenko (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
9755e111ed8SAndrew Rybchenko /*
9765e111ed8SAndrew Rybchenko * The "MAC" grouping has historically been used by drivers to
9775e111ed8SAndrew Rybchenko * mean loopbacks supported by on-chip hardware. Keep that
9785e111ed8SAndrew Rybchenko * meaning here, and include on-chip PHY layer loopbacks.
9795e111ed8SAndrew Rybchenko */
9805e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
9815e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
9825e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
9835e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
9845e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
9855e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
9865e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
9875e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
9885e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
9895e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
9905e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
9915e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
9925e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
9935e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
9945e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
9955e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
9965e111ed8SAndrew Rybchenko }
9975e111ed8SAndrew Rybchenko
9985e111ed8SAndrew Rybchenko if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
9995e111ed8SAndrew Rybchenko (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
10005e111ed8SAndrew Rybchenko /*
10015e111ed8SAndrew Rybchenko * The "PHY" grouping has historically been used by drivers to
10025e111ed8SAndrew Rybchenko * mean loopbacks supported by off-chip hardware. Keep that
10035e111ed8SAndrew Rybchenko * meaning here.
10045e111ed8SAndrew Rybchenko */
10055e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
10065e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
10075e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
10085e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
10095e111ed8SAndrew Rybchenko }
10105e111ed8SAndrew Rybchenko
10115e111ed8SAndrew Rybchenko *maskp = mask;
10125e111ed8SAndrew Rybchenko }
10135e111ed8SAndrew Rybchenko
10145e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_loopback_modes(__in efx_nic_t * enp)10155e111ed8SAndrew Rybchenko efx_mcdi_get_loopback_modes(
10165e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
10175e111ed8SAndrew Rybchenko {
10185e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
10195e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
10205e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
10215e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN);
10225e111ed8SAndrew Rybchenko efx_qword_t mask;
10235e111ed8SAndrew Rybchenko efx_qword_t modes;
10245e111ed8SAndrew Rybchenko efx_rc_t rc;
10255e111ed8SAndrew Rybchenko
10265e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
10275e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
10285e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
10295e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
10305e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN;
10315e111ed8SAndrew Rybchenko
10325e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
10335e111ed8SAndrew Rybchenko
10345e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
10355e111ed8SAndrew Rybchenko rc = req.emr_rc;
10365e111ed8SAndrew Rybchenko goto fail1;
10375e111ed8SAndrew Rybchenko }
10385e111ed8SAndrew Rybchenko
10395e111ed8SAndrew Rybchenko if (req.emr_out_length_used <
10405e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
10415e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
10425e111ed8SAndrew Rybchenko rc = EMSGSIZE;
10435e111ed8SAndrew Rybchenko goto fail2;
10445e111ed8SAndrew Rybchenko }
10455e111ed8SAndrew Rybchenko
10465e111ed8SAndrew Rybchenko /*
10475e111ed8SAndrew Rybchenko * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
10485e111ed8SAndrew Rybchenko * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
10495e111ed8SAndrew Rybchenko */
10505e111ed8SAndrew Rybchenko efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
10515e111ed8SAndrew Rybchenko
10525e111ed8SAndrew Rybchenko EFX_AND_QWORD(mask,
10535e111ed8SAndrew Rybchenko *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
10545e111ed8SAndrew Rybchenko
10555e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
10565e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10575e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
10585e111ed8SAndrew Rybchenko
10595e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
10605e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10615e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
10625e111ed8SAndrew Rybchenko
10635e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
10645e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10655e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
10665e111ed8SAndrew Rybchenko
10675e111ed8SAndrew Rybchenko if (req.emr_out_length_used >=
10685e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
10695e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
10705e111ed8SAndrew Rybchenko /* Response includes 40G loopback modes */
10715e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t,
10725e111ed8SAndrew Rybchenko GET_LOOPBACK_MODES_OUT_40G);
10735e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10745e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
10755e111ed8SAndrew Rybchenko }
10765e111ed8SAndrew Rybchenko
10775e111ed8SAndrew Rybchenko if (req.emr_out_length_used >=
10785e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST +
10795e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) {
10805e111ed8SAndrew Rybchenko /* Response includes 25G loopback modes */
10815e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t,
10825e111ed8SAndrew Rybchenko GET_LOOPBACK_MODES_OUT_V2_25G);
10835e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10845e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_25000FDX] = modes;
10855e111ed8SAndrew Rybchenko }
10865e111ed8SAndrew Rybchenko
10875e111ed8SAndrew Rybchenko if (req.emr_out_length_used >=
10885e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST +
10895e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) {
10905e111ed8SAndrew Rybchenko /* Response includes 50G loopback modes */
10915e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t,
10925e111ed8SAndrew Rybchenko GET_LOOPBACK_MODES_OUT_V2_50G);
10935e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
10945e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_50000FDX] = modes;
10955e111ed8SAndrew Rybchenko }
10965e111ed8SAndrew Rybchenko
10975e111ed8SAndrew Rybchenko if (req.emr_out_length_used >=
10985e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST +
10995e111ed8SAndrew Rybchenko MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) {
11005e111ed8SAndrew Rybchenko /* Response includes 100G loopback modes */
11015e111ed8SAndrew Rybchenko modes = *MCDI_OUT2(req, efx_qword_t,
11025e111ed8SAndrew Rybchenko GET_LOOPBACK_MODES_OUT_V2_100G);
11035e111ed8SAndrew Rybchenko EFX_AND_QWORD(modes, mask);
11045e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_100000FDX] = modes;
11055e111ed8SAndrew Rybchenko }
11065e111ed8SAndrew Rybchenko
11075e111ed8SAndrew Rybchenko EFX_ZERO_QWORD(modes);
11085e111ed8SAndrew Rybchenko EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
11095e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
11105e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
11115e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
11125e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
11135e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]);
11145e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]);
11155e111ed8SAndrew Rybchenko EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]);
11165e111ed8SAndrew Rybchenko encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
11175e111ed8SAndrew Rybchenko
11185e111ed8SAndrew Rybchenko return (0);
11195e111ed8SAndrew Rybchenko
11205e111ed8SAndrew Rybchenko fail2:
11215e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
11225e111ed8SAndrew Rybchenko fail1:
11235e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
11245e111ed8SAndrew Rybchenko
11255e111ed8SAndrew Rybchenko return (rc);
11265e111ed8SAndrew Rybchenko }
11275e111ed8SAndrew Rybchenko
11285e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_LOOPBACK */
11295e111ed8SAndrew Rybchenko
11305e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_calculate_pcie_link_bandwidth(__in uint32_t pcie_link_width,__in uint32_t pcie_link_gen,__out uint32_t * bandwidth_mbpsp)11315e111ed8SAndrew Rybchenko efx_nic_calculate_pcie_link_bandwidth(
11325e111ed8SAndrew Rybchenko __in uint32_t pcie_link_width,
11335e111ed8SAndrew Rybchenko __in uint32_t pcie_link_gen,
11345e111ed8SAndrew Rybchenko __out uint32_t *bandwidth_mbpsp)
11355e111ed8SAndrew Rybchenko {
11365e111ed8SAndrew Rybchenko uint32_t lane_bandwidth;
11375e111ed8SAndrew Rybchenko uint32_t total_bandwidth;
11385e111ed8SAndrew Rybchenko efx_rc_t rc;
11395e111ed8SAndrew Rybchenko
11405e111ed8SAndrew Rybchenko if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
11415e111ed8SAndrew Rybchenko !ISP2(pcie_link_width)) {
11425e111ed8SAndrew Rybchenko rc = EINVAL;
11435e111ed8SAndrew Rybchenko goto fail1;
11445e111ed8SAndrew Rybchenko }
11455e111ed8SAndrew Rybchenko
11465e111ed8SAndrew Rybchenko switch (pcie_link_gen) {
11475e111ed8SAndrew Rybchenko case EFX_PCIE_LINK_SPEED_GEN1:
11485e111ed8SAndrew Rybchenko /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
11495e111ed8SAndrew Rybchenko lane_bandwidth = 2000;
11505e111ed8SAndrew Rybchenko break;
11515e111ed8SAndrew Rybchenko case EFX_PCIE_LINK_SPEED_GEN2:
11525e111ed8SAndrew Rybchenko /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
11535e111ed8SAndrew Rybchenko lane_bandwidth = 4000;
11545e111ed8SAndrew Rybchenko break;
11555e111ed8SAndrew Rybchenko case EFX_PCIE_LINK_SPEED_GEN3:
11565e111ed8SAndrew Rybchenko /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
11575e111ed8SAndrew Rybchenko lane_bandwidth = 7877;
11585e111ed8SAndrew Rybchenko break;
11595e111ed8SAndrew Rybchenko default:
11605e111ed8SAndrew Rybchenko rc = EINVAL;
11615e111ed8SAndrew Rybchenko goto fail2;
11625e111ed8SAndrew Rybchenko }
11635e111ed8SAndrew Rybchenko
11645e111ed8SAndrew Rybchenko total_bandwidth = lane_bandwidth * pcie_link_width;
11655e111ed8SAndrew Rybchenko *bandwidth_mbpsp = total_bandwidth;
11665e111ed8SAndrew Rybchenko
11675e111ed8SAndrew Rybchenko return (0);
11685e111ed8SAndrew Rybchenko
11695e111ed8SAndrew Rybchenko fail2:
11705e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
11715e111ed8SAndrew Rybchenko fail1:
11725e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
11735e111ed8SAndrew Rybchenko
11745e111ed8SAndrew Rybchenko return (rc);
11755e111ed8SAndrew Rybchenko }
11765e111ed8SAndrew Rybchenko
11775e111ed8SAndrew Rybchenko #if EFSYS_OPT_FW_SUBVARIANT_AWARE
11785e111ed8SAndrew Rybchenko
11795e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_get_fw_subvariant(__in efx_nic_t * enp,__out efx_nic_fw_subvariant_t * subvariantp)11805e111ed8SAndrew Rybchenko efx_nic_get_fw_subvariant(
11815e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
11825e111ed8SAndrew Rybchenko __out efx_nic_fw_subvariant_t *subvariantp)
11835e111ed8SAndrew Rybchenko {
11845e111ed8SAndrew Rybchenko efx_rc_t rc;
11855e111ed8SAndrew Rybchenko uint32_t value;
11865e111ed8SAndrew Rybchenko
11875e111ed8SAndrew Rybchenko rc = efx_mcdi_get_nic_global(enp,
11885e111ed8SAndrew Rybchenko MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, &value);
11895e111ed8SAndrew Rybchenko if (rc != 0)
11905e111ed8SAndrew Rybchenko goto fail1;
11915e111ed8SAndrew Rybchenko
11925e111ed8SAndrew Rybchenko /* Mapping is not required since values match MCDI */
11935e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_DEFAULT ==
11945e111ed8SAndrew Rybchenko MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT);
11955e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM ==
11965e111ed8SAndrew Rybchenko MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM);
11975e111ed8SAndrew Rybchenko
11985e111ed8SAndrew Rybchenko switch (value) {
11995e111ed8SAndrew Rybchenko case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT:
12005e111ed8SAndrew Rybchenko case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM:
12015e111ed8SAndrew Rybchenko *subvariantp = value;
12025e111ed8SAndrew Rybchenko break;
12035e111ed8SAndrew Rybchenko default:
12045e111ed8SAndrew Rybchenko rc = EINVAL;
12055e111ed8SAndrew Rybchenko goto fail2;
12065e111ed8SAndrew Rybchenko }
12075e111ed8SAndrew Rybchenko
12085e111ed8SAndrew Rybchenko return (0);
12095e111ed8SAndrew Rybchenko
12105e111ed8SAndrew Rybchenko fail2:
12115e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
12125e111ed8SAndrew Rybchenko
12135e111ed8SAndrew Rybchenko fail1:
12145e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
12155e111ed8SAndrew Rybchenko
12165e111ed8SAndrew Rybchenko return (rc);
12175e111ed8SAndrew Rybchenko }
12185e111ed8SAndrew Rybchenko
12195e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_set_fw_subvariant(__in efx_nic_t * enp,__in efx_nic_fw_subvariant_t subvariant)12205e111ed8SAndrew Rybchenko efx_nic_set_fw_subvariant(
12215e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
12225e111ed8SAndrew Rybchenko __in efx_nic_fw_subvariant_t subvariant)
12235e111ed8SAndrew Rybchenko {
12245e111ed8SAndrew Rybchenko efx_rc_t rc;
12255e111ed8SAndrew Rybchenko
12265e111ed8SAndrew Rybchenko switch (subvariant) {
12275e111ed8SAndrew Rybchenko case EFX_NIC_FW_SUBVARIANT_DEFAULT:
12285e111ed8SAndrew Rybchenko case EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM:
12295e111ed8SAndrew Rybchenko /* Mapping is not required since values match MCDI */
12305e111ed8SAndrew Rybchenko break;
12315e111ed8SAndrew Rybchenko default:
12325e111ed8SAndrew Rybchenko rc = EINVAL;
12335e111ed8SAndrew Rybchenko goto fail1;
12345e111ed8SAndrew Rybchenko }
12355e111ed8SAndrew Rybchenko
12365e111ed8SAndrew Rybchenko rc = efx_mcdi_set_nic_global(enp,
12375e111ed8SAndrew Rybchenko MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, subvariant);
12385e111ed8SAndrew Rybchenko if (rc != 0)
12395e111ed8SAndrew Rybchenko goto fail2;
12405e111ed8SAndrew Rybchenko
12415e111ed8SAndrew Rybchenko return (0);
12425e111ed8SAndrew Rybchenko
12435e111ed8SAndrew Rybchenko fail2:
12445e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
12455e111ed8SAndrew Rybchenko
12465e111ed8SAndrew Rybchenko fail1:
12475e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
12485e111ed8SAndrew Rybchenko
12495e111ed8SAndrew Rybchenko return (rc);
12505e111ed8SAndrew Rybchenko }
12515e111ed8SAndrew Rybchenko
12525e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
12535e111ed8SAndrew Rybchenko
12545e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_check_pcie_link_speed(__in efx_nic_t * enp,__in uint32_t pcie_link_width,__in uint32_t pcie_link_gen,__out efx_pcie_link_performance_t * resultp)12555e111ed8SAndrew Rybchenko efx_nic_check_pcie_link_speed(
12565e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
12575e111ed8SAndrew Rybchenko __in uint32_t pcie_link_width,
12585e111ed8SAndrew Rybchenko __in uint32_t pcie_link_gen,
12595e111ed8SAndrew Rybchenko __out efx_pcie_link_performance_t *resultp)
12605e111ed8SAndrew Rybchenko {
12615e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
12625e111ed8SAndrew Rybchenko uint32_t bandwidth;
12635e111ed8SAndrew Rybchenko efx_pcie_link_performance_t result;
12645e111ed8SAndrew Rybchenko efx_rc_t rc;
12655e111ed8SAndrew Rybchenko
12665e111ed8SAndrew Rybchenko if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
12675e111ed8SAndrew Rybchenko (pcie_link_width == 0) || (pcie_link_width == 32) ||
12685e111ed8SAndrew Rybchenko (pcie_link_gen == 0)) {
12695e111ed8SAndrew Rybchenko /*
12705e111ed8SAndrew Rybchenko * No usable info on what is required and/or in use. In virtual
12715e111ed8SAndrew Rybchenko * machines, sometimes the PCIe link width is reported as 0 or
12725e111ed8SAndrew Rybchenko * 32, or the speed as 0.
12735e111ed8SAndrew Rybchenko */
12745e111ed8SAndrew Rybchenko result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
12755e111ed8SAndrew Rybchenko goto out;
12765e111ed8SAndrew Rybchenko }
12775e111ed8SAndrew Rybchenko
12785e111ed8SAndrew Rybchenko /* Calculate the available bandwidth in megabits per second */
12795e111ed8SAndrew Rybchenko rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
12805e111ed8SAndrew Rybchenko pcie_link_gen, &bandwidth);
12815e111ed8SAndrew Rybchenko if (rc != 0)
12825e111ed8SAndrew Rybchenko goto fail1;
12835e111ed8SAndrew Rybchenko
12845e111ed8SAndrew Rybchenko if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
12855e111ed8SAndrew Rybchenko result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
12865e111ed8SAndrew Rybchenko } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
12875e111ed8SAndrew Rybchenko /* The link provides enough bandwidth but not optimal latency */
12885e111ed8SAndrew Rybchenko result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
12895e111ed8SAndrew Rybchenko } else {
12905e111ed8SAndrew Rybchenko result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
12915e111ed8SAndrew Rybchenko }
12925e111ed8SAndrew Rybchenko
12935e111ed8SAndrew Rybchenko out:
12945e111ed8SAndrew Rybchenko *resultp = result;
12955e111ed8SAndrew Rybchenko
12965e111ed8SAndrew Rybchenko return (0);
12975e111ed8SAndrew Rybchenko
12985e111ed8SAndrew Rybchenko fail1:
12995e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
13005e111ed8SAndrew Rybchenko
13015e111ed8SAndrew Rybchenko return (rc);
13025e111ed8SAndrew Rybchenko }
1303*60fb370cSAndrew Rybchenko
1304*60fb370cSAndrew Rybchenko /* Required en_eslp lock held */
1305*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_config_regioned_find_region(__in const efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out const efx_nic_dma_region_t ** regionp)1306*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_find_region(
1307*60fb370cSAndrew Rybchenko __in const efx_nic_t *enp,
1308*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1309*60fb370cSAndrew Rybchenko __in size_t len,
1310*60fb370cSAndrew Rybchenko __out const efx_nic_dma_region_t **regionp)
1311*60fb370cSAndrew Rybchenko {
1312*60fb370cSAndrew Rybchenko const efx_nic_dma_region_info_t *region_info;
1313*60fb370cSAndrew Rybchenko const efx_nic_dma_region_t *region;
1314*60fb370cSAndrew Rybchenko unsigned int i;
1315*60fb370cSAndrew Rybchenko efx_rc_t rc;
1316*60fb370cSAndrew Rybchenko
1317*60fb370cSAndrew Rybchenko if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1318*60fb370cSAndrew Rybchenko EFX_NIC_DMA_MAPPING_REGIONED) {
1319*60fb370cSAndrew Rybchenko rc = EINVAL;
1320*60fb370cSAndrew Rybchenko goto fail1;
1321*60fb370cSAndrew Rybchenko }
1322*60fb370cSAndrew Rybchenko
1323*60fb370cSAndrew Rybchenko region_info = &enp->en_dma.end_u.endu_region_info;
1324*60fb370cSAndrew Rybchenko
1325*60fb370cSAndrew Rybchenko for (i = 0; i < region_info->endri_count; ++i) {
1326*60fb370cSAndrew Rybchenko efsys_dma_addr_t offset;
1327*60fb370cSAndrew Rybchenko
1328*60fb370cSAndrew Rybchenko region = ®ion_info->endri_regions[i];
1329*60fb370cSAndrew Rybchenko if (region->endr_inuse == B_FALSE)
1330*60fb370cSAndrew Rybchenko continue;
1331*60fb370cSAndrew Rybchenko
1332*60fb370cSAndrew Rybchenko if (trgt_addr < region->endr_trgt_base)
1333*60fb370cSAndrew Rybchenko continue;
1334*60fb370cSAndrew Rybchenko
1335*60fb370cSAndrew Rybchenko EFSYS_ASSERT3U(region->endr_window_log2, <, 64);
1336*60fb370cSAndrew Rybchenko offset = trgt_addr - region->endr_trgt_base;
1337*60fb370cSAndrew Rybchenko if (offset + len > (1ULL << region->endr_window_log2))
1338*60fb370cSAndrew Rybchenko continue;
1339*60fb370cSAndrew Rybchenko
1340*60fb370cSAndrew Rybchenko *regionp = region;
1341*60fb370cSAndrew Rybchenko return (0);
1342*60fb370cSAndrew Rybchenko }
1343*60fb370cSAndrew Rybchenko
1344*60fb370cSAndrew Rybchenko rc = ENOENT;
1345*60fb370cSAndrew Rybchenko goto fail2;
1346*60fb370cSAndrew Rybchenko
1347*60fb370cSAndrew Rybchenko fail2:
1348*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1349*60fb370cSAndrew Rybchenko fail1:
1350*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1351*60fb370cSAndrew Rybchenko
1352*60fb370cSAndrew Rybchenko return (rc);
1353*60fb370cSAndrew Rybchenko }
1354*60fb370cSAndrew Rybchenko
1355*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_config_regioned_add_region(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out const efx_nic_dma_region_t ** regionp)1356*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_add_region(
1357*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1358*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1359*60fb370cSAndrew Rybchenko __in size_t len,
1360*60fb370cSAndrew Rybchenko __out const efx_nic_dma_region_t **regionp)
1361*60fb370cSAndrew Rybchenko {
1362*60fb370cSAndrew Rybchenko efx_nic_dma_region_info_t *region_info;
1363*60fb370cSAndrew Rybchenko efx_nic_dma_region_t *region;
1364*60fb370cSAndrew Rybchenko unsigned int i;
1365*60fb370cSAndrew Rybchenko efx_rc_t rc;
1366*60fb370cSAndrew Rybchenko
1367*60fb370cSAndrew Rybchenko if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1368*60fb370cSAndrew Rybchenko EFX_NIC_DMA_MAPPING_REGIONED) {
1369*60fb370cSAndrew Rybchenko rc = EINVAL;
1370*60fb370cSAndrew Rybchenko goto fail1;
1371*60fb370cSAndrew Rybchenko }
1372*60fb370cSAndrew Rybchenko
1373*60fb370cSAndrew Rybchenko region_info = &enp->en_dma.end_u.endu_region_info;
1374*60fb370cSAndrew Rybchenko
1375*60fb370cSAndrew Rybchenko for (i = 0; i < region_info->endri_count; ++i) {
1376*60fb370cSAndrew Rybchenko efsys_dma_addr_t trgt_base;
1377*60fb370cSAndrew Rybchenko efsys_dma_addr_t offset;
1378*60fb370cSAndrew Rybchenko
1379*60fb370cSAndrew Rybchenko region = ®ion_info->endri_regions[i];
1380*60fb370cSAndrew Rybchenko if (region->endr_inuse == B_TRUE)
1381*60fb370cSAndrew Rybchenko continue;
1382*60fb370cSAndrew Rybchenko
1383*60fb370cSAndrew Rybchenko /*
1384*60fb370cSAndrew Rybchenko * Align target address base in accordance with
1385*60fb370cSAndrew Rybchenko * the region requirements.
1386*60fb370cSAndrew Rybchenko */
1387*60fb370cSAndrew Rybchenko EFSYS_ASSERT3U(region->endr_align_log2, <, 64);
1388*60fb370cSAndrew Rybchenko trgt_base = EFX_P2ALIGN(efsys_dma_addr_t, trgt_addr,
1389*60fb370cSAndrew Rybchenko (1ULL << region->endr_align_log2));
1390*60fb370cSAndrew Rybchenko
1391*60fb370cSAndrew Rybchenko offset = trgt_addr - trgt_base;
1392*60fb370cSAndrew Rybchenko
1393*60fb370cSAndrew Rybchenko /* Check if region window is sufficient */
1394*60fb370cSAndrew Rybchenko EFSYS_ASSERT3U(region->endr_window_log2, <, 64);
1395*60fb370cSAndrew Rybchenko if (offset + len > (1ULL << region->endr_window_log2))
1396*60fb370cSAndrew Rybchenko continue;
1397*60fb370cSAndrew Rybchenko
1398*60fb370cSAndrew Rybchenko region->endr_trgt_base = trgt_base;
1399*60fb370cSAndrew Rybchenko region->endr_inuse = B_TRUE;
1400*60fb370cSAndrew Rybchenko
1401*60fb370cSAndrew Rybchenko *regionp = region;
1402*60fb370cSAndrew Rybchenko return (0);
1403*60fb370cSAndrew Rybchenko }
1404*60fb370cSAndrew Rybchenko
1405*60fb370cSAndrew Rybchenko /* No suitable free region found */
1406*60fb370cSAndrew Rybchenko rc = ENOMEM;
1407*60fb370cSAndrew Rybchenko goto fail2;
1408*60fb370cSAndrew Rybchenko
1409*60fb370cSAndrew Rybchenko fail2:
1410*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1411*60fb370cSAndrew Rybchenko fail1:
1412*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1413*60fb370cSAndrew Rybchenko
1414*60fb370cSAndrew Rybchenko return (rc);
1415*60fb370cSAndrew Rybchenko }
1416*60fb370cSAndrew Rybchenko
1417*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_config_regioned_add(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out_opt efsys_dma_addr_t * nic_basep,__out_opt efsys_dma_addr_t * trgt_basep,__out_opt size_t * map_lenp)1418*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_add(
1419*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1420*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1421*60fb370cSAndrew Rybchenko __in size_t len,
1422*60fb370cSAndrew Rybchenko __out_opt efsys_dma_addr_t *nic_basep,
1423*60fb370cSAndrew Rybchenko __out_opt efsys_dma_addr_t *trgt_basep,
1424*60fb370cSAndrew Rybchenko __out_opt size_t *map_lenp)
1425*60fb370cSAndrew Rybchenko {
1426*60fb370cSAndrew Rybchenko const efx_nic_dma_region_t *region;
1427*60fb370cSAndrew Rybchenko efsys_lock_state_t state;
1428*60fb370cSAndrew Rybchenko efx_rc_t rc;
1429*60fb370cSAndrew Rybchenko
1430*60fb370cSAndrew Rybchenko EFSYS_LOCK(enp->en_eslp, state);
1431*60fb370cSAndrew Rybchenko
1432*60fb370cSAndrew Rybchenko rc = efx_nic_dma_config_regioned_find_region(enp, trgt_addr, len,
1433*60fb370cSAndrew Rybchenko ®ion);
1434*60fb370cSAndrew Rybchenko switch (rc) {
1435*60fb370cSAndrew Rybchenko case 0:
1436*60fb370cSAndrew Rybchenko /* Already covered by existing mapping */
1437*60fb370cSAndrew Rybchenko break;
1438*60fb370cSAndrew Rybchenko case ENOENT:
1439*60fb370cSAndrew Rybchenko /* No existing mapping found */
1440*60fb370cSAndrew Rybchenko rc = efx_nic_dma_config_regioned_add_region(enp,
1441*60fb370cSAndrew Rybchenko trgt_addr, len, ®ion);
1442*60fb370cSAndrew Rybchenko if (rc != 0)
1443*60fb370cSAndrew Rybchenko goto fail1;
1444*60fb370cSAndrew Rybchenko break;
1445*60fb370cSAndrew Rybchenko default:
1446*60fb370cSAndrew Rybchenko goto fail2;
1447*60fb370cSAndrew Rybchenko }
1448*60fb370cSAndrew Rybchenko
1449*60fb370cSAndrew Rybchenko if (nic_basep != NULL)
1450*60fb370cSAndrew Rybchenko *nic_basep = region->endr_nic_base;
1451*60fb370cSAndrew Rybchenko if (trgt_basep != NULL)
1452*60fb370cSAndrew Rybchenko *trgt_basep = region->endr_trgt_base;
1453*60fb370cSAndrew Rybchenko if (map_lenp != NULL)
1454*60fb370cSAndrew Rybchenko *map_lenp = 1ULL << region->endr_window_log2;
1455*60fb370cSAndrew Rybchenko
1456*60fb370cSAndrew Rybchenko EFSYS_UNLOCK(enp->en_eslp, state);
1457*60fb370cSAndrew Rybchenko
1458*60fb370cSAndrew Rybchenko return (0);
1459*60fb370cSAndrew Rybchenko
1460*60fb370cSAndrew Rybchenko fail2:
1461*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1462*60fb370cSAndrew Rybchenko fail1:
1463*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1464*60fb370cSAndrew Rybchenko
1465*60fb370cSAndrew Rybchenko EFSYS_UNLOCK(enp->en_eslp, state);
1466*60fb370cSAndrew Rybchenko
1467*60fb370cSAndrew Rybchenko return (rc);
1468*60fb370cSAndrew Rybchenko }
1469*60fb370cSAndrew Rybchenko
1470*60fb370cSAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_dma_config_add(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out_opt efsys_dma_addr_t * nic_basep,__out_opt efsys_dma_addr_t * trgt_basep,__out_opt size_t * map_lenp)1471*60fb370cSAndrew Rybchenko efx_nic_dma_config_add(
1472*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1473*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1474*60fb370cSAndrew Rybchenko __in size_t len,
1475*60fb370cSAndrew Rybchenko __out_opt efsys_dma_addr_t *nic_basep,
1476*60fb370cSAndrew Rybchenko __out_opt efsys_dma_addr_t *trgt_basep,
1477*60fb370cSAndrew Rybchenko __out_opt size_t *map_lenp)
1478*60fb370cSAndrew Rybchenko {
1479*60fb370cSAndrew Rybchenko const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1480*60fb370cSAndrew Rybchenko efx_rc_t rc;
1481*60fb370cSAndrew Rybchenko
1482*60fb370cSAndrew Rybchenko switch (encp->enc_dma_mapping) {
1483*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_FLAT:
1484*60fb370cSAndrew Rybchenko /* No mapping is required */
1485*60fb370cSAndrew Rybchenko if (nic_basep != NULL)
1486*60fb370cSAndrew Rybchenko *nic_basep = 0;
1487*60fb370cSAndrew Rybchenko if (trgt_basep != NULL)
1488*60fb370cSAndrew Rybchenko *trgt_basep = 0;
1489*60fb370cSAndrew Rybchenko if (map_lenp != NULL)
1490*60fb370cSAndrew Rybchenko *map_lenp = 0;
1491*60fb370cSAndrew Rybchenko break;
1492*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_REGIONED:
1493*60fb370cSAndrew Rybchenko rc = efx_nic_dma_config_regioned_add(enp, trgt_addr, len,
1494*60fb370cSAndrew Rybchenko nic_basep, trgt_basep, map_lenp);
1495*60fb370cSAndrew Rybchenko if (rc != 0)
1496*60fb370cSAndrew Rybchenko goto fail1;
1497*60fb370cSAndrew Rybchenko break;
1498*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_UNKNOWN:
1499*60fb370cSAndrew Rybchenko default:
1500*60fb370cSAndrew Rybchenko rc = ENOTSUP;
1501*60fb370cSAndrew Rybchenko goto fail2;
1502*60fb370cSAndrew Rybchenko }
1503*60fb370cSAndrew Rybchenko
1504*60fb370cSAndrew Rybchenko return (0);
1505*60fb370cSAndrew Rybchenko
1506*60fb370cSAndrew Rybchenko fail2:
1507*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1508*60fb370cSAndrew Rybchenko fail1:
1509*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1510*60fb370cSAndrew Rybchenko
1511*60fb370cSAndrew Rybchenko return (rc);
1512*60fb370cSAndrew Rybchenko }
1513*60fb370cSAndrew Rybchenko
1514*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_reconfigure_regioned(__in efx_nic_t * enp)1515*60fb370cSAndrew Rybchenko efx_nic_dma_reconfigure_regioned(
1516*60fb370cSAndrew Rybchenko __in efx_nic_t *enp)
1517*60fb370cSAndrew Rybchenko {
1518*60fb370cSAndrew Rybchenko efx_rc_t rc;
1519*60fb370cSAndrew Rybchenko
1520*60fb370cSAndrew Rybchenko rc = efx_mcdi_set_nic_addr_regions(enp,
1521*60fb370cSAndrew Rybchenko &enp->en_dma.end_u.endu_region_info);
1522*60fb370cSAndrew Rybchenko if (rc != 0)
1523*60fb370cSAndrew Rybchenko goto fail1;
1524*60fb370cSAndrew Rybchenko
1525*60fb370cSAndrew Rybchenko return (0);
1526*60fb370cSAndrew Rybchenko
1527*60fb370cSAndrew Rybchenko fail1:
1528*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1529*60fb370cSAndrew Rybchenko
1530*60fb370cSAndrew Rybchenko return (rc);
1531*60fb370cSAndrew Rybchenko
1532*60fb370cSAndrew Rybchenko }
1533*60fb370cSAndrew Rybchenko
1534*60fb370cSAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_dma_reconfigure(__in efx_nic_t * enp)1535*60fb370cSAndrew Rybchenko efx_nic_dma_reconfigure(
1536*60fb370cSAndrew Rybchenko __in efx_nic_t *enp)
1537*60fb370cSAndrew Rybchenko {
1538*60fb370cSAndrew Rybchenko const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1539*60fb370cSAndrew Rybchenko efx_rc_t rc;
1540*60fb370cSAndrew Rybchenko
1541*60fb370cSAndrew Rybchenko switch (encp->enc_dma_mapping) {
1542*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_UNKNOWN:
1543*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_FLAT:
1544*60fb370cSAndrew Rybchenko /* Nothing to do */
1545*60fb370cSAndrew Rybchenko break;
1546*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_REGIONED:
1547*60fb370cSAndrew Rybchenko rc = efx_nic_dma_reconfigure_regioned(enp);
1548*60fb370cSAndrew Rybchenko if (rc != 0)
1549*60fb370cSAndrew Rybchenko goto fail1;
1550*60fb370cSAndrew Rybchenko break;
1551*60fb370cSAndrew Rybchenko default:
1552*60fb370cSAndrew Rybchenko rc = ENOTSUP;
1553*60fb370cSAndrew Rybchenko goto fail2;
1554*60fb370cSAndrew Rybchenko }
1555*60fb370cSAndrew Rybchenko
1556*60fb370cSAndrew Rybchenko return (0);
1557*60fb370cSAndrew Rybchenko
1558*60fb370cSAndrew Rybchenko fail2:
1559*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1560*60fb370cSAndrew Rybchenko fail1:
1561*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1562*60fb370cSAndrew Rybchenko
1563*60fb370cSAndrew Rybchenko return (rc);
1564*60fb370cSAndrew Rybchenko }
1565*60fb370cSAndrew Rybchenko
1566*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_unknown_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1567*60fb370cSAndrew Rybchenko efx_nic_dma_unknown_map(
1568*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1569*60fb370cSAndrew Rybchenko __in efx_nic_dma_addr_type_t addr_type,
1570*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1571*60fb370cSAndrew Rybchenko __in size_t len,
1572*60fb370cSAndrew Rybchenko __out efsys_dma_addr_t *nic_addrp)
1573*60fb370cSAndrew Rybchenko {
1574*60fb370cSAndrew Rybchenko efx_rc_t rc;
1575*60fb370cSAndrew Rybchenko
1576*60fb370cSAndrew Rybchenko /* This function may be called before the NIC has been probed. */
1577*60fb370cSAndrew Rybchenko if (enp->en_mod_flags & EFX_MOD_PROBE) {
1578*60fb370cSAndrew Rybchenko EFSYS_ASSERT3U(efx_nic_cfg_get(enp)->enc_dma_mapping, ==,
1579*60fb370cSAndrew Rybchenko EFX_NIC_DMA_MAPPING_UNKNOWN);
1580*60fb370cSAndrew Rybchenko }
1581*60fb370cSAndrew Rybchenko
1582*60fb370cSAndrew Rybchenko switch (addr_type) {
1583*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_MCDI_BUF:
1584*60fb370cSAndrew Rybchenko /*
1585*60fb370cSAndrew Rybchenko * MC cares about MCDI buffer mapping itself since it cannot
1586*60fb370cSAndrew Rybchenko * be really mapped using MCDI because mapped MCDI
1587*60fb370cSAndrew Rybchenko * buffer is required to execute MCDI commands.
1588*60fb370cSAndrew Rybchenko */
1589*60fb370cSAndrew Rybchenko *nic_addrp = trgt_addr;
1590*60fb370cSAndrew Rybchenko break;
1591*60fb370cSAndrew Rybchenko
1592*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_MAC_STATS_BUF:
1593*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_EVENT_RING:
1594*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_RX_RING:
1595*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_TX_RING:
1596*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_RX_BUF:
1597*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_TX_BUF:
1598*60fb370cSAndrew Rybchenko /* Mapping type must be discovered first */
1599*60fb370cSAndrew Rybchenko rc = EFAULT;
1600*60fb370cSAndrew Rybchenko goto fail1;
1601*60fb370cSAndrew Rybchenko
1602*60fb370cSAndrew Rybchenko default:
1603*60fb370cSAndrew Rybchenko rc = EINVAL;
1604*60fb370cSAndrew Rybchenko goto fail2;
1605*60fb370cSAndrew Rybchenko }
1606*60fb370cSAndrew Rybchenko
1607*60fb370cSAndrew Rybchenko return (0);
1608*60fb370cSAndrew Rybchenko
1609*60fb370cSAndrew Rybchenko fail2:
1610*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1611*60fb370cSAndrew Rybchenko fail1:
1612*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1613*60fb370cSAndrew Rybchenko
1614*60fb370cSAndrew Rybchenko return (rc);
1615*60fb370cSAndrew Rybchenko }
1616*60fb370cSAndrew Rybchenko
1617*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_flat_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1618*60fb370cSAndrew Rybchenko efx_nic_dma_flat_map(
1619*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1620*60fb370cSAndrew Rybchenko __in efx_nic_dma_addr_type_t addr_type,
1621*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1622*60fb370cSAndrew Rybchenko __in size_t len,
1623*60fb370cSAndrew Rybchenko __out efsys_dma_addr_t *nic_addrp)
1624*60fb370cSAndrew Rybchenko {
1625*60fb370cSAndrew Rybchenko _NOTE(ARGUNUSED(addr_type, len))
1626*60fb370cSAndrew Rybchenko
1627*60fb370cSAndrew Rybchenko EFSYS_ASSERT3U(efx_nic_cfg_get(enp)->enc_dma_mapping, ==,
1628*60fb370cSAndrew Rybchenko EFX_NIC_DMA_MAPPING_FLAT);
1629*60fb370cSAndrew Rybchenko
1630*60fb370cSAndrew Rybchenko /* No re-mapping is required */
1631*60fb370cSAndrew Rybchenko *nic_addrp = trgt_addr;
1632*60fb370cSAndrew Rybchenko
1633*60fb370cSAndrew Rybchenko return (0);
1634*60fb370cSAndrew Rybchenko }
1635*60fb370cSAndrew Rybchenko
1636*60fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_nic_dma_regioned_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1637*60fb370cSAndrew Rybchenko efx_nic_dma_regioned_map(
1638*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1639*60fb370cSAndrew Rybchenko __in efx_nic_dma_addr_type_t addr_type,
1640*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1641*60fb370cSAndrew Rybchenko __in size_t len,
1642*60fb370cSAndrew Rybchenko __out efsys_dma_addr_t *nic_addrp)
1643*60fb370cSAndrew Rybchenko {
1644*60fb370cSAndrew Rybchenko const efx_nic_dma_region_t *region;
1645*60fb370cSAndrew Rybchenko efsys_lock_state_t state;
1646*60fb370cSAndrew Rybchenko efx_rc_t rc;
1647*60fb370cSAndrew Rybchenko
1648*60fb370cSAndrew Rybchenko if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1649*60fb370cSAndrew Rybchenko EFX_NIC_DMA_MAPPING_REGIONED) {
1650*60fb370cSAndrew Rybchenko rc = EINVAL;
1651*60fb370cSAndrew Rybchenko goto fail1;
1652*60fb370cSAndrew Rybchenko }
1653*60fb370cSAndrew Rybchenko
1654*60fb370cSAndrew Rybchenko switch (addr_type) {
1655*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_MCDI_BUF:
1656*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_MAC_STATS_BUF:
1657*60fb370cSAndrew Rybchenko /*
1658*60fb370cSAndrew Rybchenko * MC cares about MCDI buffer mapping itself since it cannot
1659*60fb370cSAndrew Rybchenko * be really mapped using MCDI because mapped MCDI buffer is
1660*60fb370cSAndrew Rybchenko * required to execute MCDI commands. It is not a problem
1661*60fb370cSAndrew Rybchenko * for MAC stats buffer, but since MC can care about mapping
1662*60fb370cSAndrew Rybchenko * itself, it may be done for MAC stats buffer as well.
1663*60fb370cSAndrew Rybchenko */
1664*60fb370cSAndrew Rybchenko *nic_addrp = trgt_addr;
1665*60fb370cSAndrew Rybchenko goto out;
1666*60fb370cSAndrew Rybchenko
1667*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_EVENT_RING:
1668*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_RX_RING:
1669*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_TX_RING:
1670*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_RX_BUF:
1671*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_ADDR_TX_BUF:
1672*60fb370cSAndrew Rybchenko /* Rings and buffer addresses should be mapped */
1673*60fb370cSAndrew Rybchenko break;
1674*60fb370cSAndrew Rybchenko
1675*60fb370cSAndrew Rybchenko default:
1676*60fb370cSAndrew Rybchenko rc = EINVAL;
1677*60fb370cSAndrew Rybchenko goto fail2;
1678*60fb370cSAndrew Rybchenko }
1679*60fb370cSAndrew Rybchenko
1680*60fb370cSAndrew Rybchenko EFSYS_LOCK(enp->en_eslp, state);
1681*60fb370cSAndrew Rybchenko
1682*60fb370cSAndrew Rybchenko rc = efx_nic_dma_config_regioned_find_region(enp, trgt_addr, len,
1683*60fb370cSAndrew Rybchenko ®ion);
1684*60fb370cSAndrew Rybchenko if (rc != 0)
1685*60fb370cSAndrew Rybchenko goto fail3;
1686*60fb370cSAndrew Rybchenko
1687*60fb370cSAndrew Rybchenko *nic_addrp = region->endr_nic_base +
1688*60fb370cSAndrew Rybchenko (trgt_addr - region->endr_trgt_base);
1689*60fb370cSAndrew Rybchenko
1690*60fb370cSAndrew Rybchenko EFSYS_UNLOCK(enp->en_eslp, state);
1691*60fb370cSAndrew Rybchenko
1692*60fb370cSAndrew Rybchenko out:
1693*60fb370cSAndrew Rybchenko return (0);
1694*60fb370cSAndrew Rybchenko
1695*60fb370cSAndrew Rybchenko fail3:
1696*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail3);
1697*60fb370cSAndrew Rybchenko EFSYS_UNLOCK(enp->en_eslp, state);
1698*60fb370cSAndrew Rybchenko fail2:
1699*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1700*60fb370cSAndrew Rybchenko fail1:
1701*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1702*60fb370cSAndrew Rybchenko
1703*60fb370cSAndrew Rybchenko return (rc);
1704*60fb370cSAndrew Rybchenko }
1705*60fb370cSAndrew Rybchenko
1706*60fb370cSAndrew Rybchenko __checkReturn efx_rc_t
efx_nic_dma_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1707*60fb370cSAndrew Rybchenko efx_nic_dma_map(
1708*60fb370cSAndrew Rybchenko __in efx_nic_t *enp,
1709*60fb370cSAndrew Rybchenko __in efx_nic_dma_addr_type_t addr_type,
1710*60fb370cSAndrew Rybchenko __in efsys_dma_addr_t trgt_addr,
1711*60fb370cSAndrew Rybchenko __in size_t len,
1712*60fb370cSAndrew Rybchenko __out efsys_dma_addr_t *nic_addrp)
1713*60fb370cSAndrew Rybchenko {
1714*60fb370cSAndrew Rybchenko efx_nic_dma_mapping_t mapping;
1715*60fb370cSAndrew Rybchenko efx_rc_t rc;
1716*60fb370cSAndrew Rybchenko
1717*60fb370cSAndrew Rybchenko /*
1718*60fb370cSAndrew Rybchenko * We cannot check configuration of a NIC that hasn't been probed.
1719*60fb370cSAndrew Rybchenko * Use EFX_NIC_DMA_MAPPING_UNKNOWN by default.
1720*60fb370cSAndrew Rybchenko */
1721*60fb370cSAndrew Rybchenko if ((enp->en_mod_flags & EFX_MOD_PROBE) == 0)
1722*60fb370cSAndrew Rybchenko mapping = EFX_NIC_DMA_MAPPING_UNKNOWN;
1723*60fb370cSAndrew Rybchenko else
1724*60fb370cSAndrew Rybchenko mapping = efx_nic_cfg_get(enp)->enc_dma_mapping;
1725*60fb370cSAndrew Rybchenko
1726*60fb370cSAndrew Rybchenko switch (mapping) {
1727*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_UNKNOWN:
1728*60fb370cSAndrew Rybchenko rc = efx_nic_dma_unknown_map(enp, addr_type, trgt_addr,
1729*60fb370cSAndrew Rybchenko len, nic_addrp);
1730*60fb370cSAndrew Rybchenko if (rc != 0)
1731*60fb370cSAndrew Rybchenko goto fail1;
1732*60fb370cSAndrew Rybchenko break;
1733*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_FLAT:
1734*60fb370cSAndrew Rybchenko rc = efx_nic_dma_flat_map(enp, addr_type, trgt_addr,
1735*60fb370cSAndrew Rybchenko len, nic_addrp);
1736*60fb370cSAndrew Rybchenko if (rc != 0)
1737*60fb370cSAndrew Rybchenko goto fail2;
1738*60fb370cSAndrew Rybchenko break;
1739*60fb370cSAndrew Rybchenko case EFX_NIC_DMA_MAPPING_REGIONED:
1740*60fb370cSAndrew Rybchenko rc = efx_nic_dma_regioned_map(enp, addr_type, trgt_addr,
1741*60fb370cSAndrew Rybchenko len, nic_addrp);
1742*60fb370cSAndrew Rybchenko if (rc != 0)
1743*60fb370cSAndrew Rybchenko goto fail3;
1744*60fb370cSAndrew Rybchenko break;
1745*60fb370cSAndrew Rybchenko default:
1746*60fb370cSAndrew Rybchenko rc = ENOTSUP;
1747*60fb370cSAndrew Rybchenko goto fail4;
1748*60fb370cSAndrew Rybchenko }
1749*60fb370cSAndrew Rybchenko
1750*60fb370cSAndrew Rybchenko return (0);
1751*60fb370cSAndrew Rybchenko
1752*60fb370cSAndrew Rybchenko fail4:
1753*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail4);
1754*60fb370cSAndrew Rybchenko fail3:
1755*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail3);
1756*60fb370cSAndrew Rybchenko fail2:
1757*60fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
1758*60fb370cSAndrew Rybchenko fail1:
1759*60fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1760*60fb370cSAndrew Rybchenko
1761*60fb370cSAndrew Rybchenko return (rc);
1762*60fb370cSAndrew Rybchenko }
1763