Index: stable/12/sys/dev/sfxge/common/efx_impl.h =================================================================== --- stable/12/sys/dev/sfxge/common/efx_impl.h (revision 342314) +++ stable/12/sys/dev/sfxge/common/efx_impl.h (revision 342315) @@ -1,1192 +1,1166 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007-2016 Solarflare Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the FreeBSD Project. * * $FreeBSD$ */ #ifndef _SYS_EFX_IMPL_H #define _SYS_EFX_IMPL_H #include "efx.h" #include "efx_regs.h" #include "efx_regs_ef10.h" /* FIXME: Add definition for driver generated software events */ #ifndef ESE_DZ_EV_CODE_DRV_GEN_EV #define ESE_DZ_EV_CODE_DRV_GEN_EV FSE_AZ_EV_CODE_DRV_GEN_EV #endif #if EFSYS_OPT_SIENA #include "siena_impl.h" #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON #include "hunt_impl.h" #endif /* EFSYS_OPT_HUNTINGTON */ #if EFSYS_OPT_MEDFORD #include "medford_impl.h" #endif /* EFSYS_OPT_MEDFORD */ #if (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD) #include "ef10_impl.h" #endif /* (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD) */ #ifdef __cplusplus extern "C" { #endif #define EFX_MOD_MCDI 0x00000001 #define EFX_MOD_PROBE 0x00000002 #define EFX_MOD_NVRAM 0x00000004 #define EFX_MOD_VPD 0x00000008 #define EFX_MOD_NIC 0x00000010 #define EFX_MOD_INTR 0x00000020 #define EFX_MOD_EV 0x00000040 #define EFX_MOD_RX 0x00000080 #define EFX_MOD_TX 0x00000100 #define EFX_MOD_PORT 0x00000200 #define EFX_MOD_MON 0x00000400 #define EFX_MOD_FILTER 0x00001000 #define EFX_MOD_LIC 0x00002000 #define EFX_RESET_PHY 0x00000001 #define EFX_RESET_RXQ_ERR 0x00000002 #define EFX_RESET_TXQ_ERR 0x00000004 typedef enum efx_mac_type_e { EFX_MAC_INVALID = 0, EFX_MAC_SIENA, EFX_MAC_HUNTINGTON, EFX_MAC_MEDFORD, EFX_MAC_NTYPES } efx_mac_type_t; typedef struct efx_ev_ops_s { efx_rc_t (*eevo_init)(efx_nic_t *); void (*eevo_fini)(efx_nic_t *); efx_rc_t (*eevo_qcreate)(efx_nic_t *, unsigned int, efsys_mem_t *, size_t, uint32_t, uint32_t, uint32_t, efx_evq_t *); void (*eevo_qdestroy)(efx_evq_t *); efx_rc_t (*eevo_qprime)(efx_evq_t *, unsigned int); void (*eevo_qpost)(efx_evq_t *, uint16_t); efx_rc_t (*eevo_qmoderate)(efx_evq_t *, unsigned int); #if EFSYS_OPT_QSTATS void (*eevo_qstats_update)(efx_evq_t *, efsys_stat_t *); #endif } efx_ev_ops_t; typedef struct efx_tx_ops_s { efx_rc_t (*etxo_init)(efx_nic_t *); void (*etxo_fini)(efx_nic_t *); efx_rc_t (*etxo_qcreate)(efx_nic_t *, unsigned int, unsigned int, efsys_mem_t *, size_t, uint32_t, uint16_t, efx_evq_t *, efx_txq_t *, unsigned int *); void (*etxo_qdestroy)(efx_txq_t *); efx_rc_t (*etxo_qpost)(efx_txq_t *, efx_buffer_t *, unsigned int, unsigned int, unsigned int *); void (*etxo_qpush)(efx_txq_t *, unsigned int, unsigned int); efx_rc_t (*etxo_qpace)(efx_txq_t *, unsigned int); efx_rc_t (*etxo_qflush)(efx_txq_t *); void (*etxo_qenable)(efx_txq_t *); efx_rc_t (*etxo_qpio_enable)(efx_txq_t *); void (*etxo_qpio_disable)(efx_txq_t *); efx_rc_t (*etxo_qpio_write)(efx_txq_t *, uint8_t *, size_t, size_t); efx_rc_t (*etxo_qpio_post)(efx_txq_t *, size_t, unsigned int, unsigned int *); efx_rc_t (*etxo_qdesc_post)(efx_txq_t *, efx_desc_t *, unsigned int, unsigned int, unsigned int *); void (*etxo_qdesc_dma_create)(efx_txq_t *, efsys_dma_addr_t, size_t, boolean_t, efx_desc_t *); void (*etxo_qdesc_tso_create)(efx_txq_t *, uint16_t, uint32_t, uint8_t, efx_desc_t *); void (*etxo_qdesc_tso2_create)(efx_txq_t *, uint16_t, uint32_t, uint16_t, efx_desc_t *, int); void (*etxo_qdesc_vlantci_create)(efx_txq_t *, uint16_t, efx_desc_t *); #if EFSYS_OPT_QSTATS void (*etxo_qstats_update)(efx_txq_t *, efsys_stat_t *); #endif } efx_tx_ops_t; typedef struct efx_rx_ops_s { efx_rc_t (*erxo_init)(efx_nic_t *); void (*erxo_fini)(efx_nic_t *); #if EFSYS_OPT_RX_SCATTER efx_rc_t (*erxo_scatter_enable)(efx_nic_t *, unsigned int); #endif #if EFSYS_OPT_RX_SCALE efx_rc_t (*erxo_scale_mode_set)(efx_nic_t *, efx_rx_hash_alg_t, efx_rx_hash_type_t, boolean_t); efx_rc_t (*erxo_scale_key_set)(efx_nic_t *, uint8_t *, size_t); efx_rc_t (*erxo_scale_tbl_set)(efx_nic_t *, unsigned int *, size_t); uint32_t (*erxo_prefix_hash)(efx_nic_t *, efx_rx_hash_alg_t, uint8_t *); #endif /* EFSYS_OPT_RX_SCALE */ efx_rc_t (*erxo_prefix_pktlen)(efx_nic_t *, uint8_t *, uint16_t *); void (*erxo_qpost)(efx_rxq_t *, efsys_dma_addr_t *, size_t, unsigned int, unsigned int, unsigned int); void (*erxo_qpush)(efx_rxq_t *, unsigned int, unsigned int *); efx_rc_t (*erxo_qflush)(efx_rxq_t *); void (*erxo_qenable)(efx_rxq_t *); efx_rc_t (*erxo_qcreate)(efx_nic_t *enp, unsigned int, unsigned int, efx_rxq_type_t, efsys_mem_t *, size_t, uint32_t, efx_evq_t *, efx_rxq_t *); void (*erxo_qdestroy)(efx_rxq_t *); } efx_rx_ops_t; typedef struct efx_mac_ops_s { efx_rc_t (*emo_poll)(efx_nic_t *, efx_link_mode_t *); efx_rc_t (*emo_up)(efx_nic_t *, boolean_t *); efx_rc_t (*emo_addr_set)(efx_nic_t *); efx_rc_t (*emo_pdu_set)(efx_nic_t *); efx_rc_t (*emo_pdu_get)(efx_nic_t *, size_t *); efx_rc_t (*emo_reconfigure)(efx_nic_t *); efx_rc_t (*emo_multicast_list_set)(efx_nic_t *); efx_rc_t (*emo_filter_default_rxq_set)(efx_nic_t *, efx_rxq_t *, boolean_t); void (*emo_filter_default_rxq_clear)(efx_nic_t *); #if EFSYS_OPT_LOOPBACK efx_rc_t (*emo_loopback_set)(efx_nic_t *, efx_link_mode_t, efx_loopback_type_t); #endif /* EFSYS_OPT_LOOPBACK */ #if EFSYS_OPT_MAC_STATS efx_rc_t (*emo_stats_get_mask)(efx_nic_t *, uint32_t *, size_t); efx_rc_t (*emo_stats_upload)(efx_nic_t *, efsys_mem_t *); efx_rc_t (*emo_stats_periodic)(efx_nic_t *, efsys_mem_t *, uint16_t, boolean_t); efx_rc_t (*emo_stats_update)(efx_nic_t *, efsys_mem_t *, efsys_stat_t *, uint32_t *); #endif /* EFSYS_OPT_MAC_STATS */ } efx_mac_ops_t; typedef struct efx_phy_ops_s { efx_rc_t (*epo_power)(efx_nic_t *, boolean_t); /* optional */ efx_rc_t (*epo_reset)(efx_nic_t *); efx_rc_t (*epo_reconfigure)(efx_nic_t *); efx_rc_t (*epo_verify)(efx_nic_t *); efx_rc_t (*epo_oui_get)(efx_nic_t *, uint32_t *); #if EFSYS_OPT_PHY_STATS efx_rc_t (*epo_stats_update)(efx_nic_t *, efsys_mem_t *, uint32_t *); #endif /* EFSYS_OPT_PHY_STATS */ #if EFSYS_OPT_BIST efx_rc_t (*epo_bist_enable_offline)(efx_nic_t *); efx_rc_t (*epo_bist_start)(efx_nic_t *, efx_bist_type_t); efx_rc_t (*epo_bist_poll)(efx_nic_t *, efx_bist_type_t, efx_bist_result_t *, uint32_t *, unsigned long *, size_t); void (*epo_bist_stop)(efx_nic_t *, efx_bist_type_t); #endif /* EFSYS_OPT_BIST */ } efx_phy_ops_t; #if EFSYS_OPT_FILTER typedef struct efx_filter_ops_s { efx_rc_t (*efo_init)(efx_nic_t *); void (*efo_fini)(efx_nic_t *); efx_rc_t (*efo_restore)(efx_nic_t *); efx_rc_t (*efo_add)(efx_nic_t *, efx_filter_spec_t *, boolean_t may_replace); efx_rc_t (*efo_delete)(efx_nic_t *, efx_filter_spec_t *); efx_rc_t (*efo_supported_filters)(efx_nic_t *, uint32_t *, size_t, size_t *); efx_rc_t (*efo_reconfigure)(efx_nic_t *, uint8_t const *, boolean_t, boolean_t, boolean_t, boolean_t, uint8_t const *, uint32_t); } efx_filter_ops_t; extern __checkReturn efx_rc_t efx_filter_reconfigure( __in efx_nic_t *enp, __in_ecount(6) uint8_t const *mac_addr, __in boolean_t all_unicst, __in boolean_t mulcst, __in boolean_t all_mulcst, __in boolean_t brdcst, __in_ecount(6*count) uint8_t const *addrs, __in uint32_t count); #endif /* EFSYS_OPT_FILTER */ typedef struct efx_port_s { efx_mac_type_t ep_mac_type; uint32_t ep_phy_type; uint8_t ep_port; uint32_t ep_mac_pdu; uint8_t ep_mac_addr[6]; efx_link_mode_t ep_link_mode; boolean_t ep_all_unicst; boolean_t ep_mulcst; boolean_t ep_all_mulcst; boolean_t ep_brdcst; unsigned int ep_fcntl; boolean_t ep_fcntl_autoneg; efx_oword_t ep_multicst_hash[2]; uint8_t ep_mulcst_addr_list[EFX_MAC_ADDR_LEN * EFX_MAC_MULTICAST_LIST_MAX]; uint32_t ep_mulcst_addr_count; #if EFSYS_OPT_LOOPBACK efx_loopback_type_t ep_loopback_type; efx_link_mode_t ep_loopback_link_mode; #endif /* EFSYS_OPT_LOOPBACK */ #if EFSYS_OPT_PHY_FLAGS uint32_t ep_phy_flags; #endif /* EFSYS_OPT_PHY_FLAGS */ #if EFSYS_OPT_PHY_LED_CONTROL efx_phy_led_mode_t ep_phy_led_mode; #endif /* EFSYS_OPT_PHY_LED_CONTROL */ efx_phy_media_type_t ep_fixed_port_type; efx_phy_media_type_t ep_module_type; uint32_t ep_adv_cap_mask; uint32_t ep_lp_cap_mask; uint32_t ep_default_adv_cap_mask; uint32_t ep_phy_cap_mask; boolean_t ep_mac_drain; boolean_t ep_mac_stats_pending; #if EFSYS_OPT_BIST efx_bist_type_t ep_current_bist; #endif const efx_mac_ops_t *ep_emop; const efx_phy_ops_t *ep_epop; } efx_port_t; typedef struct efx_mon_ops_s { #if EFSYS_OPT_MON_STATS efx_rc_t (*emo_stats_update)(efx_nic_t *, efsys_mem_t *, efx_mon_stat_value_t *); #endif /* EFSYS_OPT_MON_STATS */ } efx_mon_ops_t; typedef struct efx_mon_s { efx_mon_type_t em_type; const efx_mon_ops_t *em_emop; } efx_mon_t; typedef struct efx_intr_ops_s { efx_rc_t (*eio_init)(efx_nic_t *, efx_intr_type_t, efsys_mem_t *); void (*eio_enable)(efx_nic_t *); void (*eio_disable)(efx_nic_t *); void (*eio_disable_unlocked)(efx_nic_t *); efx_rc_t (*eio_trigger)(efx_nic_t *, unsigned int); void (*eio_status_line)(efx_nic_t *, boolean_t *, uint32_t *); void (*eio_status_message)(efx_nic_t *, unsigned int, boolean_t *); void (*eio_fatal)(efx_nic_t *); void (*eio_fini)(efx_nic_t *); } efx_intr_ops_t; typedef struct efx_intr_s { const efx_intr_ops_t *ei_eiop; efsys_mem_t *ei_esmp; efx_intr_type_t ei_type; unsigned int ei_level; } efx_intr_t; typedef struct efx_nic_ops_s { efx_rc_t (*eno_probe)(efx_nic_t *); efx_rc_t (*eno_board_cfg)(efx_nic_t *); efx_rc_t (*eno_set_drv_limits)(efx_nic_t *, efx_drv_limits_t*); efx_rc_t (*eno_reset)(efx_nic_t *); efx_rc_t (*eno_init)(efx_nic_t *); efx_rc_t (*eno_get_vi_pool)(efx_nic_t *, uint32_t *); efx_rc_t (*eno_get_bar_region)(efx_nic_t *, efx_nic_region_t, uint32_t *, size_t *); #if EFSYS_OPT_DIAG efx_rc_t (*eno_register_test)(efx_nic_t *); #endif /* EFSYS_OPT_DIAG */ void (*eno_fini)(efx_nic_t *); void (*eno_unprobe)(efx_nic_t *); } efx_nic_ops_t; #ifndef EFX_TXQ_LIMIT_TARGET #define EFX_TXQ_LIMIT_TARGET 259 #endif #ifndef EFX_RXQ_LIMIT_TARGET #define EFX_RXQ_LIMIT_TARGET 512 #endif #ifndef EFX_TXQ_DC_SIZE #define EFX_TXQ_DC_SIZE 1 /* 16 descriptors */ #endif #ifndef EFX_RXQ_DC_SIZE #define EFX_RXQ_DC_SIZE 3 /* 64 descriptors */ #endif #if EFSYS_OPT_FILTER typedef struct siena_filter_spec_s { uint8_t sfs_type; uint32_t sfs_flags; uint32_t sfs_dmaq_id; uint32_t sfs_dword[3]; } siena_filter_spec_t; typedef enum siena_filter_type_e { EFX_SIENA_FILTER_RX_TCP_FULL, /* TCP/IPv4 {dIP,dTCP,sIP,sTCP} */ EFX_SIENA_FILTER_RX_TCP_WILD, /* TCP/IPv4 {dIP,dTCP, -, -} */ EFX_SIENA_FILTER_RX_UDP_FULL, /* UDP/IPv4 {dIP,dUDP,sIP,sUDP} */ EFX_SIENA_FILTER_RX_UDP_WILD, /* UDP/IPv4 {dIP,dUDP, -, -} */ EFX_SIENA_FILTER_RX_MAC_FULL, /* Ethernet {dMAC,VLAN} */ EFX_SIENA_FILTER_RX_MAC_WILD, /* Ethernet {dMAC, -} */ EFX_SIENA_FILTER_TX_TCP_FULL, /* TCP/IPv4 {dIP,dTCP,sIP,sTCP} */ EFX_SIENA_FILTER_TX_TCP_WILD, /* TCP/IPv4 { -, -,sIP,sTCP} */ EFX_SIENA_FILTER_TX_UDP_FULL, /* UDP/IPv4 {dIP,dTCP,sIP,sTCP} */ EFX_SIENA_FILTER_TX_UDP_WILD, /* UDP/IPv4 { -, -,sIP,sUDP} */ EFX_SIENA_FILTER_TX_MAC_FULL, /* Ethernet {sMAC,VLAN} */ EFX_SIENA_FILTER_TX_MAC_WILD, /* Ethernet {sMAC, -} */ EFX_SIENA_FILTER_NTYPES } siena_filter_type_t; typedef enum siena_filter_tbl_id_e { EFX_SIENA_FILTER_TBL_RX_IP = 0, EFX_SIENA_FILTER_TBL_RX_MAC, EFX_SIENA_FILTER_TBL_TX_IP, EFX_SIENA_FILTER_TBL_TX_MAC, EFX_SIENA_FILTER_NTBLS } siena_filter_tbl_id_t; typedef struct siena_filter_tbl_s { int sft_size; /* number of entries */ int sft_used; /* active count */ uint32_t *sft_bitmap; /* active bitmap */ siena_filter_spec_t *sft_spec; /* array of saved specs */ } siena_filter_tbl_t; typedef struct siena_filter_s { siena_filter_tbl_t sf_tbl[EFX_SIENA_FILTER_NTBLS]; unsigned int sf_depth[EFX_SIENA_FILTER_NTYPES]; } siena_filter_t; typedef struct efx_filter_s { #if EFSYS_OPT_SIENA siena_filter_t *ef_siena_filter; #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD ef10_filter_table_t *ef_ef10_filter_table; #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ } efx_filter_t; extern void siena_filter_tbl_clear( __in efx_nic_t *enp, __in siena_filter_tbl_id_t tbl); #endif /* EFSYS_OPT_FILTER */ #if EFSYS_OPT_MCDI typedef struct efx_mcdi_ops_s { efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *); void (*emco_send_request)(efx_nic_t *, void *, size_t, void *, size_t); efx_rc_t (*emco_poll_reboot)(efx_nic_t *); boolean_t (*emco_poll_response)(efx_nic_t *); void (*emco_read_response)(efx_nic_t *, void *, size_t, size_t); void (*emco_fini)(efx_nic_t *); efx_rc_t (*emco_feature_supported)(efx_nic_t *, efx_mcdi_feature_id_t, boolean_t *); void (*emco_get_timeout)(efx_nic_t *, efx_mcdi_req_t *, uint32_t *); } efx_mcdi_ops_t; typedef struct efx_mcdi_s { const efx_mcdi_ops_t *em_emcop; const efx_mcdi_transport_t *em_emtp; efx_mcdi_iface_t em_emip; } efx_mcdi_t; #endif /* EFSYS_OPT_MCDI */ #if EFSYS_OPT_NVRAM typedef struct efx_nvram_ops_s { #if EFSYS_OPT_DIAG efx_rc_t (*envo_test)(efx_nic_t *); #endif /* EFSYS_OPT_DIAG */ efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t, uint32_t *); efx_rc_t (*envo_partn_size)(efx_nic_t *, uint32_t, size_t *); efx_rc_t (*envo_partn_rw_start)(efx_nic_t *, uint32_t, size_t *); efx_rc_t (*envo_partn_read)(efx_nic_t *, uint32_t, unsigned int, caddr_t, size_t); efx_rc_t (*envo_partn_erase)(efx_nic_t *, uint32_t, unsigned int, size_t); efx_rc_t (*envo_partn_write)(efx_nic_t *, uint32_t, unsigned int, caddr_t, size_t); efx_rc_t (*envo_partn_rw_finish)(efx_nic_t *, uint32_t); efx_rc_t (*envo_partn_get_version)(efx_nic_t *, uint32_t, uint32_t *, uint16_t *); efx_rc_t (*envo_partn_set_version)(efx_nic_t *, uint32_t, uint16_t *); efx_rc_t (*envo_buffer_validate)(efx_nic_t *, uint32_t, caddr_t, size_t); } efx_nvram_ops_t; #endif /* EFSYS_OPT_NVRAM */ #if EFSYS_OPT_VPD typedef struct efx_vpd_ops_s { efx_rc_t (*evpdo_init)(efx_nic_t *); efx_rc_t (*evpdo_size)(efx_nic_t *, size_t *); efx_rc_t (*evpdo_read)(efx_nic_t *, caddr_t, size_t); efx_rc_t (*evpdo_verify)(efx_nic_t *, caddr_t, size_t); efx_rc_t (*evpdo_reinit)(efx_nic_t *, caddr_t, size_t); efx_rc_t (*evpdo_get)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *); efx_rc_t (*evpdo_set)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *); efx_rc_t (*evpdo_next)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *, unsigned int *); efx_rc_t (*evpdo_write)(efx_nic_t *, caddr_t, size_t); void (*evpdo_fini)(efx_nic_t *); } efx_vpd_ops_t; #endif /* EFSYS_OPT_VPD */ #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM __checkReturn efx_rc_t efx_mcdi_nvram_partitions( __in efx_nic_t *enp, __out_bcount(size) caddr_t data, __in size_t size, __out unsigned int *npartnp); __checkReturn efx_rc_t efx_mcdi_nvram_metadata( __in efx_nic_t *enp, __in uint32_t partn, __out uint32_t *subtypep, __out_ecount(4) uint16_t version[4], __out_bcount_opt(size) char *descp, __in size_t size); __checkReturn efx_rc_t efx_mcdi_nvram_info( __in efx_nic_t *enp, __in uint32_t partn, __out_opt size_t *sizep, __out_opt uint32_t *addressp, __out_opt uint32_t *erase_sizep, __out_opt uint32_t *write_sizep); __checkReturn efx_rc_t efx_mcdi_nvram_update_start( __in efx_nic_t *enp, __in uint32_t partn); __checkReturn efx_rc_t efx_mcdi_nvram_read( __in efx_nic_t *enp, __in uint32_t partn, __in uint32_t offset, __out_bcount(size) caddr_t data, __in size_t size, __in uint32_t mode); __checkReturn efx_rc_t efx_mcdi_nvram_erase( __in efx_nic_t *enp, __in uint32_t partn, __in uint32_t offset, __in size_t size); __checkReturn efx_rc_t efx_mcdi_nvram_write( __in efx_nic_t *enp, __in uint32_t partn, __in uint32_t offset, __out_bcount(size) caddr_t data, __in size_t size); __checkReturn efx_rc_t efx_mcdi_nvram_update_finish( __in efx_nic_t *enp, __in uint32_t partn, __in boolean_t reboot, __out_opt uint32_t *resultp); #if EFSYS_OPT_DIAG __checkReturn efx_rc_t efx_mcdi_nvram_test( __in efx_nic_t *enp, __in uint32_t partn); #endif /* EFSYS_OPT_DIAG */ #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ #if EFSYS_OPT_LICENSING typedef struct efx_lic_ops_s { efx_rc_t (*elo_update_licenses)(efx_nic_t *); efx_rc_t (*elo_get_key_stats)(efx_nic_t *, efx_key_stats_t *); efx_rc_t (*elo_app_state)(efx_nic_t *, uint64_t, boolean_t *); efx_rc_t (*elo_get_id)(efx_nic_t *, size_t, uint32_t *, size_t *, uint8_t *); efx_rc_t (*elo_find_start) (efx_nic_t *, caddr_t, size_t, uint32_t *); efx_rc_t (*elo_find_end)(efx_nic_t *, caddr_t, size_t, uint32_t, uint32_t *); boolean_t (*elo_find_key)(efx_nic_t *, caddr_t, size_t, uint32_t, uint32_t *, uint32_t *); boolean_t (*elo_validate_key)(efx_nic_t *, caddr_t, uint32_t); efx_rc_t (*elo_read_key)(efx_nic_t *, caddr_t, size_t, uint32_t, uint32_t, caddr_t, size_t, uint32_t *); efx_rc_t (*elo_write_key)(efx_nic_t *, caddr_t, size_t, uint32_t, caddr_t, uint32_t, uint32_t *); efx_rc_t (*elo_delete_key)(efx_nic_t *, caddr_t, size_t, uint32_t, uint32_t, uint32_t, uint32_t *); efx_rc_t (*elo_create_partition)(efx_nic_t *, caddr_t, size_t); efx_rc_t (*elo_finish_partition)(efx_nic_t *, caddr_t, size_t); } efx_lic_ops_t; #endif typedef struct efx_drv_cfg_s { uint32_t edc_min_vi_count; uint32_t edc_max_vi_count; uint32_t edc_max_piobuf_count; uint32_t edc_pio_alloc_size; } efx_drv_cfg_t; struct efx_nic_s { uint32_t en_magic; efx_family_t en_family; uint32_t en_features; efsys_identifier_t *en_esip; efsys_lock_t *en_eslp; efsys_bar_t *en_esbp; unsigned int en_mod_flags; unsigned int en_reset_flags; efx_nic_cfg_t en_nic_cfg; efx_drv_cfg_t en_drv_cfg; efx_port_t en_port; efx_mon_t en_mon; efx_intr_t en_intr; uint32_t en_ev_qcount; uint32_t en_rx_qcount; uint32_t en_tx_qcount; const efx_nic_ops_t *en_enop; const efx_ev_ops_t *en_eevop; const efx_tx_ops_t *en_etxop; const efx_rx_ops_t *en_erxop; #if EFSYS_OPT_FILTER efx_filter_t en_filter; const efx_filter_ops_t *en_efop; #endif /* EFSYS_OPT_FILTER */ #if EFSYS_OPT_MCDI efx_mcdi_t en_mcdi; #endif /* EFSYS_OPT_MCDI */ #if EFSYS_OPT_NVRAM efx_nvram_type_t en_nvram_locked; const efx_nvram_ops_t *en_envop; #endif /* EFSYS_OPT_NVRAM */ #if EFSYS_OPT_VPD const efx_vpd_ops_t *en_evpdop; #endif /* EFSYS_OPT_VPD */ #if EFSYS_OPT_RX_SCALE efx_rx_hash_support_t en_hash_support; efx_rx_scale_support_t en_rss_support; uint32_t en_rss_context; #endif /* EFSYS_OPT_RX_SCALE */ uint32_t en_vport_id; #if EFSYS_OPT_LICENSING const efx_lic_ops_t *en_elop; boolean_t en_licensing_supported; #endif union { #if EFSYS_OPT_SIENA struct { #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD unsigned int enu_partn_mask; #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ #if EFSYS_OPT_VPD caddr_t enu_svpd; size_t enu_svpd_length; #endif /* EFSYS_OPT_VPD */ int enu_unused; } siena; #endif /* EFSYS_OPT_SIENA */ int enu_unused; } en_u; #if (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD) union en_arch { struct { int ena_vi_base; int ena_vi_count; int ena_vi_shift; #if EFSYS_OPT_VPD caddr_t ena_svpd; size_t ena_svpd_length; #endif /* EFSYS_OPT_VPD */ efx_piobuf_handle_t ena_piobuf_handle[EF10_MAX_PIOBUF_NBUFS]; uint32_t ena_piobuf_count; uint32_t ena_pio_alloc_map[EF10_MAX_PIOBUF_NBUFS]; uint32_t ena_pio_write_vi_base; /* Memory BAR mapping regions */ uint32_t ena_uc_mem_map_offset; size_t ena_uc_mem_map_size; uint32_t ena_wc_mem_map_offset; size_t ena_wc_mem_map_size; } ef10; } en_arch; #endif /* (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD) */ }; #define EFX_NIC_MAGIC 0x02121996 typedef boolean_t (*efx_ev_handler_t)(efx_evq_t *, efx_qword_t *, const efx_ev_callbacks_t *, void *); typedef struct efx_evq_rxq_state_s { unsigned int eers_rx_read_ptr; unsigned int eers_rx_mask; } efx_evq_rxq_state_t; struct efx_evq_s { uint32_t ee_magic; efx_nic_t *ee_enp; unsigned int ee_index; unsigned int ee_mask; efsys_mem_t *ee_esmp; #if EFSYS_OPT_QSTATS uint32_t ee_stat[EV_NQSTATS]; #endif /* EFSYS_OPT_QSTATS */ efx_ev_handler_t ee_rx; efx_ev_handler_t ee_tx; efx_ev_handler_t ee_driver; efx_ev_handler_t ee_global; efx_ev_handler_t ee_drv_gen; #if EFSYS_OPT_MCDI efx_ev_handler_t ee_mcdi; #endif /* EFSYS_OPT_MCDI */ efx_evq_rxq_state_t ee_rxq_state[EFX_EV_RX_NLABELS]; uint32_t ee_flags; }; #define EFX_EVQ_MAGIC 0x08081997 #define EFX_EVQ_SIENA_TIMER_QUANTUM_NS 6144 /* 768 cycles */ struct efx_rxq_s { uint32_t er_magic; efx_nic_t *er_enp; efx_evq_t *er_eep; unsigned int er_index; unsigned int er_label; unsigned int er_mask; efsys_mem_t *er_esmp; }; #define EFX_RXQ_MAGIC 0x15022005 struct efx_txq_s { uint32_t et_magic; efx_nic_t *et_enp; unsigned int et_index; unsigned int et_mask; efsys_mem_t *et_esmp; #if EFSYS_OPT_HUNTINGTON uint32_t et_pio_bufnum; uint32_t et_pio_blknum; uint32_t et_pio_write_offset; uint32_t et_pio_offset; size_t et_pio_size; #endif #if EFSYS_OPT_QSTATS uint32_t et_stat[TX_NQSTATS]; #endif /* EFSYS_OPT_QSTATS */ }; #define EFX_TXQ_MAGIC 0x05092005 #define EFX_MAC_ADDR_COPY(_dst, _src) \ do { \ (_dst)[0] = (_src)[0]; \ (_dst)[1] = (_src)[1]; \ (_dst)[2] = (_src)[2]; \ (_dst)[3] = (_src)[3]; \ (_dst)[4] = (_src)[4]; \ (_dst)[5] = (_src)[5]; \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_MAC_BROADCAST_ADDR_SET(_dst) \ do { \ uint16_t *_d = (uint16_t *)(_dst); \ _d[0] = 0xffff; \ _d[1] = 0xffff; \ _d[2] = 0xffff; \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #if EFSYS_OPT_CHECK_REG #define EFX_CHECK_REG(_enp, _reg) \ do { \ const char *name = #_reg; \ char min = name[4]; \ char max = name[5]; \ char rev; \ \ switch ((_enp)->en_family) { \ case EFX_FAMILY_SIENA: \ rev = 'C'; \ break; \ \ case EFX_FAMILY_HUNTINGTON: \ rev = 'D'; \ break; \ \ case EFX_FAMILY_MEDFORD: \ rev = 'E'; \ break; \ \ default: \ rev = '?'; \ break; \ } \ \ EFSYS_ASSERT3S(rev, >=, min); \ EFSYS_ASSERT3S(rev, <=, max); \ \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #else #define EFX_CHECK_REG(_enp, _reg) do { \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #endif #define EFX_BAR_READD(_enp, _reg, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READD((_enp)->en_esbp, _reg ## _OFST, \ (_edp), (_lock)); \ EFSYS_PROBE3(efx_bar_readd, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_WRITED(_enp, _reg, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE3(efx_bar_writed, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ EFSYS_BAR_WRITED((_enp)->en_esbp, _reg ## _OFST, \ (_edp), (_lock)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_READQ(_enp, _reg, _eqp) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READQ((_enp)->en_esbp, _reg ## _OFST, \ (_eqp)); \ EFSYS_PROBE4(efx_bar_readq, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_eqp)->eq_u32[1], \ uint32_t, (_eqp)->eq_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_WRITEQ(_enp, _reg, _eqp) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE4(efx_bar_writeq, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_eqp)->eq_u32[1], \ uint32_t, (_eqp)->eq_u32[0]); \ EFSYS_BAR_WRITEQ((_enp)->en_esbp, _reg ## _OFST, \ (_eqp)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_READO(_enp, _reg, _eop) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READO((_enp)->en_esbp, _reg ## _OFST, \ (_eop), B_TRUE); \ EFSYS_PROBE6(efx_bar_reado, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_eop)->eo_u32[3], \ uint32_t, (_eop)->eo_u32[2], \ uint32_t, (_eop)->eo_u32[1], \ uint32_t, (_eop)->eo_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_WRITEO(_enp, _reg, _eop) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE6(efx_bar_writeo, const char *, #_reg, \ uint32_t, _reg ## _OFST, \ uint32_t, (_eop)->eo_u32[3], \ uint32_t, (_eop)->eo_u32[2], \ uint32_t, (_eop)->eo_u32[1], \ uint32_t, (_eop)->eo_u32[0]); \ EFSYS_BAR_WRITEO((_enp)->en_esbp, _reg ## _OFST, \ (_eop), B_TRUE); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_READD(_enp, _reg, _index, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READD((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_edp), (_lock)); \ EFSYS_PROBE4(efx_bar_tbl_readd, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_WRITED(_enp, _reg, _index, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE4(efx_bar_tbl_writed, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ EFSYS_BAR_WRITED((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_edp), (_lock)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_WRITED2(_enp, _reg, _index, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE4(efx_bar_tbl_writed, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ EFSYS_BAR_WRITED((_enp)->en_esbp, \ (_reg ## _OFST + \ (2 * sizeof (efx_dword_t)) + \ ((_index) * _reg ## _STEP)), \ (_edp), (_lock)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_WRITED3(_enp, _reg, _index, _edp, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE4(efx_bar_tbl_writed, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_edp)->ed_u32[0]); \ EFSYS_BAR_WRITED((_enp)->en_esbp, \ (_reg ## _OFST + \ (3 * sizeof (efx_dword_t)) + \ ((_index) * _reg ## _STEP)), \ (_edp), (_lock)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_READQ(_enp, _reg, _index, _eqp) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READQ((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_eqp)); \ EFSYS_PROBE5(efx_bar_tbl_readq, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_eqp)->eq_u32[1], \ uint32_t, (_eqp)->eq_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_WRITEQ(_enp, _reg, _index, _eqp) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE5(efx_bar_tbl_writeq, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_eqp)->eq_u32[1], \ uint32_t, (_eqp)->eq_u32[0]); \ EFSYS_BAR_WRITEQ((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_eqp)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_READO(_enp, _reg, _index, _eop, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_BAR_READO((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_eop), (_lock)); \ EFSYS_PROBE7(efx_bar_tbl_reado, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_eop)->eo_u32[3], \ uint32_t, (_eop)->eo_u32[2], \ uint32_t, (_eop)->eo_u32[1], \ uint32_t, (_eop)->eo_u32[0]); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_BAR_TBL_WRITEO(_enp, _reg, _index, _eop, _lock) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE7(efx_bar_tbl_writeo, const char *, #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_eop)->eo_u32[3], \ uint32_t, (_eop)->eo_u32[2], \ uint32_t, (_eop)->eo_u32[1], \ uint32_t, (_eop)->eo_u32[0]); \ EFSYS_BAR_WRITEO((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_eop), (_lock)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) /* * Allow drivers to perform optimised 128-bit doorbell writes. * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are * special-cased in the BIU on the Falcon/Siena and EF10 architectures to avoid * the need for locking in the host, and are the only ones known to be safe to * use 128-bites write with. */ #define EFX_BAR_TBL_DOORBELL_WRITEO(_enp, _reg, _index, _eop) \ do { \ EFX_CHECK_REG((_enp), (_reg)); \ EFSYS_PROBE7(efx_bar_tbl_doorbell_writeo, \ const char *, \ #_reg, \ uint32_t, (_index), \ uint32_t, _reg ## _OFST, \ uint32_t, (_eop)->eo_u32[3], \ uint32_t, (_eop)->eo_u32[2], \ uint32_t, (_eop)->eo_u32[1], \ uint32_t, (_eop)->eo_u32[0]); \ EFSYS_BAR_DOORBELL_WRITEO((_enp)->en_esbp, \ (_reg ## _OFST + ((_index) * _reg ## _STEP)), \ (_eop)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) #define EFX_DMA_SYNC_QUEUE_FOR_DEVICE(_esmp, _entries, _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)); \ else \ /* \ * It is cheaper to sync entire map than sync \ * two parts especially when offset/size are \ * ignored and entire map is synced in any case.\ */ \ EFSYS_DMA_SYNC_FOR_DEVICE((_esmp), \ 0, \ (_entries) * sizeof (efx_desc_t)); \ _NOTE(CONSTANTCONDITION) \ } while (B_FALSE) extern __checkReturn efx_rc_t efx_nic_biu_test( __in efx_nic_t *enp); extern __checkReturn efx_rc_t efx_mac_select( __in efx_nic_t *enp); extern void efx_mac_multicast_hash_compute( __in_ecount(6*count) uint8_t const *addrs, __in int count, __out efx_oword_t *hash_low, __out efx_oword_t *hash_high); extern __checkReturn efx_rc_t efx_phy_probe( __in efx_nic_t *enp); extern void efx_phy_unprobe( __in efx_nic_t *enp); #if EFSYS_OPT_VPD /* VPD utility functions */ extern __checkReturn efx_rc_t efx_vpd_hunk_length( __in_bcount(size) caddr_t data, __in size_t size, __out size_t *lengthp); extern __checkReturn efx_rc_t efx_vpd_hunk_verify( __in_bcount(size) caddr_t data, __in size_t size, __out_opt boolean_t *cksummedp); extern __checkReturn efx_rc_t efx_vpd_hunk_reinit( __in_bcount(size) caddr_t data, __in size_t size, __in boolean_t wantpid); extern __checkReturn efx_rc_t efx_vpd_hunk_get( __in_bcount(size) caddr_t data, __in size_t size, __in efx_vpd_tag_t tag, __in efx_vpd_keyword_t keyword, __out unsigned int *payloadp, __out uint8_t *paylenp); extern __checkReturn efx_rc_t efx_vpd_hunk_next( __in_bcount(size) caddr_t data, __in size_t size, __out efx_vpd_tag_t *tagp, __out efx_vpd_keyword_t *keyword, __out_opt unsigned int *payloadp, __out_opt uint8_t *paylenp, __inout unsigned int *contp); extern __checkReturn efx_rc_t efx_vpd_hunk_set( __in_bcount(size) caddr_t data, __in size_t size, __in efx_vpd_value_t *evvp); #endif /* EFSYS_OPT_VPD */ -#if EFSYS_OPT_DIAG - -extern efx_sram_pattern_fn_t __efx_sram_pattern_fns[]; - -typedef struct efx_register_set_s { - unsigned int address; - unsigned int step; - unsigned int rows; - efx_oword_t mask; -} efx_register_set_t; - -extern __checkReturn efx_rc_t -efx_nic_test_registers( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in size_t count); - -extern __checkReturn efx_rc_t -efx_nic_test_tables( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in efx_pattern_type_t pattern, - __in size_t count); - -#endif /* EFSYS_OPT_DIAG */ - #if EFSYS_OPT_MCDI extern __checkReturn efx_rc_t efx_mcdi_set_workaround( __in efx_nic_t *enp, __in uint32_t type, __in boolean_t enabled, __out_opt uint32_t *flagsp); extern __checkReturn efx_rc_t efx_mcdi_get_workarounds( __in efx_nic_t *enp, __out_opt uint32_t *implementedp, __out_opt uint32_t *enabledp); #endif /* EFSYS_OPT_MCDI */ #if EFSYS_OPT_MAC_STATS /* * Closed range of stats (i.e. the first and the last are included). * The last must be greater or equal (if the range is one item only) to * the first. */ struct efx_mac_stats_range { efx_mac_stat_t first; efx_mac_stat_t last; }; extern efx_rc_t efx_mac_stats_mask_add_ranges( __inout_bcount(mask_size) uint32_t *maskp, __in size_t mask_size, __in_ecount(rng_count) const struct efx_mac_stats_range *rngp, __in unsigned int rng_count); #endif /* EFSYS_OPT_MAC_STATS */ #ifdef __cplusplus } #endif #endif /* _SYS_EFX_IMPL_H */ Index: stable/12/sys/dev/sfxge/common/efx_nic.c =================================================================== --- stable/12/sys/dev/sfxge/common/efx_nic.c (revision 342314) +++ stable/12/sys/dev/sfxge/common/efx_nic.c (revision 342315) @@ -1,1065 +1,932 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007-2016 Solarflare Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the FreeBSD Project. */ #include __FBSDID("$FreeBSD$"); #include "efx.h" #include "efx_impl.h" __checkReturn efx_rc_t efx_family( __in uint16_t venid, __in uint16_t devid, __out efx_family_t *efp) { if (venid == EFX_PCI_VENID_SFC) { switch (devid) { #if EFSYS_OPT_SIENA case EFX_PCI_DEVID_SIENA_F1_UNINIT: /* * Hardware default for PF0 of uninitialised Siena. * manftest must be able to cope with this device id. */ *efp = EFX_FAMILY_SIENA; return (0); case EFX_PCI_DEVID_BETHPAGE: case EFX_PCI_DEVID_SIENA: *efp = EFX_FAMILY_SIENA; return (0); #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT: /* * Hardware default for PF0 of uninitialised Huntington. * manftest must be able to cope with this device id. */ *efp = EFX_FAMILY_HUNTINGTON; return (0); case EFX_PCI_DEVID_FARMINGDALE: case EFX_PCI_DEVID_GREENPORT: *efp = EFX_FAMILY_HUNTINGTON; return (0); case EFX_PCI_DEVID_FARMINGDALE_VF: case EFX_PCI_DEVID_GREENPORT_VF: *efp = EFX_FAMILY_HUNTINGTON; return (0); #endif /* EFSYS_OPT_HUNTINGTON */ #if EFSYS_OPT_MEDFORD case EFX_PCI_DEVID_MEDFORD_PF_UNINIT: /* * Hardware default for PF0 of uninitialised Medford. * manftest must be able to cope with this device id. */ *efp = EFX_FAMILY_MEDFORD; return (0); case EFX_PCI_DEVID_MEDFORD: *efp = EFX_FAMILY_MEDFORD; return (0); case EFX_PCI_DEVID_MEDFORD_VF: *efp = EFX_FAMILY_MEDFORD; return (0); #endif /* EFSYS_OPT_MEDFORD */ case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */ default: break; } } *efp = EFX_FAMILY_INVALID; return (ENOTSUP); } #define EFX_BIU_MAGIC0 0x01234567 #define EFX_BIU_MAGIC1 0xfedcba98 __checkReturn efx_rc_t efx_nic_biu_test( __in efx_nic_t *enp) { efx_oword_t oword; efx_rc_t rc; /* * Write magic values to scratch registers 0 and 1, then * verify that the values were written correctly. Interleave * the accesses to ensure that the BIU is not just reading * back the cached value that was last written. */ EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0); EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1); EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) { rc = EIO; goto fail1; } EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) { rc = EIO; goto fail2; } /* * Perform the same test, with the values swapped. This * ensures that subsequent tests don't start with the correct * values already written into the scratch registers. */ EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1); EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0); EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) { rc = EIO; goto fail3; } EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) { rc = EIO; goto fail4; } return (0); fail4: EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #if EFSYS_OPT_SIENA static const efx_nic_ops_t __efx_nic_siena_ops = { siena_nic_probe, /* eno_probe */ NULL, /* eno_board_cfg */ NULL, /* eno_set_drv_limits */ siena_nic_reset, /* eno_reset */ siena_nic_init, /* eno_init */ NULL, /* eno_get_vi_pool */ NULL, /* eno_get_bar_region */ #if EFSYS_OPT_DIAG siena_nic_register_test, /* eno_register_test */ #endif /* EFSYS_OPT_DIAG */ siena_nic_fini, /* eno_fini */ siena_nic_unprobe, /* eno_unprobe */ }; #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON static const efx_nic_ops_t __efx_nic_hunt_ops = { ef10_nic_probe, /* eno_probe */ hunt_board_cfg, /* eno_board_cfg */ ef10_nic_set_drv_limits, /* eno_set_drv_limits */ ef10_nic_reset, /* eno_reset */ ef10_nic_init, /* eno_init */ ef10_nic_get_vi_pool, /* eno_get_vi_pool */ ef10_nic_get_bar_region, /* eno_get_bar_region */ #if EFSYS_OPT_DIAG ef10_nic_register_test, /* eno_register_test */ #endif /* EFSYS_OPT_DIAG */ ef10_nic_fini, /* eno_fini */ ef10_nic_unprobe, /* eno_unprobe */ }; #endif /* EFSYS_OPT_HUNTINGTON */ #if EFSYS_OPT_MEDFORD static const efx_nic_ops_t __efx_nic_medford_ops = { ef10_nic_probe, /* eno_probe */ medford_board_cfg, /* eno_board_cfg */ ef10_nic_set_drv_limits, /* eno_set_drv_limits */ ef10_nic_reset, /* eno_reset */ ef10_nic_init, /* eno_init */ ef10_nic_get_vi_pool, /* eno_get_vi_pool */ ef10_nic_get_bar_region, /* eno_get_bar_region */ #if EFSYS_OPT_DIAG ef10_nic_register_test, /* eno_register_test */ #endif /* EFSYS_OPT_DIAG */ ef10_nic_fini, /* eno_fini */ ef10_nic_unprobe, /* eno_unprobe */ }; #endif /* EFSYS_OPT_MEDFORD */ __checkReturn efx_rc_t efx_nic_create( __in efx_family_t family, __in efsys_identifier_t *esip, __in efsys_bar_t *esbp, __in efsys_lock_t *eslp, __deref_out efx_nic_t **enpp) { efx_nic_t *enp; efx_rc_t rc; EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID); EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES); /* Allocate a NIC object */ EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp); if (enp == NULL) { rc = ENOMEM; goto fail1; } enp->en_magic = EFX_NIC_MAGIC; switch (family) { #if EFSYS_OPT_SIENA case EFX_FAMILY_SIENA: enp->en_enop = &__efx_nic_siena_ops; enp->en_features = EFX_FEATURE_IPV6 | EFX_FEATURE_LFSR_HASH_INSERT | EFX_FEATURE_LINK_EVENTS | EFX_FEATURE_PERIODIC_MAC_STATS | EFX_FEATURE_MCDI | EFX_FEATURE_LOOKAHEAD_SPLIT | EFX_FEATURE_MAC_HEADER_FILTERS | EFX_FEATURE_TX_SRC_FILTERS; break; #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON case EFX_FAMILY_HUNTINGTON: enp->en_enop = &__efx_nic_hunt_ops; enp->en_features = EFX_FEATURE_IPV6 | EFX_FEATURE_LINK_EVENTS | EFX_FEATURE_PERIODIC_MAC_STATS | EFX_FEATURE_MCDI | EFX_FEATURE_MAC_HEADER_FILTERS | EFX_FEATURE_MCDI_DMA | EFX_FEATURE_PIO_BUFFERS | EFX_FEATURE_FW_ASSISTED_TSO | EFX_FEATURE_FW_ASSISTED_TSO_V2; break; #endif /* EFSYS_OPT_HUNTINGTON */ #if EFSYS_OPT_MEDFORD case EFX_FAMILY_MEDFORD: enp->en_enop = &__efx_nic_medford_ops; /* * FW_ASSISTED_TSO omitted as Medford only supports firmware * assisted TSO version 2, not the v1 scheme used on Huntington. */ enp->en_features = EFX_FEATURE_IPV6 | EFX_FEATURE_LINK_EVENTS | EFX_FEATURE_PERIODIC_MAC_STATS | EFX_FEATURE_MCDI | EFX_FEATURE_MAC_HEADER_FILTERS | EFX_FEATURE_MCDI_DMA | EFX_FEATURE_PIO_BUFFERS | EFX_FEATURE_FW_ASSISTED_TSO_V2; break; #endif /* EFSYS_OPT_MEDFORD */ default: rc = ENOTSUP; goto fail2; } enp->en_family = family; enp->en_esip = esip; enp->en_esbp = esbp; enp->en_eslp = eslp; *enpp = enp; return (0); fail2: EFSYS_PROBE(fail2); enp->en_magic = 0; /* Free the NIC object */ EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __checkReturn efx_rc_t efx_nic_probe( __in efx_nic_t *enp) { const efx_nic_ops_t *enop; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); #if EFSYS_OPT_MCDI EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); #endif /* EFSYS_OPT_MCDI */ EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE)); enop = enp->en_enop; if ((rc = enop->eno_probe(enp)) != 0) goto fail1; if ((rc = efx_phy_probe(enp)) != 0) goto fail2; enp->en_mod_flags |= EFX_MOD_PROBE; return (0); fail2: EFSYS_PROBE(fail2); enop->eno_unprobe(enp); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __checkReturn efx_rc_t efx_nic_set_drv_limits( __inout efx_nic_t *enp, __in efx_drv_limits_t *edlp) { const efx_nic_ops_t *enop = enp->en_enop; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); if (enop->eno_set_drv_limits != NULL) { if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0) goto fail1; } return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __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) { const efx_nic_ops_t *enop = enp->en_enop; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); if (enop->eno_get_bar_region == NULL) { rc = ENOTSUP; goto fail1; } if ((rc = (enop->eno_get_bar_region)(enp, region, offsetp, sizep)) != 0) { goto fail2; } return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __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) { const efx_nic_ops_t *enop = enp->en_enop; efx_nic_cfg_t *encp = &enp->en_nic_cfg; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); if (enop->eno_get_vi_pool != NULL) { uint32_t vi_count = 0; if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0) goto fail1; *evq_countp = vi_count; *rxq_countp = vi_count; *txq_countp = vi_count; } else { /* Use NIC limits as default value */ *evq_countp = encp->enc_evq_limit; *rxq_countp = encp->enc_rxq_limit; *txq_countp = encp->enc_txq_limit; } return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __checkReturn efx_rc_t efx_nic_init( __in efx_nic_t *enp) { const efx_nic_ops_t *enop = enp->en_enop; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); if (enp->en_mod_flags & EFX_MOD_NIC) { rc = EINVAL; goto fail1; } if ((rc = enop->eno_init(enp)) != 0) goto fail2; enp->en_mod_flags |= EFX_MOD_NIC; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } void efx_nic_fini( __in efx_nic_t *enp) { const efx_nic_ops_t *enop = enp->en_enop; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE); EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); enop->eno_fini(enp); enp->en_mod_flags &= ~EFX_MOD_NIC; } void efx_nic_unprobe( __in efx_nic_t *enp) { const efx_nic_ops_t *enop = enp->en_enop; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); #if EFSYS_OPT_MCDI EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); #endif /* EFSYS_OPT_MCDI */ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); efx_phy_unprobe(enp); enop->eno_unprobe(enp); enp->en_mod_flags &= ~EFX_MOD_PROBE; } void efx_nic_destroy( __in efx_nic_t *enp) { efsys_identifier_t *esip = enp->en_esip; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0); enp->en_family = EFX_FAMILY_INVALID; enp->en_esip = NULL; enp->en_esbp = NULL; enp->en_eslp = NULL; enp->en_enop = NULL; enp->en_magic = 0; /* Free the NIC object */ EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp); } __checkReturn efx_rc_t efx_nic_reset( __in efx_nic_t *enp) { const efx_nic_ops_t *enop = enp->en_enop; unsigned int mod_flags; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE); /* * All modules except the MCDI, PROBE, NVRAM, VPD, MON * (which we do not reset here) must have been shut down or never * initialized. * * A rule of thumb here is: If the controller or MC reboots, is *any* * state lost. If it's lost and needs reapplying, then the module * *must* not be initialised during the reset. */ mod_flags = enp->en_mod_flags; mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM | EFX_MOD_VPD | EFX_MOD_MON); EFSYS_ASSERT3U(mod_flags, ==, 0); if (mod_flags != 0) { rc = EINVAL; goto fail1; } if ((rc = enop->eno_reset(enp)) != 0) goto fail2; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } const efx_nic_cfg_t * efx_nic_cfg_get( __in efx_nic_t *enp) { EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); return (&(enp->en_nic_cfg)); } #if EFSYS_OPT_DIAG __checkReturn efx_rc_t efx_nic_register_test( __in efx_nic_t *enp) { const efx_nic_ops_t *enop = enp->en_enop; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); if ((rc = enop->eno_register_test(enp)) != 0) goto fail1; return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn efx_rc_t -efx_nic_test_registers( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in size_t count) -{ - unsigned int bit; - efx_oword_t original; - efx_oword_t reg; - efx_oword_t buf; - efx_rc_t rc; - - while (count > 0) { - /* This function is only suitable for registers */ - EFSYS_ASSERT(rsp->rows == 1); - - /* bit sweep on and off */ - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, - B_TRUE); - for (bit = 0; bit < 128; bit++) { - /* Is this bit in the mask? */ - if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) - continue; - - /* Test this bit can be set in isolation */ - reg = original; - EFX_AND_OWORD(reg, rsp->mask); - EFX_SET_OWORD_BIT(reg, bit); - - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, - B_TRUE); - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, - B_TRUE); - - EFX_AND_OWORD(buf, rsp->mask); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail1; - } - - /* Test this bit can be cleared in isolation */ - EFX_OR_OWORD(reg, rsp->mask); - EFX_CLEAR_OWORD_BIT(reg, bit); - - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, - B_TRUE); - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, - B_TRUE); - - EFX_AND_OWORD(buf, rsp->mask); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail2; - } - } - - /* Restore the old value */ - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, - B_TRUE); - - --count; - ++rsp; - } - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - /* Restore the old value */ - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); - - return (rc); -} - - __checkReturn efx_rc_t -efx_nic_test_tables( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in efx_pattern_type_t pattern, - __in size_t count) -{ - efx_sram_pattern_fn_t func; - unsigned int index; - unsigned int address; - efx_oword_t reg; - efx_oword_t buf; - efx_rc_t rc; - - EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); - func = __efx_sram_pattern_fns[pattern]; - - while (count > 0) { - /* Write */ - address = rsp->address; - for (index = 0; index < rsp->rows; ++index) { - func(2 * index + 0, B_FALSE, ®.eo_qword[0]); - func(2 * index + 1, B_FALSE, ®.eo_qword[1]); - EFX_AND_OWORD(reg, rsp->mask); - EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); - - address += rsp->step; - } - - /* Read */ - address = rsp->address; - for (index = 0; index < rsp->rows; ++index) { - func(2 * index + 0, B_FALSE, ®.eo_qword[0]); - func(2 * index + 1, B_FALSE, ®.eo_qword[1]); - EFX_AND_OWORD(reg, rsp->mask); - EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail1; - } - - address += rsp->step; - } - - ++rsp; - --count; - } - - return (0); - -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - #endif /* EFSYS_OPT_DIAG */ #if EFSYS_OPT_LOOPBACK extern void efx_loopback_mask( __in efx_loopback_kind_t loopback_kind, __out efx_qword_t *maskp) { efx_qword_t mask; EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS); EFSYS_ASSERT(maskp != NULL); /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */ EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XPORT == EFX_LOOPBACK_XPORT); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII_WS == EFX_LOOPBACK_XGMII_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS == EFX_LOOPBACK_XAUI_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_FAR == EFX_LOOPBACK_XAUI_WS_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_NEAR == EFX_LOOPBACK_XAUI_WS_NEAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_WS == EFX_LOOPBACK_GMII_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS == EFX_LOOPBACK_XFI_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS_FAR == EFX_LOOPBACK_XFI_WS_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS_WS == EFX_LOOPBACK_PHYXS_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT == EFX_LOOPBACK_PMA_INT); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_NEAR == EFX_LOOPBACK_SD_NEAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FAR == EFX_LOOPBACK_SD_FAR); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT_WS == EFX_LOOPBACK_PMA_INT_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP2_WS == EFX_LOOPBACK_SD_FEP2_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP1_5_WS == EFX_LOOPBACK_SD_FEP1_5_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP_WS == EFX_LOOPBACK_SD_FEP_WS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FES_WS == EFX_LOOPBACK_SD_FES_WS); /* Build bitmask of possible loopback types */ EFX_ZERO_QWORD(mask); if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) || (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF); } if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) || (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { /* * The "MAC" grouping has historically been used by drivers to * mean loopbacks supported by on-chip hardware. Keep that * meaning here, and include on-chip PHY layer loopbacks. */ EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR); } if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) || (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { /* * The "PHY" grouping has historically been used by drivers to * mean loopbacks supported by off-chip hardware. Keep that * meaning here. */ EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS); EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD); } *maskp = mask; } __checkReturn efx_rc_t efx_mcdi_get_loopback_modes( __in efx_nic_t *enp) { efx_nic_cfg_t *encp = &(enp->en_nic_cfg); efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_LOOPBACK_MODES_IN_LEN, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN)]; efx_qword_t mask; efx_qword_t modes; efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; req.emr_in_buf = payload; req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN; req.emr_out_buf = payload; req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_LEN; efx_mcdi_execute(enp, &req); if (req.emr_rc != 0) { rc = req.emr_rc; goto fail1; } if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST + MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) { rc = EMSGSIZE; goto fail2; } /* * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link(). */ efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask); EFX_AND_QWORD(mask, *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED)); modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M); EFX_AND_QWORD(modes, mask); encp->enc_loopback_types[EFX_LINK_100FDX] = modes; modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G); EFX_AND_QWORD(modes, mask); encp->enc_loopback_types[EFX_LINK_1000FDX] = modes; modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G); EFX_AND_QWORD(modes, mask); encp->enc_loopback_types[EFX_LINK_10000FDX] = modes; if (req.emr_out_length_used >= MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST + MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) { /* Response includes 40G loopback modes */ modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_40G); EFX_AND_QWORD(modes, mask); encp->enc_loopback_types[EFX_LINK_40000FDX] = modes; } EFX_ZERO_QWORD(modes); EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF); EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]); EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]); EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]); EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]); encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #endif /* EFSYS_OPT_LOOPBACK */ __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) { uint32_t lane_bandwidth; uint32_t total_bandwidth; efx_rc_t rc; if ((pcie_link_width == 0) || (pcie_link_width > 16) || !ISP2(pcie_link_width)) { rc = EINVAL; goto fail1; } switch (pcie_link_gen) { case EFX_PCIE_LINK_SPEED_GEN1: /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */ lane_bandwidth = 2000; break; case EFX_PCIE_LINK_SPEED_GEN2: /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */ lane_bandwidth = 4000; break; case EFX_PCIE_LINK_SPEED_GEN3: /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */ lane_bandwidth = 7877; break; default: rc = EINVAL; goto fail2; } total_bandwidth = lane_bandwidth * pcie_link_width; *bandwidth_mbpsp = total_bandwidth; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __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) { efx_nic_cfg_t *encp = &(enp->en_nic_cfg); uint32_t bandwidth; efx_pcie_link_performance_t result; efx_rc_t rc; if ((encp->enc_required_pcie_bandwidth_mbps == 0) || (pcie_link_width == 0) || (pcie_link_width == 32) || (pcie_link_gen == 0)) { /* * No usable info on what is required and/or in use. In virtual * machines, sometimes the PCIe link width is reported as 0 or * 32, or the speed as 0. */ result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH; goto out; } /* Calculate the available bandwidth in megabits per second */ rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width, pcie_link_gen, &bandwidth); if (rc != 0) goto fail1; if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) { result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH; } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) { /* The link provides enough bandwidth but not optimal latency */ result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY; } else { result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL; } out: *resultp = result; return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } Index: stable/12/sys/dev/sfxge/common/siena_impl.h =================================================================== --- stable/12/sys/dev/sfxge/common/siena_impl.h (revision 342314) +++ stable/12/sys/dev/sfxge/common/siena_impl.h (revision 342315) @@ -1,435 +1,444 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2009-2016 Solarflare Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the FreeBSD Project. * * $FreeBSD$ */ #ifndef _SYS_SIENA_IMPL_H #define _SYS_SIENA_IMPL_H #include "efx.h" #include "efx_regs.h" #include "efx_mcdi.h" #include "siena_flash.h" #ifdef __cplusplus extern "C" { #endif #define SIENA_NVRAM_CHUNK 0x80 extern __checkReturn efx_rc_t siena_nic_probe( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_nic_reset( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_nic_init( __in efx_nic_t *enp); #if EFSYS_OPT_DIAG +extern efx_sram_pattern_fn_t __efx_sram_pattern_fns[]; + +typedef struct siena_register_set_s { + unsigned int address; + unsigned int step; + unsigned int rows; + efx_oword_t mask; +} siena_register_set_t; + extern __checkReturn efx_rc_t siena_nic_register_test( __in efx_nic_t *enp); #endif /* EFSYS_OPT_DIAG */ extern void siena_nic_fini( __in efx_nic_t *enp); extern void siena_nic_unprobe( __in efx_nic_t *enp); #define SIENA_SRAM_ROWS 0x12000 extern void siena_sram_init( __in efx_nic_t *enp); #if EFSYS_OPT_DIAG extern __checkReturn efx_rc_t siena_sram_test( __in efx_nic_t *enp, __in efx_sram_pattern_fn_t func); #endif /* EFSYS_OPT_DIAG */ #if EFSYS_OPT_MCDI extern __checkReturn efx_rc_t siena_mcdi_init( __in efx_nic_t *enp, __in const efx_mcdi_transport_t *mtp); extern void siena_mcdi_send_request( __in efx_nic_t *enp, __in_bcount(hdr_len) void *hdrp, __in size_t hdr_len, __in_bcount(sdu_len) void *sdup, __in size_t sdu_len); extern __checkReturn boolean_t siena_mcdi_poll_response( __in efx_nic_t *enp); extern void siena_mcdi_read_response( __in efx_nic_t *enp, __out_bcount(length) void *bufferp, __in size_t offset, __in size_t length); extern efx_rc_t siena_mcdi_poll_reboot( __in efx_nic_t *enp); extern void siena_mcdi_fini( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_mcdi_feature_supported( __in efx_nic_t *enp, __in efx_mcdi_feature_id_t id, __out boolean_t *supportedp); extern void siena_mcdi_get_timeout( __in efx_nic_t *enp, __in efx_mcdi_req_t *emrp, __out uint32_t *timeoutp); #endif /* EFSYS_OPT_MCDI */ #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD extern __checkReturn efx_rc_t siena_nvram_partn_lock( __in efx_nic_t *enp, __in uint32_t partn); extern __checkReturn efx_rc_t siena_nvram_partn_unlock( __in efx_nic_t *enp, __in uint32_t partn); extern __checkReturn efx_rc_t siena_nvram_get_dynamic_cfg( __in efx_nic_t *enp, __in uint32_t partn, __in boolean_t vpd, __out siena_mc_dynamic_config_hdr_t **dcfgp, __out size_t *sizep); #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ #if EFSYS_OPT_NVRAM #if EFSYS_OPT_DIAG extern __checkReturn efx_rc_t siena_nvram_test( __in efx_nic_t *enp); #endif /* EFSYS_OPT_DIAG */ extern __checkReturn efx_rc_t siena_nvram_get_subtype( __in efx_nic_t *enp, __in uint32_t partn, __out uint32_t *subtypep); extern __checkReturn efx_rc_t siena_nvram_type_to_partn( __in efx_nic_t *enp, __in efx_nvram_type_t type, __out uint32_t *partnp); extern __checkReturn efx_rc_t siena_nvram_partn_size( __in efx_nic_t *enp, __in uint32_t partn, __out size_t *sizep); extern __checkReturn efx_rc_t siena_nvram_partn_rw_start( __in efx_nic_t *enp, __in uint32_t partn, __out size_t *chunk_sizep); extern __checkReturn efx_rc_t siena_nvram_partn_read( __in efx_nic_t *enp, __in uint32_t partn, __in unsigned int offset, __out_bcount(size) caddr_t data, __in size_t size); extern __checkReturn efx_rc_t siena_nvram_partn_erase( __in efx_nic_t *enp, __in uint32_t partn, __in unsigned int offset, __in size_t size); extern __checkReturn efx_rc_t siena_nvram_partn_write( __in efx_nic_t *enp, __in uint32_t partn, __in unsigned int offset, __out_bcount(size) caddr_t data, __in size_t size); extern __checkReturn efx_rc_t siena_nvram_partn_rw_finish( __in efx_nic_t *enp, __in uint32_t partn); extern __checkReturn efx_rc_t siena_nvram_partn_get_version( __in efx_nic_t *enp, __in uint32_t partn, __out uint32_t *subtypep, __out_ecount(4) uint16_t version[4]); extern __checkReturn efx_rc_t siena_nvram_partn_set_version( __in efx_nic_t *enp, __in uint32_t partn, __in_ecount(4) uint16_t version[4]); #endif /* EFSYS_OPT_NVRAM */ #if EFSYS_OPT_VPD extern __checkReturn efx_rc_t siena_vpd_init( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_vpd_size( __in efx_nic_t *enp, __out size_t *sizep); extern __checkReturn efx_rc_t siena_vpd_read( __in efx_nic_t *enp, __out_bcount(size) caddr_t data, __in size_t size); extern __checkReturn efx_rc_t siena_vpd_verify( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size); extern __checkReturn efx_rc_t siena_vpd_reinit( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size); extern __checkReturn efx_rc_t siena_vpd_get( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size, __inout efx_vpd_value_t *evvp); extern __checkReturn efx_rc_t siena_vpd_set( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size, __in efx_vpd_value_t *evvp); extern __checkReturn efx_rc_t siena_vpd_next( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size, __out efx_vpd_value_t *evvp, __inout unsigned int *contp); extern __checkReturn efx_rc_t siena_vpd_write( __in efx_nic_t *enp, __in_bcount(size) caddr_t data, __in size_t size); extern void siena_vpd_fini( __in efx_nic_t *enp); #endif /* EFSYS_OPT_VPD */ typedef struct siena_link_state_s { uint32_t sls_adv_cap_mask; uint32_t sls_lp_cap_mask; unsigned int sls_fcntl; efx_link_mode_t sls_link_mode; #if EFSYS_OPT_LOOPBACK efx_loopback_type_t sls_loopback; #endif boolean_t sls_mac_up; } siena_link_state_t; extern void siena_phy_link_ev( __in efx_nic_t *enp, __in efx_qword_t *eqp, __out efx_link_mode_t *link_modep); extern __checkReturn efx_rc_t siena_phy_get_link( __in efx_nic_t *enp, __out siena_link_state_t *slsp); extern __checkReturn efx_rc_t siena_phy_power( __in efx_nic_t *enp, __in boolean_t on); extern __checkReturn efx_rc_t siena_phy_reconfigure( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_phy_verify( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_phy_oui_get( __in efx_nic_t *enp, __out uint32_t *ouip); #if EFSYS_OPT_PHY_STATS extern void siena_phy_decode_stats( __in efx_nic_t *enp, __in uint32_t vmask, __in_opt efsys_mem_t *esmp, __out_opt uint64_t *smaskp, __inout_ecount_opt(EFX_PHY_NSTATS) uint32_t *stat); extern __checkReturn efx_rc_t siena_phy_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat); #endif /* EFSYS_OPT_PHY_STATS */ #if EFSYS_OPT_BIST extern __checkReturn efx_rc_t siena_phy_bist_start( __in efx_nic_t *enp, __in efx_bist_type_t type); extern __checkReturn efx_rc_t siena_phy_bist_poll( __in efx_nic_t *enp, __in efx_bist_type_t type, __out efx_bist_result_t *resultp, __out_opt __drv_when(count > 0, __notnull) uint32_t *value_maskp, __out_ecount_opt(count) __drv_when(count > 0, __notnull) unsigned long *valuesp, __in size_t count); extern void siena_phy_bist_stop( __in efx_nic_t *enp, __in efx_bist_type_t type); #endif /* EFSYS_OPT_BIST */ extern __checkReturn efx_rc_t siena_mac_poll( __in efx_nic_t *enp, __out efx_link_mode_t *link_modep); extern __checkReturn efx_rc_t siena_mac_up( __in efx_nic_t *enp, __out boolean_t *mac_upp); extern __checkReturn efx_rc_t siena_mac_reconfigure( __in efx_nic_t *enp); extern __checkReturn efx_rc_t siena_mac_pdu_get( __in efx_nic_t *enp, __out size_t *pdu); #if EFSYS_OPT_LOOPBACK extern __checkReturn efx_rc_t siena_mac_loopback_set( __in efx_nic_t *enp, __in efx_link_mode_t link_mode, __in efx_loopback_type_t loopback_type); #endif /* EFSYS_OPT_LOOPBACK */ #if EFSYS_OPT_MAC_STATS extern __checkReturn efx_rc_t siena_mac_stats_get_mask( __in efx_nic_t *enp, __inout_bcount(mask_size) uint32_t *maskp, __in size_t mask_size); extern __checkReturn efx_rc_t siena_mac_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat, __inout_opt uint32_t *generationp); #endif /* EFSYS_OPT_MAC_STATS */ #ifdef __cplusplus } #endif #endif /* _SYS_SIENA_IMPL_H */ Index: stable/12/sys/dev/sfxge/common/siena_nic.c =================================================================== --- stable/12/sys/dev/sfxge/common/siena_nic.c (revision 342314) +++ stable/12/sys/dev/sfxge/common/siena_nic.c (revision 342315) @@ -1,590 +1,724 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2009-2016 Solarflare Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the FreeBSD Project. */ #include __FBSDID("$FreeBSD$"); #include "efx.h" #include "efx_impl.h" #include "mcdi_mon.h" #if EFSYS_OPT_SIENA #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM static __checkReturn efx_rc_t siena_nic_get_partn_mask( __in efx_nic_t *enp, __out unsigned int *maskp) { efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN, MC_CMD_NVRAM_TYPES_OUT_LEN)]; efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_NVRAM_TYPES; req.emr_in_buf = payload; req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN; req.emr_out_buf = payload; req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN; efx_mcdi_execute(enp, &req); if (req.emr_rc != 0) { rc = req.emr_rc; goto fail1; } if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { rc = EMSGSIZE; goto fail2; } *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ static __checkReturn efx_rc_t siena_board_cfg( __in efx_nic_t *enp) { efx_nic_cfg_t *encp = &(enp->en_nic_cfg); uint8_t mac_addr[6]; efx_dword_t capabilities; uint32_t board_type; uint32_t nevq, nrxq, ntxq; efx_rc_t rc; /* External port identifier using one-based port numbering */ encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port; /* Board configuration */ if ((rc = efx_mcdi_get_board_cfg(enp, &board_type, &capabilities, mac_addr)) != 0) goto fail1; EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); encp->enc_board_type = board_type; /* * There is no possibility to determine the number of PFs on Siena * by issuing MCDI request, and it is not an easy task to find the * value based on the board type, so 'enc_hw_pf_count' is set to 1 */ encp->enc_hw_pf_count = 1; /* Additional capabilities */ encp->enc_clk_mult = 1; if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) { enp->en_features |= EFX_FEATURE_TURBO; if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO_ACTIVE)) { encp->enc_clk_mult = 2; } } encp->enc_evq_timer_quantum_ns = EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; /* When hash header insertion is enabled, Siena inserts 16 bytes */ encp->enc_rx_prefix_size = 16; /* Alignment for receive packet DMA buffers */ encp->enc_rx_buf_align_start = 1; encp->enc_rx_buf_align_end = 1; /* Alignment for WPTR updates */ encp->enc_rx_push_align = 1; encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT); /* Fragments must not span 4k boundaries. */ encp->enc_tx_dma_desc_boundary = 4096; /* Resource limits */ rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq); if (rc != 0) { if (rc != ENOTSUP) goto fail2; nevq = 1024; nrxq = EFX_RXQ_LIMIT_TARGET; ntxq = EFX_TXQ_LIMIT_TARGET; } encp->enc_evq_limit = nevq; encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq); encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq); encp->enc_txq_max_ndescs = 4096; encp->enc_buftbl_limit = SIENA_SRAM_ROWS - (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; encp->enc_fw_assisted_tso_enabled = B_FALSE; encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; encp->enc_fw_assisted_tso_v2_n_contexts = 0; encp->enc_allow_set_mac_with_installed_filters = B_TRUE; /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */ encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; encp->enc_fw_verified_nvram_update_required = B_FALSE; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } static __checkReturn efx_rc_t siena_phy_cfg( __in efx_nic_t *enp) { #if EFSYS_OPT_PHY_STATS efx_nic_cfg_t *encp = &(enp->en_nic_cfg); #endif /* EFSYS_OPT_PHY_STATS */ efx_rc_t rc; /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) goto fail1; #if EFSYS_OPT_PHY_STATS /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask, NULL, &encp->enc_phy_stat_mask, NULL); #endif /* EFSYS_OPT_PHY_STATS */ return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __checkReturn efx_rc_t siena_nic_probe( __in efx_nic_t *enp) { efx_port_t *epp = &(enp->en_port); efx_nic_cfg_t *encp = &(enp->en_nic_cfg); siena_link_state_t sls; unsigned int mask; efx_oword_t oword; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); /* Test BIU */ if ((rc = efx_nic_biu_test(enp)) != 0) goto fail1; /* Clear the region register */ EFX_POPULATE_OWORD_4(oword, FRF_AZ_ADR_REGION0, 0, FRF_AZ_ADR_REGION1, (1 << 16), FRF_AZ_ADR_REGION2, (2 << 16), FRF_AZ_ADR_REGION3, (3 << 16)); EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword); /* Read clear any assertion state */ if ((rc = efx_mcdi_read_assertion(enp)) != 0) goto fail2; /* Exit the assertion handler */ if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) goto fail3; /* Wrestle control from the BMC */ if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) goto fail4; if ((rc = siena_board_cfg(enp)) != 0) goto fail5; if ((rc = siena_phy_cfg(enp)) != 0) goto fail6; /* Obtain the default PHY advertised capabilities */ if ((rc = siena_nic_reset(enp)) != 0) goto fail7; if ((rc = siena_phy_get_link(enp, &sls)) != 0) goto fail8; epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) goto fail9; enp->en_u.siena.enu_partn_mask = mask; #endif #if EFSYS_OPT_MAC_STATS /* Wipe the MAC statistics */ if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) goto fail10; #endif #if EFSYS_OPT_LOOPBACK if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) goto fail11; #endif #if EFSYS_OPT_MON_STATS if ((rc = mcdi_mon_cfg_build(enp)) != 0) goto fail12; #endif encp->enc_features = enp->en_features; return (0); #if EFSYS_OPT_MON_STATS fail12: EFSYS_PROBE(fail12); #endif #if EFSYS_OPT_LOOPBACK fail11: EFSYS_PROBE(fail11); #endif #if EFSYS_OPT_MAC_STATS fail10: EFSYS_PROBE(fail10); #endif #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM fail9: EFSYS_PROBE(fail9); #endif fail8: EFSYS_PROBE(fail8); fail7: EFSYS_PROBE(fail7); fail6: EFSYS_PROBE(fail6); fail5: EFSYS_PROBE(fail5); fail4: EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } __checkReturn efx_rc_t siena_nic_reset( __in efx_nic_t *enp) { efx_mcdi_req_t req; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); /* siena_nic_reset() is called to recover from BADASSERT failures. */ if ((rc = efx_mcdi_read_assertion(enp)) != 0) goto fail1; if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) goto fail2; /* * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied * for backwards compatibility with PORT_RESET_IN_LEN. */ EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0); req.emr_cmd = MC_CMD_ENTITY_RESET; req.emr_in_buf = NULL; req.emr_in_length = 0; req.emr_out_buf = NULL; req.emr_out_length = 0; efx_mcdi_execute(enp, &req); if (req.emr_rc != 0) { rc = req.emr_rc; goto fail3; } return (0); fail3: EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (0); } static void siena_nic_rx_cfg( __in efx_nic_t *enp) { efx_oword_t oword; /* * RX_INGR_EN is always enabled on Siena, because we rely on * the RX parser to be resiliant to missing SOP/EOP. */ EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); /* Disable parsing of additional 802.1Q in Q packets */ EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); } static void siena_nic_usrev_dis( __in efx_nic_t *enp) { efx_oword_t oword; EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); } __checkReturn efx_rc_t siena_nic_init( __in efx_nic_t *enp) { efx_rc_t rc; EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); /* Enable reporting of some events (e.g. link change) */ if ((rc = efx_mcdi_log_ctrl(enp)) != 0) goto fail1; siena_sram_init(enp); /* Configure Siena's RX block */ siena_nic_rx_cfg(enp); /* Disable USR_EVents for now */ siena_nic_usrev_dis(enp); /* bug17057: Ensure set_link is called */ if ((rc = siena_phy_reconfigure(enp)) != 0) goto fail2; enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1; return (0); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } void siena_nic_fini( __in efx_nic_t *enp) { _NOTE(ARGUNUSED(enp)) } void siena_nic_unprobe( __in efx_nic_t *enp) { #if EFSYS_OPT_MON_STATS mcdi_mon_cfg_free(enp); #endif /* EFSYS_OPT_MON_STATS */ (void) efx_mcdi_drv_attach(enp, B_FALSE); } #if EFSYS_OPT_DIAG -static efx_register_set_t __siena_registers[] = { +static siena_register_set_t __siena_registers[] = { { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} }; static const uint32_t __siena_register_masks[] = { 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 }; -static efx_register_set_t __siena_tables[] = { +static siena_register_set_t __siena_tables[] = { { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, FR_AZ_RX_FILTER_TBL0_ROWS }, { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, { FR_AZ_RX_DESC_PTR_TBL_OFST, FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, { FR_AZ_TX_DESC_PTR_TBL_OFST, FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, { FR_CZ_TX_FILTER_TBL0_OFST, FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, { FR_CZ_TX_MAC_FILTER_TBL0_OFST, FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } }; static const uint32_t __siena_table_masks[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, }; __checkReturn efx_rc_t +siena_nic_test_registers( + __in efx_nic_t *enp, + __in siena_register_set_t *rsp, + __in size_t count) +{ + unsigned int bit; + efx_oword_t original; + efx_oword_t reg; + efx_oword_t buf; + efx_rc_t rc; + + while (count > 0) { + /* This function is only suitable for registers */ + EFSYS_ASSERT(rsp->rows == 1); + + /* bit sweep on and off */ + EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, + B_TRUE); + for (bit = 0; bit < 128; bit++) { + /* Is this bit in the mask? */ + if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) + continue; + + /* Test this bit can be set in isolation */ + reg = original; + EFX_AND_OWORD(reg, rsp->mask); + EFX_SET_OWORD_BIT(reg, bit); + + EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, + B_TRUE); + EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, + B_TRUE); + + EFX_AND_OWORD(buf, rsp->mask); + if (memcmp(®, &buf, sizeof (reg))) { + rc = EIO; + goto fail1; + } + + /* Test this bit can be cleared in isolation */ + EFX_OR_OWORD(reg, rsp->mask); + EFX_CLEAR_OWORD_BIT(reg, bit); + + EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, + B_TRUE); + EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, + B_TRUE); + + EFX_AND_OWORD(buf, rsp->mask); + if (memcmp(®, &buf, sizeof (reg))) { + rc = EIO; + goto fail2; + } + } + + /* Restore the old value */ + EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, + B_TRUE); + + --count; + ++rsp; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + /* Restore the old value */ + EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); + + return (rc); +} + + __checkReturn efx_rc_t +siena_nic_test_tables( + __in efx_nic_t *enp, + __in siena_register_set_t *rsp, + __in efx_pattern_type_t pattern, + __in size_t count) +{ + efx_sram_pattern_fn_t func; + unsigned int index; + unsigned int address; + efx_oword_t reg; + efx_oword_t buf; + efx_rc_t rc; + + EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); + func = __efx_sram_pattern_fns[pattern]; + + while (count > 0) { + /* Write */ + address = rsp->address; + for (index = 0; index < rsp->rows; ++index) { + func(2 * index + 0, B_FALSE, ®.eo_qword[0]); + func(2 * index + 1, B_FALSE, ®.eo_qword[1]); + EFX_AND_OWORD(reg, rsp->mask); + EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); + + address += rsp->step; + } + + /* Read */ + address = rsp->address; + for (index = 0; index < rsp->rows; ++index) { + func(2 * index + 0, B_FALSE, ®.eo_qword[0]); + func(2 * index + 1, B_FALSE, ®.eo_qword[1]); + EFX_AND_OWORD(reg, rsp->mask); + EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); + if (memcmp(®, &buf, sizeof (reg))) { + rc = EIO; + goto fail1; + } + + address += rsp->step; + } + + ++rsp; + --count; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + + __checkReturn efx_rc_t siena_nic_register_test( __in efx_nic_t *enp) { - efx_register_set_t *rsp; + siena_register_set_t *rsp; const uint32_t *dwordp; unsigned int nitems; unsigned int count; efx_rc_t rc; /* Fill out the register mask entries */ EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) == EFX_ARRAY_SIZE(__siena_registers) * 4); nitems = EFX_ARRAY_SIZE(__siena_registers); dwordp = __siena_register_masks; for (count = 0; count < nitems; ++count) { rsp = __siena_registers + count; rsp->mask.eo_u32[0] = *dwordp++; rsp->mask.eo_u32[1] = *dwordp++; rsp->mask.eo_u32[2] = *dwordp++; rsp->mask.eo_u32[3] = *dwordp++; } /* Fill out the register table entries */ EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) == EFX_ARRAY_SIZE(__siena_tables) * 4); nitems = EFX_ARRAY_SIZE(__siena_tables); dwordp = __siena_table_masks; for (count = 0; count < nitems; ++count) { rsp = __siena_tables + count; rsp->mask.eo_u32[0] = *dwordp++; rsp->mask.eo_u32[1] = *dwordp++; rsp->mask.eo_u32[2] = *dwordp++; rsp->mask.eo_u32[3] = *dwordp++; } - if ((rc = efx_nic_test_registers(enp, __siena_registers, + if ((rc = siena_nic_test_registers(enp, __siena_registers, EFX_ARRAY_SIZE(__siena_registers))) != 0) goto fail1; - if ((rc = efx_nic_test_tables(enp, __siena_tables, + if ((rc = siena_nic_test_tables(enp, __siena_tables, EFX_PATTERN_BYTE_ALTERNATE, EFX_ARRAY_SIZE(__siena_tables))) != 0) goto fail2; - if ((rc = efx_nic_test_tables(enp, __siena_tables, + if ((rc = siena_nic_test_tables(enp, __siena_tables, EFX_PATTERN_BYTE_CHANGING, EFX_ARRAY_SIZE(__siena_tables))) != 0) goto fail3; - if ((rc = efx_nic_test_tables(enp, __siena_tables, + if ((rc = siena_nic_test_tables(enp, __siena_tables, EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) goto fail4; return (0); fail4: EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #endif /* EFSYS_OPT_DIAG */ #endif /* EFSYS_OPT_SIENA */ Index: stable/12 =================================================================== --- stable/12 (revision 342314) +++ stable/12 (revision 342315) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r340883