/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019-2021 Xilinx, Inc.
* Copyright(c) 2007-2019 Solarflare Communications Inc.
*/
#define EFX_MOD_TUNNEL 0x00004000
#define EFX_MOD_EVB 0x00008000
#define EFX_MOD_PROXY 0x00010000
+#define EFX_MOD_VIRTIO 0x00020000
#define EFX_RESET_PHY 0x00000001
#define EFX_RESET_RXQ_ERR 0x00000002
#if EFSYS_OPT_TUNNEL
typedef struct efx_tunnel_ops_s {
- boolean_t (*eto_udp_encap_supported)(efx_nic_t *);
efx_rc_t (*eto_reconfigure)(efx_nic_t *);
+ void (*eto_fini)(efx_nic_t *);
} efx_tunnel_ops_t;
#endif /* EFSYS_OPT_TUNNEL */
+#if EFSYS_OPT_VIRTIO
+typedef struct efx_virtio_ops_s {
+ efx_rc_t (*evo_virtio_qstart)(efx_virtio_vq_t *,
+ efx_virtio_vq_cfg_t *,
+ efx_virtio_vq_dyncfg_t *);
+ efx_rc_t (*evo_virtio_qstop)(efx_virtio_vq_t *,
+ efx_virtio_vq_dyncfg_t *);
+ efx_rc_t (*evo_get_doorbell_offset)(efx_virtio_vq_t *,
+ uint32_t *);
+ efx_rc_t (*evo_get_features)(efx_nic_t *,
+ efx_virtio_device_type_t, uint64_t *);
+ efx_rc_t (*evo_verify_features)(efx_nic_t *,
+ efx_virtio_device_type_t, uint64_t);
+} efx_virtio_ops_t;
+#endif /* EFSYS_OPT_VIRTIO */
+
typedef struct efx_port_s {
efx_mac_type_t ep_mac_type;
uint32_t ep_phy_type;
#if EFSYS_OPT_TUNNEL
+/* State of a UDP tunnel table entry */
+typedef enum efx_tunnel_udp_entry_state_e {
+ EFX_TUNNEL_UDP_ENTRY_ADDED, /* Tunnel addition is requested */
+ EFX_TUNNEL_UDP_ENTRY_REMOVED, /* Tunnel removal is requested */
+ EFX_TUNNEL_UDP_ENTRY_APPLIED, /* Tunnel is applied by HW */
+} efx_tunnel_udp_entry_state_t;
+
+#if EFSYS_OPT_RIVERHEAD
+typedef uint32_t efx_vnic_encap_rule_handle_t;
+#endif /* EFSYS_OPT_RIVERHEAD */
+
typedef struct efx_tunnel_udp_entry_s {
uint16_t etue_port; /* host/cpu-endian */
uint16_t etue_protocol;
+ boolean_t etue_busy;
+ efx_tunnel_udp_entry_state_t etue_state;
+#if EFSYS_OPT_RIVERHEAD
+ efx_vnic_encap_rule_handle_t etue_handle;
+#endif /* EFSYS_OPT_RIVERHEAD */
} efx_tunnel_udp_entry_t;
typedef struct efx_tunnel_cfg_s {
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+#if EFSYS_OPT_MAE
+
+typedef struct efx_mae_field_cap_s {
+ uint32_t emfc_support;
+ boolean_t emfc_mask_affects_class;
+ boolean_t emfc_match_affects_class;
+} efx_mae_field_cap_t;
+
+typedef struct efx_mae_s {
+ uint32_t em_max_n_action_prios;
+ /*
+ * The number of MAE field IDs recognised by the FW implementation.
+ * Any field ID greater than or equal to this value is unsupported.
+ */
+ uint32_t em_max_nfields;
+ /** Action rule match field capabilities. */
+ efx_mae_field_cap_t *em_action_rule_field_caps;
+ size_t em_action_rule_field_caps_size;
+ uint32_t em_max_n_outer_prios;
+ uint32_t em_encap_types_supported;
+ /** Outer rule match field capabilities. */
+ efx_mae_field_cap_t *em_outer_rule_field_caps;
+ size_t em_outer_rule_field_caps_size;
+} efx_mae_t;
+
+#endif /* EFSYS_OPT_MAE */
+
#define EFX_DRV_VER_MAX 20
typedef struct efx_drv_cfg_s {
#if EFSYS_OPT_VPD
const efx_vpd_ops_t *en_evpdop;
#endif /* EFSYS_OPT_VPD */
+#if EFSYS_OPT_VIRTIO
+ const efx_virtio_ops_t *en_evop;
+#endif /* EFSYS_OPT_VPD */
#if EFSYS_OPT_RX_SCALE
efx_rx_hash_support_t en_hash_support;
efx_rx_scale_context_type_t en_rss_context_type;
int ena_vi_base;
int ena_vi_count;
int ena_vi_shift;
+ uint32_t ena_fcw_base;
#if EFSYS_OPT_VPD
caddr_t ena_svpd;
size_t ena_svpd_length;
#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
const efx_proxy_ops_t *en_epop;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+#if EFSYS_OPT_MAE
+ efx_mae_t *en_maep;
+#endif /* EFSYS_OPT_MAE */
};
#define EFX_FAMILY_IS_EF10(_enp) \
typedef boolean_t (*efx_ev_handler_t)(efx_evq_t *, efx_qword_t *,
const efx_ev_callbacks_t *, void *);
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+typedef boolean_t (*efx_ev_ew_handler_t)(efx_evq_t *, efx_xword_t *,
+ const efx_ev_callbacks_t *, void *);
+#endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
+
typedef struct efx_evq_rxq_state_s {
unsigned int eers_rx_read_ptr;
unsigned int eers_rx_mask;
efx_ev_handler_t ee_mcdi;
#endif /* EFSYS_OPT_MCDI */
+#if EFSYS_OPT_DESC_PROXY
+ efx_ev_ew_handler_t ee_ew_txq_desc;
+ efx_ev_ew_handler_t ee_ew_virtq_desc;
+#endif /* EFSYS_OPT_DESC_PROXY */
+
efx_evq_rxq_state_t ee_rxq_state[EFX_EV_RX_NLABELS];
};
size_t er_buf_size;
efsys_mem_t *er_esmp;
efx_evq_rxq_state_t *er_ev_qstate;
+ efx_rx_prefix_layout_t er_prefix_layout;
};
#define EFX_RXQ_MAGIC 0x15022005
* Code used on EF10 *must* use EFX_BAR_VI_*() macros for per-VI registers,
* to ensure the correct runtime VI window size is used on Medford2.
*
+ * Code used on EF100 *must* use EFX_BAR_FCW_* macros for function control
+ * window registers, to ensure the correct starting offset is used.
+ *
* Siena-only code may continue using EFX_BAR_TBL_*() macros for VI registers.
*/
_NOTE(CONSTANTCONDITION) \
} while (B_FALSE)
+/*
+ * Accessors for memory BAR function control window registers.
+ *
+ * The function control window is located at an offset which can be
+ * non-zero in case of Riverhead.
+ */
+
+#if EFSYS_OPT_RIVERHEAD
+
+#define EFX_BAR_FCW_READD(_enp, _reg, _edp) \
+ do { \
+ EFX_CHECK_REG((_enp), (_reg)); \
+ EFSYS_BAR_READD((_enp)->en_esbp, _reg ## _OFST + \
+ (_enp)->en_arch.ef10.ena_fcw_base, \
+ (_edp), B_FALSE); \
+ EFSYS_PROBE3(efx_bar_fcw_readd, const char *, #_reg, \
+ uint32_t, _reg ## _OFST, \
+ uint32_t, (_edp)->ed_u32[0]); \
+ _NOTE(CONSTANTCONDITION) \
+ } while (B_FALSE)
+
+#define EFX_BAR_FCW_WRITED(_enp, _reg, _edp) \
+ do { \
+ EFX_CHECK_REG((_enp), (_reg)); \
+ EFSYS_PROBE3(efx_bar_fcw_writed, const char *, #_reg, \
+ uint32_t, _reg ## _OFST, \
+ uint32_t, (_edp)->ed_u32[0]); \
+ EFSYS_BAR_WRITED((_enp)->en_esbp, _reg ## _OFST + \
+ (_enp)->en_arch.ef10.ena_fcw_base, \
+ (_edp), B_FALSE); \
+ _NOTE(CONSTANTCONDITION) \
+ } while (B_FALSE)
+
+#endif /* EFSYS_OPT_RIVERHEAD */
+
/*
* Accessors for memory BAR per-VI registers.
*
_NOTE(CONSTANTCONDITION) \
} while (B_FALSE)
-#define EFX_DMA_SYNC_QUEUE_FOR_DEVICE(_esmp, _entries, _wptr, _owptr) \
+#define EFX_DMA_SYNC_QUEUE_FOR_DEVICE(_esmp, _entries, _desc_size, \
+ _wptr, _owptr) \
do { \
unsigned int _new = (_wptr); \
unsigned int _old = (_owptr); \
\
if ((_new) >= (_old)) \
EFSYS_DMA_SYNC_FOR_DEVICE((_esmp), \
- (_old) * sizeof (efx_desc_t), \
- ((_new) - (_old)) * sizeof (efx_desc_t)); \
+ (_old) * (_desc_size), \
+ ((_new) - (_old)) * (_desc_size)); \
else \
/* \
* It is cheaper to sync entire map than sync \
*/ \
EFSYS_DMA_SYNC_FOR_DEVICE((_esmp), \
0, \
- (_entries) * sizeof (efx_desc_t)); \
+ (_entries) * (_desc_size)); \
_NOTE(CONSTANTCONDITION) \
} while (B_FALSE)
__out_opt uint32_t *implementedp,
__out_opt uint32_t *enabledp);
-#if EFX_OPTS_EF10()
+#if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
LIBEFX_INTERNAL
extern __checkReturn efx_rc_t
__in efx_nic_t *enp,
__in uint32_t instance);
-#endif /* EFX_OPTS_EF10() */
+typedef struct efx_mcdi_init_rxq_params_s {
+ boolean_t disable_scatter;
+ boolean_t want_inner_classes;
+ uint32_t buf_size;
+ uint32_t ps_buf_size;
+ uint32_t es_bufs_per_desc;
+ uint32_t es_max_dma_len;
+ uint32_t es_buf_stride;
+ uint32_t hol_block_timeout;
+ uint32_t prefix_id;
+} efx_mcdi_init_rxq_params_t;
+
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_mcdi_init_rxq(
+ __in efx_nic_t *enp,
+ __in uint32_t ndescs,
+ __in efx_evq_t *eep,
+ __in uint32_t label,
+ __in uint32_t instance,
+ __in efsys_mem_t *esmp,
+ __in const efx_mcdi_init_rxq_params_t *params);
+
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_mcdi_fini_rxq(
+ __in efx_nic_t *enp,
+ __in uint32_t instance);
+
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_mcdi_init_txq(
+ __in efx_nic_t *enp,
+ __in uint32_t ndescs,
+ __in uint32_t target_evq,
+ __in uint32_t label,
+ __in uint32_t instance,
+ __in uint16_t flags,
+ __in efsys_mem_t *esmp);
+
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_mcdi_fini_txq(
+ __in efx_nic_t *enp,
+ __in uint32_t instance);
+
+#endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
#endif /* EFSYS_OPT_MCDI */
#endif /* EFSYS_OPT_MAC_STATS */
+#if EFSYS_OPT_PCI
+
+/*
+ * Find the next extended capability in a PCI device's config space
+ * with specified capability id.
+ * Passing 0 offset makes the function search from the start.
+ * If search succeeds, found capability is in modified offset.
+ *
+ * Returns ENOENT if a capability is not found.
+ */
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_pci_config_find_next_ext_cap(
+ __in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
+ __in uint16_t cap_id,
+ __inout size_t *offsetp);
+
+/*
+ * Get the next extended capability in a PCI device's config space.
+ * Passing 0 offset makes the function get the first capability.
+ * If search succeeds, the capability is in modified offset.
+ *
+ * Returns ENOENT if there is no next capability.
+ */
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_pci_config_next_ext_cap(
+ __in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
+ __inout size_t *offsetp);
+
+/*
+ * Find the next Xilinx capabilities table location by searching
+ * PCI extended capabilities.
+ *
+ * Returns ENOENT if a table location is not found.
+ */
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_pci_find_next_xilinx_cap_table(
+ __in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
+ __inout size_t *pci_cap_offsetp,
+ __out unsigned int *xilinx_tbl_barp,
+ __out efsys_dma_addr_t *xilinx_tbl_offsetp);
+
+/*
+ * Read a Xilinx extended PCI capability that gives the location
+ * of a Xilinx capabilities table.
+ *
+ * Returns ENOENT if the extended PCI capability does not contain
+ * Xilinx capabilities table locator.
+ */
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_pci_read_ext_cap_xilinx_table(
+ __in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
+ __in size_t cap_offset,
+ __out unsigned int *barp,
+ __out efsys_dma_addr_t *offsetp);
+
+/*
+ * Find a capability with specified format_id in a Xilinx capabilities table.
+ * Searching is started from provided offset, taking skip_first into account.
+ * If search succeeds, found capability is in modified offset.
+ *
+ * Returns ENOENT if an entry with specified format id is not found.
+ */
+LIBEFX_INTERNAL
+extern __checkReturn efx_rc_t
+efx_pci_xilinx_cap_tbl_find(
+ __in efsys_bar_t *esbp,
+ __in uint32_t format_id,
+ __in boolean_t skip_first,
+ __inout efsys_dma_addr_t *entry_offsetp);
+
+#endif /* EFSYS_OPT_PCI */
+
+#if EFSYS_OPT_MAE
+
+struct efx_mae_match_spec_s {
+ efx_mae_rule_type_t emms_type;
+ uint32_t emms_prio;
+ union emms_mask_value_pairs {
+ uint8_t action[
+ MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN];
+ uint8_t outer[MAE_ENC_FIELD_PAIRS_LEN];
+ } emms_mask_value_pairs;
+};
+
+typedef enum efx_mae_action_e {
+ /* These actions are strictly ordered. */
+ EFX_MAE_ACTION_DECAP,
+ EFX_MAE_ACTION_VLAN_POP,
+ EFX_MAE_ACTION_VLAN_PUSH,
+ EFX_MAE_ACTION_ENCAP,
+
+ /*
+ * These actions are not strictly ordered and can
+ * be passed by a client in any order (before DELIVER).
+ * However, these enumerants must be kept compactly
+ * in the end of the enumeration (before DELIVER).
+ */
+ EFX_MAE_ACTION_FLAG,
+ EFX_MAE_ACTION_MARK,
+
+ /* DELIVER is always the last action. */
+ EFX_MAE_ACTION_DELIVER,
+
+ EFX_MAE_NACTIONS
+} efx_mae_action_t;
+
+/* MAE VLAN_POP action can handle 1 or 2 tags. */
+#define EFX_MAE_VLAN_POP_MAX_NTAGS (2)
+
+/* MAE VLAN_PUSH action can handle 1 or 2 tags. */
+#define EFX_MAE_VLAN_PUSH_MAX_NTAGS (2)
+
+typedef struct efx_mae_action_vlan_push_s {
+ uint16_t emavp_tpid_be;
+ uint16_t emavp_tci_be;
+} efx_mae_action_vlan_push_t;
+
+typedef struct efx_mae_actions_rsrc_s {
+ efx_mae_eh_id_t emar_eh_id;
+} efx_mae_actions_rsrc_t;
+
+struct efx_mae_actions_s {
+ /* Bitmap of actions in spec, indexed by action type */
+ uint32_t ema_actions;
+
+ unsigned int ema_n_vlan_tags_to_pop;
+ unsigned int ema_n_vlan_tags_to_push;
+ efx_mae_action_vlan_push_t ema_vlan_push_descs[
+ EFX_MAE_VLAN_PUSH_MAX_NTAGS];
+ uint32_t ema_mark_value;
+ efx_mport_sel_t ema_deliver_mport;
+
+ /*
+ * Always keep this at the end of the struct since
+ * efx_mae_action_set_specs_equal() relies on that
+ * to make sure that resource IDs are not compared.
+ */
+ efx_mae_actions_rsrc_t ema_rsrc;
+};
+
+#endif /* EFSYS_OPT_MAE */
+
+#if EFSYS_OPT_VIRTIO
+
+#define EFX_VQ_MAGIC 0x026011950
+
+typedef enum efx_virtio_vq_state_e {
+ EFX_VIRTIO_VQ_STATE_UNKNOWN = 0,
+ EFX_VIRTIO_VQ_STATE_INITIALIZED,
+ EFX_VIRTIO_VQ_STATE_STARTED,
+ EFX_VIRTIO_VQ_NSTATES
+} efx_virtio_vq_state_t;
+
+struct efx_virtio_vq_s {
+ uint32_t evv_magic;
+ efx_nic_t *evv_enp;
+ efx_virtio_vq_state_t evv_state;
+ uint32_t evv_vi_index;
+ efx_virtio_vq_type_t evv_type;
+ uint16_t evv_target_vf;
+};
+
+#endif /* EFSYS_OPT_VIRTIO */
+
#ifdef __cplusplus
}
#endif