net/sfc/base: import SFN7xxx family support
SFN7xxx is the first family based on EF10 architecture. EFSYS_OPT_HUNTINGTON should be enabled to use it. From Solarflare Communications Inc. Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
f7dc06bf35
commit
e7cd430c86
1226
drivers/net/sfc/base/ef10_ev.c
Normal file
1226
drivers/net/sfc/base/ef10_ev.c
Normal file
File diff suppressed because it is too large
Load Diff
1469
drivers/net/sfc/base/ef10_filter.c
Normal file
1469
drivers/net/sfc/base/ef10_filter.c
Normal file
File diff suppressed because it is too large
Load Diff
718
drivers/net/sfc/base/ef10_impl.h
Normal file
718
drivers/net/sfc/base/ef10_impl.h
Normal file
@ -0,0 +1,718 @@
|
||||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_EF10_IMPL_H
|
||||
#define _SYS_EF10_IMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
#define EF10_MAX_PIOBUF_NBUFS HUNT_PIOBUF_NBUFS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FIXME: This is just a power of 2 which fits in an MCDI v1 message, and could
|
||||
* possibly be increased, or the write size reported by newer firmware used
|
||||
* instead.
|
||||
*/
|
||||
#define EF10_NVRAM_CHUNK 0x80
|
||||
|
||||
/* Alignment requirement for value written to RX WPTR:
|
||||
* the WPTR must be aligned to an 8 descriptor boundary
|
||||
*/
|
||||
#define EF10_RX_WPTR_ALIGN 8
|
||||
|
||||
/*
|
||||
* Max byte offset into the packet the TCP header must start for the hardware
|
||||
* to be able to parse the packet correctly.
|
||||
*/
|
||||
#define EF10_TCP_HEADER_OFFSET_LIMIT 208
|
||||
|
||||
/* Invalid RSS context handle */
|
||||
#define EF10_RSS_CONTEXT_INVALID (0xffffffff)
|
||||
|
||||
|
||||
/* EV */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_ev_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
void
|
||||
ef10_ev_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_ev_qcreate(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int index,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in size_t n,
|
||||
__in uint32_t id,
|
||||
__in uint32_t us,
|
||||
__in uint32_t flags,
|
||||
__in efx_evq_t *eep);
|
||||
|
||||
void
|
||||
ef10_ev_qdestroy(
|
||||
__in efx_evq_t *eep);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_ev_qprime(
|
||||
__in efx_evq_t *eep,
|
||||
__in unsigned int count);
|
||||
|
||||
void
|
||||
ef10_ev_qpost(
|
||||
__in efx_evq_t *eep,
|
||||
__in uint16_t data);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_ev_qmoderate(
|
||||
__in efx_evq_t *eep,
|
||||
__in unsigned int us);
|
||||
|
||||
void
|
||||
ef10_ev_rxlabel_init(
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_rxq_t *erp,
|
||||
__in unsigned int label,
|
||||
__in boolean_t packed_stream);
|
||||
|
||||
void
|
||||
ef10_ev_rxlabel_fini(
|
||||
__in efx_evq_t *eep,
|
||||
__in unsigned int label);
|
||||
|
||||
/* INTR */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_intr_init(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_intr_type_t type,
|
||||
__in efsys_mem_t *esmp);
|
||||
|
||||
void
|
||||
ef10_intr_enable(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
void
|
||||
ef10_intr_disable(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
void
|
||||
ef10_intr_disable_unlocked(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_intr_trigger(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int level);
|
||||
|
||||
void
|
||||
ef10_intr_status_line(
|
||||
__in efx_nic_t *enp,
|
||||
__out boolean_t *fatalp,
|
||||
__out uint32_t *qmaskp);
|
||||
|
||||
void
|
||||
ef10_intr_status_message(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int message,
|
||||
__out boolean_t *fatalp);
|
||||
|
||||
void
|
||||
ef10_intr_fatal(
|
||||
__in efx_nic_t *enp);
|
||||
void
|
||||
ef10_intr_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
/* NIC */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_probe(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_set_drv_limits(
|
||||
__inout efx_nic_t *enp,
|
||||
__in efx_drv_limits_t *edlp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_get_vi_pool(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *vi_countp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_get_bar_region(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_nic_region_t region,
|
||||
__out uint32_t *offsetp,
|
||||
__out size_t *sizep);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_reset(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern void
|
||||
ef10_nic_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern void
|
||||
ef10_nic_unprobe(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
|
||||
/* MAC */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_poll(
|
||||
__in efx_nic_t *enp,
|
||||
__out efx_link_mode_t *link_modep);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_up(
|
||||
__in efx_nic_t *enp,
|
||||
__out boolean_t *mac_upp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_addr_set(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_pdu_set(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_pdu_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out size_t *pdu);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_reconfigure(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_multicast_list_set(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_filter_default_rxq_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_rxq_t *erp,
|
||||
__in boolean_t using_rss);
|
||||
|
||||
extern void
|
||||
ef10_mac_filter_default_rxq_clear(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
|
||||
/* MCDI */
|
||||
|
||||
#if EFSYS_OPT_MCDI
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mcdi_init(
|
||||
__in efx_nic_t *enp,
|
||||
__in const efx_mcdi_transport_t *mtp);
|
||||
|
||||
extern void
|
||||
ef10_mcdi_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern void
|
||||
ef10_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
|
||||
ef10_mcdi_poll_response(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern void
|
||||
ef10_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
|
||||
ef10_mcdi_poll_reboot(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mcdi_feature_supported(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_mcdi_feature_id_t id,
|
||||
__out boolean_t *supportedp);
|
||||
|
||||
extern void
|
||||
ef10_mcdi_get_timeout(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_mcdi_req_t *emrp,
|
||||
__out uint32_t *timeoutp);
|
||||
|
||||
#endif /* EFSYS_OPT_MCDI */
|
||||
|
||||
/* NVRAM */
|
||||
|
||||
|
||||
/* PHY */
|
||||
|
||||
typedef struct ef10_link_state_s {
|
||||
uint32_t els_adv_cap_mask;
|
||||
uint32_t els_lp_cap_mask;
|
||||
unsigned int els_fcntl;
|
||||
efx_link_mode_t els_link_mode;
|
||||
boolean_t els_mac_up;
|
||||
} ef10_link_state_t;
|
||||
|
||||
extern void
|
||||
ef10_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
|
||||
ef10_phy_get_link(
|
||||
__in efx_nic_t *enp,
|
||||
__out ef10_link_state_t *elsp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_phy_power(
|
||||
__in efx_nic_t *enp,
|
||||
__in boolean_t on);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_phy_reconfigure(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_phy_verify(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_phy_oui_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *ouip);
|
||||
|
||||
/* TX */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern void
|
||||
ef10_tx_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qcreate(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int index,
|
||||
__in unsigned int label,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in size_t n,
|
||||
__in uint32_t id,
|
||||
__in uint16_t flags,
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_txq_t *etp,
|
||||
__out unsigned int *addedp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qdestroy(
|
||||
__in efx_txq_t *etp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpost(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(n) efx_buffer_t *eb,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qpush(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int added,
|
||||
__in unsigned int pushed);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpace(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int ns);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qflush(
|
||||
__in efx_txq_t *etp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qenable(
|
||||
__in efx_txq_t *etp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpio_enable(
|
||||
__in efx_txq_t *etp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qpio_disable(
|
||||
__in efx_txq_t *etp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpio_write(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(buf_length) uint8_t *buffer,
|
||||
__in size_t buf_length,
|
||||
__in size_t pio_buf_offset);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpio_post(
|
||||
__in efx_txq_t *etp,
|
||||
__in size_t pkt_length,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qdesc_post(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(n) efx_desc_t *ed,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qdesc_dma_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in efsys_dma_addr_t addr,
|
||||
__in size_t size,
|
||||
__in boolean_t eop,
|
||||
__out efx_desc_t *edp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qdesc_tso_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t ipv4_id,
|
||||
__in uint32_t tcp_seq,
|
||||
__in uint8_t tcp_flags,
|
||||
__out efx_desc_t *edp);
|
||||
|
||||
extern void
|
||||
ef10_tx_qdesc_tso2_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t ipv4_id,
|
||||
__in uint32_t tcp_seq,
|
||||
__in uint16_t tcp_mss,
|
||||
__out_ecount(count) efx_desc_t *edp,
|
||||
__in int count);
|
||||
|
||||
extern void
|
||||
ef10_tx_qdesc_vlantci_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t vlan_tci,
|
||||
__out efx_desc_t *edp);
|
||||
|
||||
|
||||
typedef uint32_t efx_piobuf_handle_t;
|
||||
|
||||
#define EFX_PIOBUF_HANDLE_INVALID ((efx_piobuf_handle_t) -1)
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_pio_alloc(
|
||||
__inout efx_nic_t *enp,
|
||||
__out uint32_t *bufnump,
|
||||
__out efx_piobuf_handle_t *handlep,
|
||||
__out uint32_t *blknump,
|
||||
__out uint32_t *offsetp,
|
||||
__out size_t *sizep);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_pio_free(
|
||||
__inout efx_nic_t *enp,
|
||||
__in uint32_t bufnum,
|
||||
__in uint32_t blknum);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_pio_link(
|
||||
__inout efx_nic_t *enp,
|
||||
__in uint32_t vi_index,
|
||||
__in efx_piobuf_handle_t handle);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_pio_unlink(
|
||||
__inout efx_nic_t *enp,
|
||||
__in uint32_t vi_index);
|
||||
|
||||
|
||||
/* VPD */
|
||||
|
||||
|
||||
/* RX */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_rx_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_rx_prefix_pktlen(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint8_t *buffer,
|
||||
__out uint16_t *lengthp);
|
||||
|
||||
extern void
|
||||
ef10_rx_qpost(
|
||||
__in efx_rxq_t *erp,
|
||||
__in_ecount(n) efsys_dma_addr_t *addrp,
|
||||
__in size_t size,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__in unsigned int added);
|
||||
|
||||
extern void
|
||||
ef10_rx_qpush(
|
||||
__in efx_rxq_t *erp,
|
||||
__in unsigned int added,
|
||||
__inout unsigned int *pushedp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_rx_qflush(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern void
|
||||
ef10_rx_qenable(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_rx_qcreate(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int index,
|
||||
__in unsigned int label,
|
||||
__in efx_rxq_type_t type,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in size_t n,
|
||||
__in uint32_t id,
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern void
|
||||
ef10_rx_qdestroy(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern void
|
||||
ef10_rx_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
#if EFSYS_OPT_FILTER
|
||||
|
||||
typedef struct ef10_filter_handle_s {
|
||||
uint32_t efh_lo;
|
||||
uint32_t efh_hi;
|
||||
} ef10_filter_handle_t;
|
||||
|
||||
typedef struct ef10_filter_entry_s {
|
||||
uintptr_t efe_spec; /* pointer to filter spec plus busy bit */
|
||||
ef10_filter_handle_t efe_handle;
|
||||
} ef10_filter_entry_t;
|
||||
|
||||
/*
|
||||
* BUSY flag indicates that an update is in progress.
|
||||
* AUTO_OLD flag is used to mark and sweep MAC packet filters.
|
||||
*/
|
||||
#define EFX_EF10_FILTER_FLAG_BUSY 1U
|
||||
#define EFX_EF10_FILTER_FLAG_AUTO_OLD 2U
|
||||
#define EFX_EF10_FILTER_FLAGS 3U
|
||||
|
||||
/*
|
||||
* Size of the hash table used by the driver. Doesn't need to be the
|
||||
* same size as the hardware's table.
|
||||
*/
|
||||
#define EFX_EF10_FILTER_TBL_ROWS 8192
|
||||
|
||||
/* Only need to allow for one directed and one unknown unicast filter */
|
||||
#define EFX_EF10_FILTER_UNICAST_FILTERS_MAX 2
|
||||
|
||||
/* Allow for the broadcast address to be added to the multicast list */
|
||||
#define EFX_EF10_FILTER_MULTICAST_FILTERS_MAX (EFX_MAC_MULTICAST_LIST_MAX + 1)
|
||||
|
||||
typedef struct ef10_filter_table_s {
|
||||
ef10_filter_entry_t eft_entry[EFX_EF10_FILTER_TBL_ROWS];
|
||||
efx_rxq_t *eft_default_rxq;
|
||||
boolean_t eft_using_rss;
|
||||
uint32_t eft_unicst_filter_indexes[
|
||||
EFX_EF10_FILTER_UNICAST_FILTERS_MAX];
|
||||
uint32_t eft_unicst_filter_count;
|
||||
uint32_t eft_mulcst_filter_indexes[
|
||||
EFX_EF10_FILTER_MULTICAST_FILTERS_MAX];
|
||||
uint32_t eft_mulcst_filter_count;
|
||||
boolean_t eft_using_all_mulcst;
|
||||
} ef10_filter_table_t;
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_filter_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
void
|
||||
ef10_filter_fini(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_filter_restore(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_filter_add(
|
||||
__in efx_nic_t *enp,
|
||||
__inout efx_filter_spec_t *spec,
|
||||
__in boolean_t may_replace);
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_filter_delete(
|
||||
__in efx_nic_t *enp,
|
||||
__inout efx_filter_spec_t *spec);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_filter_supported_filters(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *list,
|
||||
__out size_t *length);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_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);
|
||||
|
||||
extern void
|
||||
ef10_filter_get_default_rxq(
|
||||
__in efx_nic_t *enp,
|
||||
__out efx_rxq_t **erpp,
|
||||
__out boolean_t *using_rss);
|
||||
|
||||
extern void
|
||||
ef10_filter_default_rxq_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_rxq_t *erp,
|
||||
__in boolean_t using_rss);
|
||||
|
||||
extern void
|
||||
ef10_filter_default_rxq_clear(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
|
||||
#endif /* EFSYS_OPT_FILTER */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_function_info(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *pfp,
|
||||
__out_opt uint32_t *vfp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_privilege_mask(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t pf,
|
||||
__in uint32_t vf,
|
||||
__out uint32_t *maskp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_port_assignment(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *portp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_port_modes(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *modesp,
|
||||
__out_opt uint32_t *current_modep);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_nic_get_port_mode_bandwidth(
|
||||
__in uint32_t port_mode,
|
||||
__out uint32_t *bandwidth_mbpsp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_mac_address_pf(
|
||||
__in efx_nic_t *enp,
|
||||
__out_ecount_opt(6) uint8_t mac_addrp[6]);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_mac_address_vf(
|
||||
__in efx_nic_t *enp,
|
||||
__out_ecount_opt(6) uint8_t mac_addrp[6]);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_clock(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *sys_freqp,
|
||||
__out uint32_t *dpcpu_freqp);
|
||||
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_vector_cfg(
|
||||
__in efx_nic_t *enp,
|
||||
__out_opt uint32_t *vec_basep,
|
||||
__out_opt uint32_t *pf_nvecp,
|
||||
__out_opt uint32_t *vf_nvecp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_get_datapath_caps(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_get_privilege_mask(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *maskp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_external_port_mapping(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t port,
|
||||
__out uint8_t *external_portp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_EF10_IMPL_H */
|
197
drivers/net/sfc/base/ef10_intr.c
Normal file
197
drivers/net/sfc/base/ef10_intr.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_intr_init(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_intr_type_t type,
|
||||
__in efsys_mem_t *esmp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp, type, esmp))
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ef10_intr_enable(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ef10_intr_disable(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ef10_intr_disable_unlocked(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_trigger_interrupt(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int level)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_TRIGGER_INTERRUPT_IN_LEN,
|
||||
MC_CMD_TRIGGER_INTERRUPT_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
if (level >= enp->en_nic_cfg.enc_intr_limit) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_TRIGGER_INTERRUPT;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_TRIGGER_INTERRUPT_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_TRIGGER_INTERRUPT_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, TRIGGER_INTERRUPT_IN_INTR_LEVEL, level);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_intr_trigger(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int level)
|
||||
{
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_rc_t rc;
|
||||
|
||||
if (encp->enc_bug41750_workaround) {
|
||||
/*
|
||||
* bug 41750: Test interrupts don't work on Greenport
|
||||
* bug 50084: Test interrupts don't work on VFs
|
||||
*/
|
||||
rc = ENOTSUP;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if ((rc = efx_mcdi_trigger_interrupt(enp, level)) != 0)
|
||||
goto fail2;
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_intr_status_line(
|
||||
__in efx_nic_t *enp,
|
||||
__out boolean_t *fatalp,
|
||||
__out uint32_t *qmaskp)
|
||||
{
|
||||
efx_dword_t dword;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
/* Read the queue mask and implicitly acknowledge the interrupt. */
|
||||
EFX_BAR_READD(enp, ER_DZ_BIU_INT_ISR_REG, &dword, B_FALSE);
|
||||
*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
|
||||
|
||||
EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
|
||||
|
||||
*fatalp = B_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
ef10_intr_status_message(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int message,
|
||||
__out boolean_t *fatalp)
|
||||
{
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
_NOTE(ARGUNUSED(enp, message))
|
||||
|
||||
/* EF10 fatal errors are reported via events */
|
||||
*fatalp = B_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
ef10_intr_fatal(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
/* EF10 fatal errors are reported via events */
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
void
|
||||
ef10_intr_fini(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
446
drivers/net/sfc/base/ef10_mac.c
Normal file
446
drivers/net/sfc/base/ef10_mac.c
Normal file
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_poll(
|
||||
__in efx_nic_t *enp,
|
||||
__out efx_link_mode_t *link_modep)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
ef10_link_state_t els;
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = ef10_phy_get_link(enp, &els)) != 0)
|
||||
goto fail1;
|
||||
|
||||
epp->ep_adv_cap_mask = els.els_adv_cap_mask;
|
||||
epp->ep_fcntl = els.els_fcntl;
|
||||
|
||||
*link_modep = els.els_link_mode;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
*link_modep = EFX_LINK_UNKNOWN;
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_up(
|
||||
__in efx_nic_t *enp,
|
||||
__out boolean_t *mac_upp)
|
||||
{
|
||||
ef10_link_state_t els;
|
||||
efx_rc_t rc;
|
||||
|
||||
/*
|
||||
* Because EF10 doesn't *require* polling, we can't rely on
|
||||
* ef10_mac_poll() being executed to populate epp->ep_mac_up.
|
||||
*/
|
||||
if ((rc = ef10_phy_get_link(enp, &els)) != 0)
|
||||
goto fail1;
|
||||
|
||||
*mac_upp = els.els_mac_up;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* EF10 adapters use MC_CMD_VADAPTOR_SET_MAC to set the
|
||||
* MAC address; the address field in MC_CMD_SET_MAC has no
|
||||
* effect.
|
||||
* MC_CMD_VADAPTOR_SET_MAC requires mac-spoofing privilege and
|
||||
* the port to have no filters or queues active.
|
||||
*/
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_vadapter_set_mac(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_VADAPTOR_SET_MAC_IN_LEN,
|
||||
MC_CMD_VADAPTOR_SET_MAC_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_VADAPTOR_SET_MAC;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_VADAPTOR_SET_MAC_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_VADAPTOR_SET_MAC_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
|
||||
enp->en_vport_id);
|
||||
EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, VADAPTOR_SET_MAC_IN_MACADDR),
|
||||
epp->ep_mac_addr);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_addr_set(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_vadapter_set_mac(enp)) != 0) {
|
||||
if (rc != ENOTSUP)
|
||||
goto fail1;
|
||||
|
||||
/*
|
||||
* Fallback for older Huntington firmware without Vadapter
|
||||
* support.
|
||||
*/
|
||||
if ((rc = ef10_mac_reconfigure(enp)) != 0)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_mtu_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t mtu)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_SET_MAC_EXT_IN_LEN,
|
||||
MC_CMD_SET_MAC_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_SET_MAC;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_SET_MAC_EXT_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;
|
||||
|
||||
/* Only configure the MTU in this call to MC_CMD_SET_MAC */
|
||||
MCDI_IN_SET_DWORD(req, SET_MAC_EXT_IN_MTU, mtu);
|
||||
MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_EXT_IN_CONTROL,
|
||||
SET_MAC_EXT_IN_CFG_MTU, 1);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_mtu_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out size_t *mtu)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_SET_MAC_EXT_IN_LEN,
|
||||
MC_CMD_SET_MAC_V2_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_SET_MAC;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_SET_MAC_EXT_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_SET_MAC_V2_OUT_LEN;
|
||||
|
||||
/*
|
||||
* With MC_CMD_SET_MAC_EXT_IN_CONTROL set to 0, this just queries the
|
||||
* MTU. This should always be supported on Medford, but it is not
|
||||
* supported on older Huntington firmware.
|
||||
*/
|
||||
MCDI_IN_SET_DWORD(req, SET_MAC_EXT_IN_CONTROL, 0);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
if (req.emr_out_length_used < MC_CMD_SET_MAC_V2_OUT_MTU_OFST + 4) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
*mtu = MCDI_OUT_DWORD(req, SET_MAC_V2_OUT_MTU);
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_pdu_set(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_rc_t rc;
|
||||
|
||||
if (encp->enc_enhanced_set_mac_supported) {
|
||||
if ((rc = efx_mcdi_mtu_set(enp, epp->ep_mac_pdu)) != 0)
|
||||
goto fail1;
|
||||
} else {
|
||||
/*
|
||||
* Fallback for older Huntington firmware, which always
|
||||
* configure all of the parameters to MC_CMD_SET_MAC. This isn't
|
||||
* suitable for setting the MTU on unpriviliged functions.
|
||||
*/
|
||||
if ((rc = ef10_mac_reconfigure(enp)) != 0)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_pdu_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out size_t *pdu)
|
||||
{
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_mtu_get(enp, pdu)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_reconfigure(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_SET_MAC_IN_LEN,
|
||||
MC_CMD_SET_MAC_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_SET_MAC;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
|
||||
MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
|
||||
EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
|
||||
epp->ep_mac_addr);
|
||||
|
||||
/*
|
||||
* Note: The Huntington MAC does not support REJECT_BRDCST.
|
||||
* The REJECT_UNCST flag will also prevent multicast traffic
|
||||
* from reaching the filters. As Huntington filters drop any
|
||||
* traffic that does not match a filter it is ok to leave the
|
||||
* MAC running in promiscuous mode. See bug41141.
|
||||
*
|
||||
* FIXME: Does REJECT_UNCST behave the same way on Medford?
|
||||
*/
|
||||
MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
|
||||
SET_MAC_IN_REJECT_UNCST, 0,
|
||||
SET_MAC_IN_REJECT_BRDCST, 0);
|
||||
|
||||
/*
|
||||
* Flow control, whether it is auto-negotiated or not,
|
||||
* is set via the PHY advertised capabilities. When set to
|
||||
* automatic the MAC will use the PHY settings to determine
|
||||
* the flow control settings.
|
||||
*/
|
||||
MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, MC_CMD_FCNTL_AUTO);
|
||||
|
||||
/* Do not include the Ethernet frame checksum in RX packets */
|
||||
MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_IN_FLAGS,
|
||||
SET_MAC_IN_FLAG_INCLUDE_FCS, 0);
|
||||
|
||||
efx_mcdi_execute_quiet(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
/*
|
||||
* Unprivileged functions cannot control link state,
|
||||
* but still need to configure filters.
|
||||
*/
|
||||
if (req.emr_rc != EACCES) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the filters for the MAC configuration.
|
||||
* If the NIC isn't ready to accept filters this may
|
||||
* return success without setting anything.
|
||||
*/
|
||||
rc = efx_filter_reconfigure(enp, epp->ep_mac_addr,
|
||||
epp->ep_all_unicst, epp->ep_mulcst,
|
||||
epp->ep_all_mulcst, epp->ep_brdcst,
|
||||
epp->ep_mulcst_addr_list,
|
||||
epp->ep_mulcst_addr_count);
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_multicast_list_set(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
const efx_mac_ops_t *emop = epp->ep_emop;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
if ((rc = emop->emo_reconfigure(enp)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_filter_default_rxq_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_rxq_t *erp,
|
||||
__in boolean_t using_rss)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_rxq_t *old_rxq;
|
||||
boolean_t old_using_rss;
|
||||
efx_rc_t rc;
|
||||
|
||||
ef10_filter_get_default_rxq(enp, &old_rxq, &old_using_rss);
|
||||
|
||||
ef10_filter_default_rxq_set(enp, erp, using_rss);
|
||||
|
||||
rc = efx_filter_reconfigure(enp, epp->ep_mac_addr,
|
||||
epp->ep_all_unicst, epp->ep_mulcst,
|
||||
epp->ep_all_mulcst, epp->ep_brdcst,
|
||||
epp->ep_mulcst_addr_list,
|
||||
epp->ep_mulcst_addr_count);
|
||||
|
||||
if (rc != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
ef10_filter_default_rxq_set(enp, old_rxq, old_using_rss);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_mac_filter_default_rxq_clear(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
|
||||
ef10_filter_default_rxq_clear(enp);
|
||||
|
||||
efx_filter_reconfigure(enp, epp->ep_mac_addr,
|
||||
epp->ep_all_unicst, epp->ep_mulcst,
|
||||
epp->ep_all_mulcst, epp->ep_brdcst,
|
||||
epp->ep_mulcst_addr_list,
|
||||
epp->ep_mulcst_addr_count);
|
||||
}
|
||||
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
342
drivers/net/sfc/base/ef10_mcdi.c
Normal file
342
drivers/net/sfc/base/ef10_mcdi.c
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
#if EFSYS_OPT_MCDI
|
||||
|
||||
#ifndef WITH_MCDI_V2
|
||||
#error "WITH_MCDI_V2 required for EF10 MCDIv2 commands."
|
||||
#endif
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mcdi_init(
|
||||
__in efx_nic_t *enp,
|
||||
__in const efx_mcdi_transport_t *emtp)
|
||||
{
|
||||
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
||||
efsys_mem_t *esmp = emtp->emt_dma_mem;
|
||||
efx_dword_t dword;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
EFSYS_ASSERT(enp->en_features & EFX_FEATURE_MCDI_DMA);
|
||||
|
||||
/*
|
||||
* All EF10 firmware supports MCDIv2 and MCDIv1.
|
||||
* Medford BootROM supports MCDIv2 and MCDIv1.
|
||||
* Huntington BootROM supports MCDIv1 only.
|
||||
*/
|
||||
emip->emi_max_version = 2;
|
||||
|
||||
/* A host DMA buffer is required for EF10 MCDI */
|
||||
if (esmp == NULL) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the MC doorbell is in a known state before issuing MCDI
|
||||
* commands. The recovery algorithm requires that the MC command buffer
|
||||
* must be 256 byte aligned. See bug24769.
|
||||
*/
|
||||
if ((EFSYS_MEM_ADDR(esmp) & 0xFF) != 0) {
|
||||
rc = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 1);
|
||||
EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
|
||||
|
||||
/* Save initial MC reboot status */
|
||||
(void) ef10_mcdi_poll_reboot(enp);
|
||||
|
||||
/* Start a new epoch (allow fresh MCDI requests to succeed) */
|
||||
efx_mcdi_new_epoch(enp);
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_mcdi_fini(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
||||
|
||||
emip->emi_new_epoch = B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* In older firmware all commands are processed in a single thread, so a long
|
||||
* running command for one PCIe function can block processing for another
|
||||
* function (see bug 61269).
|
||||
*
|
||||
* In newer firmware that supports multithreaded MCDI processing, we can extend
|
||||
* the timeout for long-running requests which we know firmware may choose to
|
||||
* process in a background thread.
|
||||
*/
|
||||
#define EF10_MCDI_CMD_TIMEOUT_US (10 * 1000 * 1000)
|
||||
#define EF10_MCDI_CMD_LONG_TIMEOUT_US (60 * 1000 * 1000)
|
||||
|
||||
void
|
||||
ef10_mcdi_get_timeout(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_mcdi_req_t *emrp,
|
||||
__out uint32_t *timeoutp)
|
||||
{
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
|
||||
switch (emrp->emr_cmd) {
|
||||
case MC_CMD_POLL_BIST:
|
||||
case MC_CMD_NVRAM_ERASE:
|
||||
case MC_CMD_LICENSING_V3:
|
||||
case MC_CMD_NVRAM_UPDATE_FINISH:
|
||||
if (encp->enc_fw_verified_nvram_update_required != B_FALSE) {
|
||||
/*
|
||||
* Potentially longer running commands, which firmware
|
||||
* may choose to process in a background thread.
|
||||
*/
|
||||
*timeoutp = EF10_MCDI_CMD_LONG_TIMEOUT_US;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
*timeoutp = EF10_MCDI_CMD_TIMEOUT_US;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ef10_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)
|
||||
{
|
||||
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
|
||||
efsys_mem_t *esmp = emtp->emt_dma_mem;
|
||||
efx_dword_t dword;
|
||||
unsigned int pos;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
/* Write the header */
|
||||
for (pos = 0; pos < hdr_len; pos += sizeof (efx_dword_t)) {
|
||||
dword = *(efx_dword_t *)((uint8_t *)hdrp + pos);
|
||||
EFSYS_MEM_WRITED(esmp, pos, &dword);
|
||||
}
|
||||
|
||||
/* Write the payload */
|
||||
for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) {
|
||||
dword = *(efx_dword_t *)((uint8_t *)sdup + pos);
|
||||
EFSYS_MEM_WRITED(esmp, hdr_len + pos, &dword);
|
||||
}
|
||||
|
||||
/* Guarantee ordering of memory (MCDI request) and PIO (MC doorbell) */
|
||||
EFSYS_DMA_SYNC_FOR_DEVICE(esmp, 0, hdr_len + sdu_len);
|
||||
EFSYS_PIO_WRITE_BARRIER();
|
||||
|
||||
/* Ring the doorbell to post the command DMA address to the MC */
|
||||
EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
|
||||
EFSYS_MEM_ADDR(esmp) >> 32);
|
||||
EFX_BAR_WRITED(enp, ER_DZ_MC_DB_LWRD_REG, &dword, B_FALSE);
|
||||
|
||||
EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
|
||||
EFSYS_MEM_ADDR(esmp) & 0xffffffff);
|
||||
EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
|
||||
}
|
||||
|
||||
__checkReturn boolean_t
|
||||
ef10_mcdi_poll_response(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
|
||||
efsys_mem_t *esmp = emtp->emt_dma_mem;
|
||||
efx_dword_t hdr;
|
||||
|
||||
EFSYS_MEM_READD(esmp, 0, &hdr);
|
||||
EFSYS_MEM_READ_BARRIER();
|
||||
|
||||
return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_mcdi_read_response(
|
||||
__in efx_nic_t *enp,
|
||||
__out_bcount(length) void *bufferp,
|
||||
__in size_t offset,
|
||||
__in size_t length)
|
||||
{
|
||||
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
|
||||
efsys_mem_t *esmp = emtp->emt_dma_mem;
|
||||
unsigned int pos;
|
||||
efx_dword_t data;
|
||||
|
||||
for (pos = 0; pos < length; pos += sizeof (efx_dword_t)) {
|
||||
EFSYS_MEM_READD(esmp, offset + pos, &data);
|
||||
memcpy((uint8_t *)bufferp + pos, &data,
|
||||
MIN(sizeof (data), length - pos));
|
||||
}
|
||||
}
|
||||
|
||||
efx_rc_t
|
||||
ef10_mcdi_poll_reboot(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
||||
efx_dword_t dword;
|
||||
uint32_t old_status;
|
||||
uint32_t new_status;
|
||||
efx_rc_t rc;
|
||||
|
||||
old_status = emip->emi_mc_reboot_status;
|
||||
|
||||
/* Update MC reboot status word */
|
||||
EFX_BAR_TBL_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, 0, &dword, B_FALSE);
|
||||
new_status = dword.ed_u32[0];
|
||||
|
||||
/* MC has rebooted if the value has changed */
|
||||
if (new_status != old_status) {
|
||||
emip->emi_mc_reboot_status = new_status;
|
||||
|
||||
/*
|
||||
* FIXME: Ignore detected MC REBOOT for now.
|
||||
*
|
||||
* The Siena support for checking for MC reboot from status
|
||||
* flags is broken - see comments in siena_mcdi_poll_reboot().
|
||||
* As the generic MCDI code is shared the EF10 reboot
|
||||
* detection suffers similar problems.
|
||||
*
|
||||
* Do not report an error when the boot status changes until
|
||||
* this can be handled by common code drivers (and reworked to
|
||||
* support Siena too).
|
||||
*/
|
||||
_NOTE(CONSTANTCONDITION)
|
||||
if (B_FALSE) {
|
||||
rc = EIO;
|
||||
goto fail1;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mcdi_feature_supported(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_mcdi_feature_id_t id,
|
||||
__out boolean_t *supportedp)
|
||||
{
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
uint32_t privilege_mask = encp->enc_privilege_mask;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD);
|
||||
|
||||
/*
|
||||
* Use privilege mask state at MCDI attach.
|
||||
*/
|
||||
|
||||
switch (id) {
|
||||
case EFX_MCDI_FEATURE_FW_UPDATE:
|
||||
/*
|
||||
* Admin privilege must be used prior to introduction of
|
||||
* specific flag.
|
||||
*/
|
||||
*supportedp =
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
|
||||
break;
|
||||
case EFX_MCDI_FEATURE_LINK_CONTROL:
|
||||
/*
|
||||
* Admin privilege used prior to introduction of
|
||||
* specific flag.
|
||||
*/
|
||||
*supportedp =
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, LINK) ||
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
|
||||
break;
|
||||
case EFX_MCDI_FEATURE_MACADDR_CHANGE:
|
||||
/*
|
||||
* Admin privilege must be used prior to introduction of
|
||||
* mac spoofing privilege (at v4.6), which is used up to
|
||||
* introduction of change mac spoofing privilege (at v4.7)
|
||||
*/
|
||||
*supportedp =
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, CHANGE_MAC) ||
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) ||
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
|
||||
break;
|
||||
case EFX_MCDI_FEATURE_MAC_SPOOFING:
|
||||
/*
|
||||
* Admin privilege must be used prior to introduction of
|
||||
* mac spoofing privilege (at v4.6), which is used up to
|
||||
* introduction of mac spoofing TX privilege (at v4.7)
|
||||
*/
|
||||
*supportedp =
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING_TX) ||
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) ||
|
||||
EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
|
||||
break;
|
||||
default:
|
||||
rc = ENOTSUP;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_MCDI */
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
1769
drivers/net/sfc/base/ef10_nic.c
Normal file
1769
drivers/net/sfc/base/ef10_nic.c
Normal file
File diff suppressed because it is too large
Load Diff
393
drivers/net/sfc/base/ef10_phy.c
Normal file
393
drivers/net/sfc/base/ef10_phy.c
Normal file
@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
static void
|
||||
mcdi_phy_decode_cap(
|
||||
__in uint32_t mcdi_cap,
|
||||
__out uint32_t *maskp)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = 0;
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_10HDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_10FDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_100HDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_100FDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_1000HDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_1000FDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_10000FDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_40000FDX);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_PAUSE);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_ASYM);
|
||||
if (mcdi_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
|
||||
mask |= (1 << EFX_PHY_CAP_AN);
|
||||
|
||||
*maskp = mask;
|
||||
}
|
||||
|
||||
static void
|
||||
mcdi_phy_decode_link_mode(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t link_flags,
|
||||
__in unsigned int speed,
|
||||
__in unsigned int fcntl,
|
||||
__out efx_link_mode_t *link_modep,
|
||||
__out unsigned int *fcntlp)
|
||||
{
|
||||
boolean_t fd = !!(link_flags &
|
||||
(1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
|
||||
boolean_t up = !!(link_flags &
|
||||
(1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
|
||||
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
|
||||
if (!up)
|
||||
*link_modep = EFX_LINK_DOWN;
|
||||
else if (speed == 40000 && fd)
|
||||
*link_modep = EFX_LINK_40000FDX;
|
||||
else if (speed == 10000 && fd)
|
||||
*link_modep = EFX_LINK_10000FDX;
|
||||
else if (speed == 1000)
|
||||
*link_modep = fd ? EFX_LINK_1000FDX : EFX_LINK_1000HDX;
|
||||
else if (speed == 100)
|
||||
*link_modep = fd ? EFX_LINK_100FDX : EFX_LINK_100HDX;
|
||||
else if (speed == 10)
|
||||
*link_modep = fd ? EFX_LINK_10FDX : EFX_LINK_10HDX;
|
||||
else
|
||||
*link_modep = EFX_LINK_UNKNOWN;
|
||||
|
||||
if (fcntl == MC_CMD_FCNTL_OFF)
|
||||
*fcntlp = 0;
|
||||
else if (fcntl == MC_CMD_FCNTL_RESPOND)
|
||||
*fcntlp = EFX_FCNTL_RESPOND;
|
||||
else if (fcntl == MC_CMD_FCNTL_GENERATE)
|
||||
*fcntlp = EFX_FCNTL_GENERATE;
|
||||
else if (fcntl == MC_CMD_FCNTL_BIDIR)
|
||||
*fcntlp = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
|
||||
else {
|
||||
EFSYS_PROBE1(mc_pcol_error, int, fcntl);
|
||||
*fcntlp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ef10_phy_link_ev(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_qword_t *eqp,
|
||||
__out efx_link_mode_t *link_modep)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
unsigned int link_flags;
|
||||
unsigned int speed;
|
||||
unsigned int fcntl;
|
||||
efx_link_mode_t link_mode;
|
||||
uint32_t lp_cap_mask;
|
||||
|
||||
/*
|
||||
* Convert the LINKCHANGE speed enumeration into mbit/s, in the
|
||||
* same way as GET_LINK encodes the speed
|
||||
*/
|
||||
switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) {
|
||||
case MCDI_EVENT_LINKCHANGE_SPEED_100M:
|
||||
speed = 100;
|
||||
break;
|
||||
case MCDI_EVENT_LINKCHANGE_SPEED_1G:
|
||||
speed = 1000;
|
||||
break;
|
||||
case MCDI_EVENT_LINKCHANGE_SPEED_10G:
|
||||
speed = 10000;
|
||||
break;
|
||||
case MCDI_EVENT_LINKCHANGE_SPEED_40G:
|
||||
speed = 40000;
|
||||
break;
|
||||
default:
|
||||
speed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
|
||||
mcdi_phy_decode_link_mode(enp, link_flags, speed,
|
||||
MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL),
|
||||
&link_mode, &fcntl);
|
||||
mcdi_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
|
||||
&lp_cap_mask);
|
||||
|
||||
/*
|
||||
* It's safe to update ep_lp_cap_mask without the driver's port lock
|
||||
* because presumably any concurrently running efx_port_poll() is
|
||||
* only going to arrive at the same value.
|
||||
*
|
||||
* ep_fcntl has two meanings. It's either the link common fcntl
|
||||
* (if the PHY supports AN), or it's the forced link state. If
|
||||
* the former, it's safe to update the value for the same reason as
|
||||
* for ep_lp_cap_mask. If the latter, then just ignore the value,
|
||||
* because we can race with efx_mac_fcntl_set().
|
||||
*/
|
||||
epp->ep_lp_cap_mask = lp_cap_mask;
|
||||
epp->ep_fcntl = fcntl;
|
||||
|
||||
*link_modep = link_mode;
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_phy_power(
|
||||
__in efx_nic_t *enp,
|
||||
__in boolean_t power)
|
||||
{
|
||||
efx_rc_t rc;
|
||||
|
||||
if (!power)
|
||||
return (0);
|
||||
|
||||
/* Check if the PHY is a zombie */
|
||||
if ((rc = ef10_phy_verify(enp)) != 0)
|
||||
goto fail1;
|
||||
|
||||
enp->en_reset_flags |= EFX_RESET_PHY;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_phy_get_link(
|
||||
__in efx_nic_t *enp,
|
||||
__out ef10_link_state_t *elsp)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_GET_LINK_IN_LEN,
|
||||
MC_CMD_GET_LINK_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_GET_LINK;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_GET_LINK_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_GET_LINK_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_LINK_OUT_LEN) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
|
||||
&elsp->els_adv_cap_mask);
|
||||
mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
|
||||
&elsp->els_lp_cap_mask);
|
||||
|
||||
mcdi_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
|
||||
MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED),
|
||||
MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
|
||||
&elsp->els_link_mode, &elsp->els_fcntl);
|
||||
|
||||
elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_phy_reconfigure(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_SET_LINK_IN_LEN,
|
||||
MC_CMD_SET_LINK_OUT_LEN)];
|
||||
uint32_t cap_mask;
|
||||
unsigned int led_mode;
|
||||
unsigned int speed;
|
||||
boolean_t supported;
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_link_control_supported(enp, &supported)) != 0)
|
||||
goto fail1;
|
||||
if (supported == B_FALSE)
|
||||
goto out;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_SET_LINK;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN;
|
||||
|
||||
cap_mask = epp->ep_adv_cap_mask;
|
||||
MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
|
||||
PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
|
||||
PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
|
||||
PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
|
||||
PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
|
||||
PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
|
||||
PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
|
||||
PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
|
||||
PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
|
||||
PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
|
||||
PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
|
||||
/* Too many fields for for POPULATE macros, so insert this afterwards */
|
||||
MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
|
||||
PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);
|
||||
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
|
||||
speed = 0;
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);
|
||||
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/* And set the blink mode */
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_SET_ID_LED;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail3;
|
||||
}
|
||||
out:
|
||||
return (0);
|
||||
|
||||
fail3:
|
||||
EFSYS_PROBE(fail3);
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_phy_verify(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_GET_PHY_STATE_IN_LEN,
|
||||
MC_CMD_GET_PHY_STATE_OUT_LEN)];
|
||||
uint32_t state;
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_GET_PHY_STATE;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_GET_PHY_STATE_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_GET_PHY_STATE_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_PHY_STATE_OUT_LEN) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE);
|
||||
if (state != MC_CMD_PHY_STATE_OK) {
|
||||
if (state != MC_CMD_PHY_STATE_ZOMBIE)
|
||||
EFSYS_PROBE1(mc_pcol_error, int, state);
|
||||
rc = ENOTACTIVE;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail3:
|
||||
EFSYS_PROBE(fail3);
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_phy_oui_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *ouip)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp, ouip))
|
||||
|
||||
return (ENOTSUP);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
397
drivers/net/sfc/base/ef10_rx.c
Normal file
397
drivers/net/sfc/base/ef10_rx.c
Normal file
@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_init_rxq(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t size,
|
||||
__in uint32_t target_evq,
|
||||
__in uint32_t label,
|
||||
__in uint32_t instance,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in boolean_t disable_scatter,
|
||||
__in uint32_t ps_bufsize)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_INIT_RXQ_EXT_IN_LEN,
|
||||
MC_CMD_INIT_RXQ_EXT_OUT_LEN)];
|
||||
int npages = EFX_RXQ_NBUFS(size);
|
||||
int i;
|
||||
efx_qword_t *dma_addr;
|
||||
uint64_t addr;
|
||||
efx_rc_t rc;
|
||||
uint32_t dma_mode;
|
||||
|
||||
/* If this changes, then the payload size might need to change. */
|
||||
EFSYS_ASSERT3U(MC_CMD_INIT_RXQ_OUT_LEN, ==, 0);
|
||||
EFSYS_ASSERT3U(size, <=, EFX_RXQ_MAXNDESCS);
|
||||
|
||||
if (ps_bufsize > 0)
|
||||
dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM;
|
||||
else
|
||||
dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_INIT_RXQ;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_INIT_RXQ_EXT_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_INIT_RXQ_EXT_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, size);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, target_evq);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance);
|
||||
MCDI_IN_POPULATE_DWORD_8(req, INIT_RXQ_EXT_IN_FLAGS,
|
||||
INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0,
|
||||
INIT_RXQ_EXT_IN_CRC_MODE, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_PREFIX, 1,
|
||||
INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, disable_scatter,
|
||||
INIT_RXQ_EXT_IN_DMA_MODE,
|
||||
dma_mode,
|
||||
INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, ps_bufsize);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
|
||||
|
||||
dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR);
|
||||
addr = EFSYS_MEM_ADDR(esmp);
|
||||
|
||||
for (i = 0; i < npages; i++) {
|
||||
EFX_POPULATE_QWORD_2(*dma_addr,
|
||||
EFX_DWORD_1, (uint32_t)(addr >> 32),
|
||||
EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
|
||||
|
||||
dma_addr++;
|
||||
addr += EFX_BUF_SIZE;
|
||||
}
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_fini_rxq(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t instance)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_FINI_RXQ_IN_LEN,
|
||||
MC_CMD_FINI_RXQ_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_FINI_RXQ;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance);
|
||||
|
||||
efx_mcdi_execute_quiet(enp, &req);
|
||||
|
||||
if ((req.emr_rc != 0) && (req.emr_rc != MC_CMD_ERR_EALREADY)) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_rx_init(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EF10 RX pseudo-header
|
||||
* ---------------------
|
||||
*
|
||||
* Receive packets are prefixed by an (optional) 14 byte pseudo-header:
|
||||
*
|
||||
* +00: Toeplitz hash value.
|
||||
* (32bit little-endian)
|
||||
* +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
|
||||
* (16bit big-endian)
|
||||
* +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
|
||||
* (16bit big-endian)
|
||||
* +08: Packet Length. Zero if the RX datapath was in cut-through mode.
|
||||
* (16bit little-endian)
|
||||
* +10: MAC timestamp. Zero if timestamping is not enabled.
|
||||
* (32bit little-endian)
|
||||
*
|
||||
* See "The RX Pseudo-header" in SF-109306-TC.
|
||||
*/
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_rx_prefix_pktlen(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint8_t *buffer,
|
||||
__out uint16_t *lengthp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
|
||||
/*
|
||||
* The RX pseudo-header contains the packet length, excluding the
|
||||
* pseudo-header. If the hardware receive datapath was operating in
|
||||
* cut-through mode then the length in the RX pseudo-header will be
|
||||
* zero, and the packet length must be obtained from the DMA length
|
||||
* reported in the RX event.
|
||||
*/
|
||||
*lengthp = buffer[8] | (buffer[9] << 8);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_rx_qpost(
|
||||
__in efx_rxq_t *erp,
|
||||
__in_ecount(n) efsys_dma_addr_t *addrp,
|
||||
__in size_t size,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__in unsigned int added)
|
||||
{
|
||||
efx_qword_t qword;
|
||||
unsigned int i;
|
||||
unsigned int offset;
|
||||
unsigned int id;
|
||||
|
||||
/* The client driver must not overfill the queue */
|
||||
EFSYS_ASSERT3U(added - completed + n, <=,
|
||||
EFX_RXQ_LIMIT(erp->er_mask + 1));
|
||||
|
||||
id = added & (erp->er_mask);
|
||||
for (i = 0; i < n; i++) {
|
||||
EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
|
||||
unsigned int, id, efsys_dma_addr_t, addrp[i],
|
||||
size_t, size);
|
||||
|
||||
EFX_POPULATE_QWORD_3(qword,
|
||||
ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
|
||||
ESF_DZ_RX_KER_BUF_ADDR_DW0,
|
||||
(uint32_t)(addrp[i] & 0xffffffff),
|
||||
ESF_DZ_RX_KER_BUF_ADDR_DW1,
|
||||
(uint32_t)(addrp[i] >> 32));
|
||||
|
||||
offset = id * sizeof (efx_qword_t);
|
||||
EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
|
||||
|
||||
id = (id + 1) & (erp->er_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ef10_rx_qpush(
|
||||
__in efx_rxq_t *erp,
|
||||
__in unsigned int added,
|
||||
__inout unsigned int *pushedp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
unsigned int pushed = *pushedp;
|
||||
uint32_t wptr;
|
||||
efx_dword_t dword;
|
||||
|
||||
/* Hardware has alignment restriction for WPTR */
|
||||
wptr = P2ALIGN(added, EF10_RX_WPTR_ALIGN);
|
||||
if (pushed == wptr)
|
||||
return;
|
||||
|
||||
*pushedp = wptr;
|
||||
|
||||
/* Push the populated descriptors out */
|
||||
wptr &= erp->er_mask;
|
||||
|
||||
EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
|
||||
|
||||
/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
|
||||
EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
|
||||
wptr, pushed & erp->er_mask);
|
||||
EFSYS_PIO_WRITE_BARRIER();
|
||||
EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
|
||||
erp->er_index, &dword, B_FALSE);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_rx_qflush(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_rx_qenable(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
/* FIXME */
|
||||
_NOTE(ARGUNUSED(erp))
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_rx_qcreate(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int index,
|
||||
__in unsigned int label,
|
||||
__in efx_rxq_type_t type,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in size_t n,
|
||||
__in uint32_t id,
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_rc_t rc;
|
||||
boolean_t disable_scatter;
|
||||
unsigned int ps_buf_size;
|
||||
|
||||
_NOTE(ARGUNUSED(id, erp))
|
||||
|
||||
EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
|
||||
EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
|
||||
EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
|
||||
|
||||
EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
|
||||
EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
|
||||
|
||||
if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
if (index >= encp->enc_rxq_limit) {
|
||||
rc = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case EFX_RXQ_TYPE_DEFAULT:
|
||||
case EFX_RXQ_TYPE_SCATTER:
|
||||
ps_buf_size = 0;
|
||||
break;
|
||||
default:
|
||||
rc = ENOTSUP;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
EFSYS_ASSERT(ps_buf_size == 0);
|
||||
|
||||
/* Scatter can only be disabled if the firmware supports doing so */
|
||||
if (type == EFX_RXQ_TYPE_SCATTER)
|
||||
disable_scatter = B_FALSE;
|
||||
else
|
||||
disable_scatter = encp->enc_rx_disable_scatter_supported;
|
||||
|
||||
if ((rc = efx_mcdi_init_rxq(enp, n, eep->ee_index, label, index,
|
||||
esmp, disable_scatter, ps_buf_size)) != 0)
|
||||
goto fail6;
|
||||
|
||||
erp->er_eep = eep;
|
||||
erp->er_label = label;
|
||||
|
||||
ef10_ev_rxlabel_init(eep, erp, label, ps_buf_size != 0);
|
||||
|
||||
return (0);
|
||||
|
||||
fail6:
|
||||
EFSYS_PROBE(fail6);
|
||||
fail3:
|
||||
EFSYS_PROBE(fail3);
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_rx_qdestroy(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
efx_evq_t *eep = erp->er_eep;
|
||||
unsigned int label = erp->er_label;
|
||||
|
||||
ef10_ev_rxlabel_fini(eep, label);
|
||||
|
||||
EFSYS_ASSERT(enp->en_rx_qcount != 0);
|
||||
--enp->en_rx_qcount;
|
||||
|
||||
EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_rx_fini(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
941
drivers/net/sfc/base/ef10_tlv_layout.h
Normal file
941
drivers/net/sfc/base/ef10_tlv_layout.h
Normal file
@ -0,0 +1,941 @@
|
||||
/**************************************************************************\
|
||||
*//*! \file
|
||||
** <L5_PRIVATE L5_SOURCE>
|
||||
** \author mjs
|
||||
** \brief TLV item layouts for EF10 static and dynamic config in NVRAM
|
||||
** \date 2012/11/20
|
||||
** \cop (c) Solarflare Communications Inc.
|
||||
** </L5_PRIVATE>
|
||||
*//*
|
||||
\**************************************************************************/
|
||||
|
||||
/* These structures define the layouts for the TLV items stored in static and
|
||||
* dynamic configuration partitions in NVRAM for EF10 (Huntington etc.).
|
||||
*
|
||||
* They contain the same sort of information that was kept in the
|
||||
* siena_mc_static_config_hdr_t and siena_mc_dynamic_config_hdr_t structures
|
||||
* (defined in <ci/mgmt/mc_flash_layout.h> and <ci/mgmt/mc_dynamic_cfg.h>) for
|
||||
* Siena.
|
||||
*
|
||||
* These are used directly by the MC and should also be usable directly on host
|
||||
* systems which are little-endian and do not do strange things with structure
|
||||
* padding. (Big-endian host systems will require some byte-swapping.)
|
||||
*
|
||||
* -----
|
||||
*
|
||||
* Please refer to SF-108797-SW for a general overview of the TLV partition
|
||||
* format.
|
||||
*
|
||||
* -----
|
||||
*
|
||||
* The current tag IDs have a general structure: with the exception of the
|
||||
* special values defined in the document, they are of the form 0xLTTTNNNN,
|
||||
* where:
|
||||
*
|
||||
* - L is a location, indicating where this tag is expected to be found:
|
||||
* 0: static configuration
|
||||
* 1: dynamic configuration
|
||||
* 2: firmware internal use
|
||||
* 3: license partition
|
||||
*
|
||||
* - TTT is a type, which is just a unique value. The same type value
|
||||
* might appear in both locations, indicating a relationship between
|
||||
* the items (e.g. static and dynamic VPD below).
|
||||
*
|
||||
* - NNNN is an index of some form. Some item types are per-port, some
|
||||
* are per-PF, some are per-partition-type.
|
||||
*
|
||||
* -----
|
||||
*
|
||||
* As with the previous Siena structures, each structure here is laid out
|
||||
* carefully: values are aligned to their natural boundary, with explicit
|
||||
* padding fields added where necessary. (No, technically this does not
|
||||
* absolutely guarantee portability. But, in practice, compilers are generally
|
||||
* sensible enough not to introduce completely pointless padding, and it works
|
||||
* well enough.)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CI_MGMT_TLV_LAYOUT_H
|
||||
#define CI_MGMT_TLV_LAYOUT_H
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* General structure (defined by SF-108797-SW)
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* The "end" tag.
|
||||
*
|
||||
* (Note that this is *not* followed by length or value fields: anything after
|
||||
* the tag itself is irrelevant.)
|
||||
*/
|
||||
|
||||
#define TLV_TAG_END (0xEEEEEEEE)
|
||||
|
||||
|
||||
/* Other special reserved tag values.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_SKIP (0x00000000)
|
||||
#define TLV_TAG_INVALID (0xFFFFFFFF)
|
||||
|
||||
|
||||
/* TLV partition header.
|
||||
*
|
||||
* In a TLV partition, this must be the first item in the sequence, at offset
|
||||
* 0.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PARTITION_HEADER (0xEF10DA7A)
|
||||
|
||||
struct tlv_partition_header {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t type_id;
|
||||
/* 0 indicates the default segment (always located at offset 0), while other values
|
||||
* are for RFID-selectable presets that should immediately follow the default segment.
|
||||
* The default segment may also have preset > 0, which means that it is a preset
|
||||
* selected through an RFID command and copied by FW to the location at offset 0. */
|
||||
uint16_t preset;
|
||||
uint32_t generation;
|
||||
uint32_t total_length;
|
||||
};
|
||||
|
||||
|
||||
/* TLV partition trailer.
|
||||
*
|
||||
* In a TLV partition, this must be the last item in the sequence, immediately
|
||||
* preceding the TLV_TAG_END word.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PARTITION_TRAILER (0xEF101A57)
|
||||
|
||||
struct tlv_partition_trailer {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t generation;
|
||||
uint32_t checksum;
|
||||
};
|
||||
|
||||
|
||||
/* Appendable TLV partition header.
|
||||
*
|
||||
* In an appendable TLV partition, this must be the first item in the sequence,
|
||||
* at offset 0. (Note that, unlike the configuration partitions, there is no
|
||||
* trailer before the TLV_TAG_END word.)
|
||||
*/
|
||||
|
||||
#define TLV_TAG_APPENDABLE_PARTITION_HEADER (0xEF10ADA7)
|
||||
|
||||
struct tlv_appendable_partition_header {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t type_id;
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Configuration items
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* NIC global capabilities.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_GLOBAL_CAPABILITIES (0x00010000)
|
||||
|
||||
struct tlv_global_capabilities {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
|
||||
/* Siena-style per-port MAC address allocation.
|
||||
*
|
||||
* There are <count> addresses, starting at <base_address> and incrementing
|
||||
* by adding <stride> to the low-order byte(s).
|
||||
*
|
||||
* (See also TLV_TAG_GLOBAL_MAC for an alternative, specifying a global pool
|
||||
* of contiguous MAC addresses for the firmware to allocate as it sees fit.)
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PORT_MAC(port) (0x00020000 + (port))
|
||||
|
||||
struct tlv_port_mac {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t base_address[6];
|
||||
uint16_t reserved;
|
||||
uint16_t count;
|
||||
uint16_t stride;
|
||||
};
|
||||
|
||||
|
||||
/* Static VPD.
|
||||
*
|
||||
* This is the portion of VPD which is set at manufacturing time and not
|
||||
* expected to change. It is formatted as a standard PCI VPD block. There are
|
||||
* global and per-pf TLVs for this, the global TLV is new for Medford and is
|
||||
* used in preference to the per-pf TLV.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PF_STATIC_VPD(pf) (0x00030000 + (pf))
|
||||
|
||||
struct tlv_pf_static_vpd {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
};
|
||||
|
||||
#define TLV_TAG_GLOBAL_STATIC_VPD (0x001f0000)
|
||||
|
||||
struct tlv_global_static_vpd {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
};
|
||||
|
||||
|
||||
/* Dynamic VPD.
|
||||
*
|
||||
* This is the portion of VPD which may be changed (e.g. by firmware updates).
|
||||
* It is formatted as a standard PCI VPD block. There are global and per-pf TLVs
|
||||
* for this, the global TLV is new for Medford and is used in preference to the
|
||||
* per-pf TLV.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PF_DYNAMIC_VPD(pf) (0x10030000 + (pf))
|
||||
|
||||
struct tlv_pf_dynamic_vpd {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
};
|
||||
|
||||
#define TLV_TAG_GLOBAL_DYNAMIC_VPD (0x10200000)
|
||||
|
||||
struct tlv_global_dynamic_vpd {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
};
|
||||
|
||||
|
||||
/* "DBI" PCI config space changes.
|
||||
*
|
||||
* This is a set of edits made to the default PCI config space values before
|
||||
* the device is allowed to enumerate. There are global and per-pf TLVs for
|
||||
* this, the global TLV is new for Medford and is used in preference to the
|
||||
* per-pf TLV.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PF_DBI(pf) (0x00040000 + (pf))
|
||||
|
||||
struct tlv_pf_dbi {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
struct {
|
||||
uint16_t addr;
|
||||
uint16_t byte_enables;
|
||||
uint32_t value;
|
||||
} items[];
|
||||
};
|
||||
|
||||
|
||||
#define TLV_TAG_GLOBAL_DBI (0x00210000)
|
||||
|
||||
struct tlv_global_dbi {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
struct {
|
||||
uint16_t addr;
|
||||
uint16_t byte_enables;
|
||||
uint32_t value;
|
||||
} items[];
|
||||
};
|
||||
|
||||
|
||||
/* Partition subtype codes.
|
||||
*
|
||||
* A subtype may optionally be stored for each type of partition present in
|
||||
* the NVRAM. For example, this may be used to allow a generic firmware update
|
||||
* utility to select a specific variant of firmware for a specific variant of
|
||||
* board.
|
||||
*
|
||||
* The description[] field is an optional string which is returned in the
|
||||
* MC_CMD_NVRAM_METADATA response if present.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PARTITION_SUBTYPE(type) (0x00050000 + (type))
|
||||
|
||||
struct tlv_partition_subtype {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t subtype;
|
||||
uint8_t description[];
|
||||
};
|
||||
|
||||
|
||||
/* Partition version codes.
|
||||
*
|
||||
* A version may optionally be stored for each type of partition present in
|
||||
* the NVRAM. This provides a standard way of tracking the currently stored
|
||||
* version of each of the various component images.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_PARTITION_VERSION(type) (0x10060000 + (type))
|
||||
|
||||
struct tlv_partition_version {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t version_w;
|
||||
uint16_t version_x;
|
||||
uint16_t version_y;
|
||||
uint16_t version_z;
|
||||
};
|
||||
|
||||
/* Global PCIe configuration */
|
||||
|
||||
#define TLV_TAG_GLOBAL_PCIE_CONFIG (0x10070000)
|
||||
|
||||
struct tlv_pcie_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
int16_t max_pf_number; /**< Largest PF RID (lower PFs may be hidden) */
|
||||
uint16_t pf_aper; /**< BIU aperture for PF BAR2 */
|
||||
uint16_t vf_aper; /**< BIU aperture for VF BAR0 */
|
||||
uint16_t int_aper; /**< BIU aperture for PF BAR4 and VF BAR2 */
|
||||
#define TLV_MAX_PF_DEFAULT (-1) /* Use FW default for largest PF RID */
|
||||
#define TLV_APER_DEFAULT (0xFFFF) /* Use FW default for a given aperture */
|
||||
};
|
||||
|
||||
/* Per-PF configuration. Note that not all these fields are necessarily useful
|
||||
* as the apertures are constrained by the BIU settings (the one case we do
|
||||
* use is to make BAR2 bigger than the BIU thinks to reserve space), but we can
|
||||
* tidy things up later */
|
||||
|
||||
#define TLV_TAG_PF_PCIE_CONFIG(pf) (0x10080000 + (pf))
|
||||
|
||||
struct tlv_per_pf_pcie_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t vfs_total;
|
||||
uint8_t port_allocation;
|
||||
uint16_t vectors_per_pf;
|
||||
uint16_t vectors_per_vf;
|
||||
uint8_t pf_bar0_aperture;
|
||||
uint8_t pf_bar2_aperture;
|
||||
uint8_t vf_bar0_aperture;
|
||||
uint8_t vf_base;
|
||||
uint16_t supp_pagesz;
|
||||
uint16_t msix_vec_base;
|
||||
};
|
||||
|
||||
|
||||
/* Development ONLY. This is a single TLV tag for all the gubbins
|
||||
* that can be set through the MC command-line other than the PCIe
|
||||
* settings. This is a temporary measure. */
|
||||
#define TLV_TAG_TMP_GUBBINS (0x10090000) /* legacy symbol - do not use */
|
||||
#define TLV_TAG_TMP_GUBBINS_HUNT TLV_TAG_TMP_GUBBINS
|
||||
|
||||
struct tlv_tmp_gubbins {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
/* Consumed by dpcpu.c */
|
||||
uint64_t tx0_tags; /* Bitmap */
|
||||
uint64_t tx1_tags; /* Bitmap */
|
||||
uint64_t dl_tags; /* Bitmap */
|
||||
uint32_t flags;
|
||||
#define TLV_DPCPU_TX_STRIPE (1) /* No longer used, has no effect */
|
||||
#define TLV_DPCPU_BIU_TAGS (2) /* Use BIU tag manager */
|
||||
#define TLV_DPCPU_TX0_TAGS (4) /* tx0_tags is valid */
|
||||
#define TLV_DPCPU_TX1_TAGS (8) /* tx1_tags is valid */
|
||||
#define TLV_DPCPU_DL_TAGS (16) /* dl_tags is valid */
|
||||
/* Consumed by features.c */
|
||||
uint32_t dut_features; /* All 1s -> leave alone */
|
||||
int8_t with_rmon; /* 0 -> off, 1 -> on, -1 -> leave alone */
|
||||
/* Consumed by clocks_hunt.c */
|
||||
int8_t clk_mode; /* 0 -> off, 1 -> on, -1 -> leave alone */
|
||||
/* No longer used, superseded by TLV_TAG_DESCRIPTOR_CACHE_CONFIG. */
|
||||
int8_t rx_dc_size; /* -1 -> leave alone */
|
||||
int8_t tx_dc_size;
|
||||
int16_t num_q_allocs;
|
||||
};
|
||||
|
||||
/* Global port configuration
|
||||
*
|
||||
* This is now deprecated in favour of a platform-provided default
|
||||
* and dynamic config override via tlv_global_port_options.
|
||||
*/
|
||||
#define TLV_TAG_GLOBAL_PORT_CONFIG (0x000a0000)
|
||||
|
||||
struct tlv_global_port_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t ports_per_core;
|
||||
uint32_t max_port_speed;
|
||||
};
|
||||
|
||||
|
||||
/* Firmware options.
|
||||
*
|
||||
* This is intended for user-configurable selection of optional firmware
|
||||
* features and variants.
|
||||
*
|
||||
* Initially, this consists only of the satellite CPU firmware variant
|
||||
* selection, but this tag could be extended in the future (using the
|
||||
* tag length to determine whether additional fields are present).
|
||||
*/
|
||||
|
||||
#define TLV_TAG_FIRMWARE_OPTIONS (0x100b0000)
|
||||
|
||||
struct tlv_firmware_options {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t firmware_variant;
|
||||
#define TLV_FIRMWARE_VARIANT_DRIVER_SELECTED (0xffffffff)
|
||||
|
||||
/* These are the values for overriding the driver's choice; the definitions
|
||||
* are taken from MCDI so that they don't get out of step. Include
|
||||
* <ci/mgmt/mc_driver_pcol.h> or the equivalent from your driver's tree if
|
||||
* you need to use these constants.
|
||||
*/
|
||||
#define TLV_FIRMWARE_VARIANT_FULL_FEATURED MC_CMD_FW_FULL_FEATURED
|
||||
#define TLV_FIRMWARE_VARIANT_LOW_LATENCY MC_CMD_FW_LOW_LATENCY
|
||||
#define TLV_FIRMWARE_VARIANT_PACKED_STREAM MC_CMD_FW_PACKED_STREAM
|
||||
#define TLV_FIRMWARE_VARIANT_HIGH_TX_RATE MC_CMD_FW_HIGH_TX_RATE
|
||||
#define TLV_FIRMWARE_VARIANT_PACKED_STREAM_HASH_MODE_1 \
|
||||
MC_CMD_FW_PACKED_STREAM_HASH_MODE_1
|
||||
#define TLV_FIRMWARE_VARIANT_RULES_ENGINE MC_CMD_FW_RULES_ENGINE
|
||||
};
|
||||
|
||||
/* Voltage settings
|
||||
*
|
||||
* Intended for boards with A0 silicon where the core voltage may
|
||||
* need tweaking. Most likely set once when the pass voltage is
|
||||
* determined. */
|
||||
|
||||
#define TLV_TAG_0V9_SETTINGS (0x000c0000)
|
||||
|
||||
struct tlv_0v9_settings {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t flags; /* Boards with high 0v9 settings may need active cooling */
|
||||
#define TLV_TAG_0V9_REQUIRES_FAN (1)
|
||||
uint16_t target_voltage; /* In millivolts */
|
||||
/* Since the limits are meant to be centred to the target (and must at least
|
||||
* contain it) they need setting as well. */
|
||||
uint16_t warn_low; /* In millivolts */
|
||||
uint16_t warn_high; /* In millivolts */
|
||||
uint16_t panic_low; /* In millivolts */
|
||||
uint16_t panic_high; /* In millivolts */
|
||||
};
|
||||
|
||||
|
||||
/* Clock configuration */
|
||||
|
||||
#define TLV_TAG_CLOCK_CONFIG (0x000d0000) /* legacy symbol - do not use */
|
||||
#define TLV_TAG_CLOCK_CONFIG_HUNT TLV_TAG_CLOCK_CONFIG
|
||||
|
||||
struct tlv_clock_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t clk_sys; /* MHz */
|
||||
uint16_t clk_dpcpu; /* MHz */
|
||||
uint16_t clk_icore; /* MHz */
|
||||
uint16_t clk_pcs; /* MHz */
|
||||
};
|
||||
|
||||
#define TLV_TAG_CLOCK_CONFIG_MEDFORD (0x00100000)
|
||||
|
||||
struct tlv_clock_config_medford {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t clk_sys; /* MHz */
|
||||
uint16_t clk_mc; /* MHz */
|
||||
uint16_t clk_rmon; /* MHz */
|
||||
uint16_t clk_vswitch; /* MHz */
|
||||
uint16_t clk_dpcpu; /* MHz */
|
||||
uint16_t clk_pcs; /* MHz */
|
||||
};
|
||||
|
||||
|
||||
/* EF10-style global pool of MAC addresses.
|
||||
*
|
||||
* There are <count> addresses, starting at <base_address>, which are
|
||||
* contiguous. Firmware is responsible for allocating addresses from this
|
||||
* pool to ports / PFs as appropriate.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_GLOBAL_MAC (0x000e0000)
|
||||
|
||||
struct tlv_global_mac {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t base_address[6];
|
||||
uint16_t reserved1;
|
||||
uint16_t count;
|
||||
uint16_t reserved2;
|
||||
};
|
||||
|
||||
#define TLV_TAG_ATB_0V9_TARGET (0x000f0000) /* legacy symbol - do not use */
|
||||
#define TLV_TAG_ATB_0V9_TARGET_HUNT TLV_TAG_ATB_0V9_TARGET
|
||||
|
||||
/* The target value for the 0v9 power rail measured on-chip at the
|
||||
* analogue test bus */
|
||||
struct tlv_0v9_atb_target {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t millivolts;
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
/* Factory settings for amplitude calibration of the PCIE TX serdes */
|
||||
#define TLV_TAG_TX_PCIE_AMP_CONFIG (0x00220000)
|
||||
struct tlv_pcie_tx_amp_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t quad_tx_imp2k[4];
|
||||
uint8_t quad_tx_imp50[4];
|
||||
uint8_t lane_amp[16];
|
||||
};
|
||||
|
||||
|
||||
/* Global PCIe configuration, second revision. This represents the visible PFs
|
||||
* by a bitmap rather than having the number of the highest visible one. As such
|
||||
* it can (for a 16-PF chip) represent a superset of what TLV_TAG_GLOBAL_PCIE_CONFIG
|
||||
* can and it should be used in place of that tag in future (but compatibility with
|
||||
* the old tag will be left in the firmware indefinitely). */
|
||||
|
||||
#define TLV_TAG_GLOBAL_PCIE_CONFIG_R2 (0x10100000)
|
||||
|
||||
struct tlv_pcie_config_r2 {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t visible_pfs; /**< Bitmap of visible PFs */
|
||||
uint16_t pf_aper; /**< BIU aperture for PF BAR2 */
|
||||
uint16_t vf_aper; /**< BIU aperture for VF BAR0 */
|
||||
uint16_t int_aper; /**< BIU aperture for PF BAR4 and VF BAR2 */
|
||||
};
|
||||
|
||||
/* Dynamic port mode.
|
||||
*
|
||||
* Allows selecting alternate port configuration for platforms that support it
|
||||
* (e.g. 1x40G vs 2x10G on Milano, 1x40G vs 4x10G on Medford). This affects the
|
||||
* number of externally visible ports (and, hence, PF to port mapping), so must
|
||||
* be done at boot time.
|
||||
*
|
||||
* This tag supercedes tlv_global_port_config.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_GLOBAL_PORT_MODE (0x10110000)
|
||||
|
||||
struct tlv_global_port_mode {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t port_mode;
|
||||
#define TLV_PORT_MODE_DEFAULT (0xffffffff) /* Default for given platform */
|
||||
#define TLV_PORT_MODE_10G (0) /* 10G, single SFP/10G-KR */
|
||||
#define TLV_PORT_MODE_40G (1) /* 40G, single QSFP/40G-KR */
|
||||
#define TLV_PORT_MODE_10G_10G (2) /* 2x10G, dual SFP/10G-KR or single QSFP */
|
||||
#define TLV_PORT_MODE_40G_40G (3) /* 40G + 40G, dual QSFP/40G-KR (Greenport, Medford) */
|
||||
#define TLV_PORT_MODE_10G_10G_10G_10G (4) /* 2x10G + 2x10G, quad SFP/10G-KR or dual QSFP (Greenport) */
|
||||
#define TLV_PORT_MODE_10G_10G_10G_10G_Q1 (4) /* 4x10G, single QSFP, cage 0 (Medford) */
|
||||
#define TLV_PORT_MODE_10G_10G_10G_10G_Q (5) /* 4x10G, single QSFP, cage 0 (Medford) OBSOLETE DO NOT USE */
|
||||
#define TLV_PORT_MODE_40G_10G_10G (6) /* 1x40G + 2x10G, dual QSFP (Greenport, Medford) */
|
||||
#define TLV_PORT_MODE_10G_10G_40G (7) /* 2x10G + 1x40G, dual QSFP (Greenport, Medford) */
|
||||
#define TLV_PORT_MODE_10G_10G_10G_10G_Q2 (8) /* 4x10G, single QSFP, cage 1 (Medford) */
|
||||
#define TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2 (9) /* 2x10G + 2x10G, dual QSFP (Medford) */
|
||||
#define TLV_PORT_MODE_MAX TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2
|
||||
};
|
||||
|
||||
/* Type of the v-switch created implicitly by the firmware */
|
||||
|
||||
#define TLV_TAG_VSWITCH_TYPE(port) (0x10120000 + (port))
|
||||
|
||||
struct tlv_vswitch_type {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t vswitch_type;
|
||||
#define TLV_VSWITCH_TYPE_DEFAULT (0xffffffff) /* Firmware default; equivalent to no TLV present for a given port */
|
||||
#define TLV_VSWITCH_TYPE_NONE (0)
|
||||
#define TLV_VSWITCH_TYPE_VLAN (1)
|
||||
#define TLV_VSWITCH_TYPE_VEB (2)
|
||||
#define TLV_VSWITCH_TYPE_VEPA (3)
|
||||
#define TLV_VSWITCH_TYPE_MUX (4)
|
||||
#define TLV_VSWITCH_TYPE_TEST (5)
|
||||
};
|
||||
|
||||
/* A VLAN tag for the v-port created implicitly by the firmware */
|
||||
|
||||
#define TLV_TAG_VPORT_VLAN_TAG(pf) (0x10130000 + (pf))
|
||||
|
||||
struct tlv_vport_vlan_tag {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t vlan_tag;
|
||||
#define TLV_VPORT_NO_VLAN_TAG (0xFFFFFFFF) /* Default in the absence of TLV for a given PF */
|
||||
};
|
||||
|
||||
/* Offset to be applied to the 0v9 setting, wherever it came from */
|
||||
|
||||
#define TLV_TAG_ATB_0V9_OFFSET (0x10140000)
|
||||
|
||||
struct tlv_0v9_atb_offset {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
int16_t offset_millivolts;
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
/* A privilege mask given on reset to all non-admin PCIe functions (that is other than first-PF-per-port).
|
||||
* The meaning of particular bits is defined in mcdi_ef10.yml under MC_CMD_PRIVILEGE_MASK, see also bug 44583.
|
||||
* TLV_TAG_PRIVILEGE_MASK_ADD specifies bits that should be added (ORed) to firmware default while
|
||||
* TLV_TAG_PRIVILEGE_MASK_REM specifies bits that should be removed (ANDed) from firmware default:
|
||||
* Initial_privilege_mask = (firmware_default_mask | privilege_mask_add) & ~privilege_mask_rem */
|
||||
|
||||
#define TLV_TAG_PRIVILEGE_MASK (0x10150000) /* legacy symbol - do not use */
|
||||
|
||||
struct tlv_privilege_mask { /* legacy structure - do not use */
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t privilege_mask;
|
||||
};
|
||||
|
||||
#define TLV_TAG_PRIVILEGE_MASK_ADD (0x10150000)
|
||||
|
||||
struct tlv_privilege_mask_add {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t privilege_mask_add;
|
||||
};
|
||||
|
||||
#define TLV_TAG_PRIVILEGE_MASK_REM (0x10160000)
|
||||
|
||||
struct tlv_privilege_mask_rem {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t privilege_mask_rem;
|
||||
};
|
||||
|
||||
/* Additional privileges given to all PFs.
|
||||
* This tag takes precedence over TLV_TAG_PRIVILEGE_MASK_REM. */
|
||||
|
||||
#define TLV_TAG_PRIVILEGE_MASK_ADD_ALL_PFS (0x10190000)
|
||||
|
||||
struct tlv_privilege_mask_add_all_pfs {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t privilege_mask_add;
|
||||
};
|
||||
|
||||
/* Additional privileges given to a selected PF.
|
||||
* This tag takes precedence over TLV_TAG_PRIVILEGE_MASK_REM. */
|
||||
|
||||
#define TLV_TAG_PRIVILEGE_MASK_ADD_SINGLE_PF(pf) (0x101A0000 + (pf))
|
||||
|
||||
struct tlv_privilege_mask_add_single_pf {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t privilege_mask_add;
|
||||
};
|
||||
|
||||
/* Turning on/off the PFIOV mode.
|
||||
* This tag only takes effect if TLV_TAG_VSWITCH_TYPE is missing or set to DEFAULT. */
|
||||
|
||||
#define TLV_TAG_PFIOV(port) (0x10170000 + (port))
|
||||
|
||||
struct tlv_pfiov {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t pfiov;
|
||||
#define TLV_PFIOV_OFF (0) /* Default */
|
||||
#define TLV_PFIOV_ON (1)
|
||||
};
|
||||
|
||||
/* Multicast filter chaining mode selection.
|
||||
*
|
||||
* When enabled, multicast packets are delivered to all recipients of all
|
||||
* matching multicast filters, with the exception that IP multicast filters
|
||||
* will steal traffic from MAC multicast filters on a per-function basis.
|
||||
* (New behaviour.)
|
||||
*
|
||||
* When disabled, multicast packets will always be delivered only to the
|
||||
* recipients of the highest priority matching multicast filter.
|
||||
* (Legacy behaviour.)
|
||||
*
|
||||
* The DEFAULT mode (which is the same as the tag not being present at all)
|
||||
* is equivalent to ENABLED in production builds, and DISABLED in eftest
|
||||
* builds.
|
||||
*
|
||||
* This option is intended to provide run-time control over this feature
|
||||
* while it is being stabilised and may be withdrawn at some point in the
|
||||
* future; the new behaviour is intended to become the standard behaviour.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_MCAST_FILTER_CHAINING (0x10180000)
|
||||
|
||||
struct tlv_mcast_filter_chaining {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t mode;
|
||||
#define TLV_MCAST_FILTER_CHAINING_DEFAULT (0xffffffff)
|
||||
#define TLV_MCAST_FILTER_CHAINING_DISABLED (0)
|
||||
#define TLV_MCAST_FILTER_CHAINING_ENABLED (1)
|
||||
};
|
||||
|
||||
/* Pacer rate limit per PF */
|
||||
#define TLV_TAG_RATE_LIMIT(pf) (0x101b0000 + (pf))
|
||||
|
||||
struct tlv_rate_limit {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t rate_mbps;
|
||||
};
|
||||
|
||||
/* OCSD Enable/Disable
|
||||
*
|
||||
* This setting allows OCSD to be disabled. This is a requirement for HP
|
||||
* servers to support PCI passthrough for virtualization.
|
||||
*
|
||||
* The DEFAULT mode (which is the same as the tag not being present) is
|
||||
* equivalent to ENABLED.
|
||||
*
|
||||
* This option is not used by the MCFW, and is entirely handled by the various
|
||||
* drivers that support OCSD, by reading the setting before they attempt
|
||||
* to enable OCSD.
|
||||
*
|
||||
* bit0: OCSD Disabled/Enabled
|
||||
*/
|
||||
|
||||
#define TLV_TAG_OCSD (0x101C0000)
|
||||
|
||||
struct tlv_ocsd {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t mode;
|
||||
#define TLV_OCSD_DISABLED 0
|
||||
#define TLV_OCSD_ENABLED 1 /* Default */
|
||||
};
|
||||
|
||||
/* Descriptor cache config.
|
||||
*
|
||||
* Sets the sizes of the TX and RX descriptor caches as a power of 2. It also
|
||||
* sets the total number of VIs. When the number of VIs is reduced VIs are taken
|
||||
* away from the highest numbered port first, so a vi_count of 1024 means 1024
|
||||
* VIs on the first port and 0 on the second (on a Torino).
|
||||
*/
|
||||
|
||||
#define TLV_TAG_DESCRIPTOR_CACHE_CONFIG (0x101d0000)
|
||||
|
||||
struct tlv_descriptor_cache_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t rx_desc_cache_size;
|
||||
uint8_t tx_desc_cache_size;
|
||||
uint16_t vi_count;
|
||||
};
|
||||
#define TLV_DESC_CACHE_DEFAULT (0xff)
|
||||
#define TLV_VI_COUNT_DEFAULT (0xffff)
|
||||
|
||||
/* RX event merging config (read batching).
|
||||
*
|
||||
* Sets the global maximum number of events for the merging bins, and the
|
||||
* global timeout configuration for the bins.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_RX_EVENT_MERGING_CONFIG (0x101e0000)
|
||||
|
||||
struct tlv_rx_event_merging_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t max_events;
|
||||
#define TLV_RX_EVENT_MERGING_CONFIG_MAX_EVENTS_MAX ((1 << 4) - 1)
|
||||
uint32_t timeout_ns;
|
||||
};
|
||||
#define TLV_RX_EVENT_MERGING_MAX_EVENTS_DEFAULT (0xffffffff)
|
||||
#define TLV_RX_EVENT_MERGING_TIMEOUT_NS_DEFAULT (0xffffffff)
|
||||
|
||||
#define TLV_TAG_PCIE_LINK_SETTINGS (0x101f0000)
|
||||
struct tlv_pcie_link_settings {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint16_t gen; /* Target PCIe generation: 1, 2, 3 */
|
||||
uint16_t width; /* Number of lanes */
|
||||
};
|
||||
|
||||
/* TX event merging config.
|
||||
*
|
||||
* Sets the global maximum number of events for the merging bins, and the
|
||||
* global timeout configuration for the bins, and the global timeout for
|
||||
* empty queues.
|
||||
*/
|
||||
#define TLV_TAG_TX_EVENT_MERGING_CONFIG (0x10210000)
|
||||
struct tlv_tx_event_merging_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t max_events;
|
||||
#define TLV_TX_EVENT_MERGING_CONFIG_MAX_EVENTS_MAX ((1 << 4) - 1)
|
||||
uint32_t timeout_ns;
|
||||
uint32_t qempty_timeout_ns; /* Medford only */
|
||||
};
|
||||
#define TLV_TX_EVENT_MERGING_MAX_EVENTS_DEFAULT (0xffffffff)
|
||||
#define TLV_TX_EVENT_MERGING_TIMEOUT_NS_DEFAULT (0xffffffff)
|
||||
#define TLV_TX_EVENT_MERGING_QEMPTY_TIMEOUT_NS_DEFAULT (0xffffffff)
|
||||
|
||||
#define TLV_TAG_LICENSE (0x30800000)
|
||||
|
||||
typedef struct tlv_license {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t data[];
|
||||
} tlv_license_t;
|
||||
|
||||
/* TSA NIC IP address configuration
|
||||
*
|
||||
* Sets the TSA NIC IP address statically via configuration tool or dynamically
|
||||
* via DHCP via snooping based on the mode selection (0=Static, 1=DHCP, 2=Snoop)
|
||||
*
|
||||
* NOTE: This TAG is temporarily placed in the dynamic config partition and will
|
||||
* be moved to a private partition during TSA development. It is not used in any
|
||||
* released code yet.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TMP_TSAN_CONFIG (0x10220000)
|
||||
|
||||
#define TLV_TSAN_IP_MODE_STATIC (0)
|
||||
#define TLV_TSAN_IP_MODE_DHCP (1)
|
||||
#define TLV_TSAN_IP_MODE_SNOOP (2)
|
||||
typedef struct tlv_tsan_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t mode;
|
||||
uint32_t ip;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t port;
|
||||
uint32_t bind_retry; /* DEPRECATED */
|
||||
uint32_t bind_bkout; /* DEPRECATED */
|
||||
} tlv_tsan_config_t;
|
||||
|
||||
/* TSA Controller IP address configuration
|
||||
*
|
||||
* Sets the TSA Controller IP address statically via configuration tool
|
||||
*
|
||||
* NOTE: This TAG is temporarily placed in the dynamic config partition and will
|
||||
* be moved to a private partition during TSA development. It is not used in any
|
||||
* released code yet.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TMP_TSAC_CONFIG (0x10230000)
|
||||
|
||||
#define TLV_MAX_TSACS (4)
|
||||
typedef struct tlv_tsac_config {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint32_t num_tsacs;
|
||||
uint32_t ip[TLV_MAX_TSACS];
|
||||
uint32_t port[TLV_MAX_TSACS];
|
||||
} tlv_tsac_config_t;
|
||||
|
||||
/* Binding ticket
|
||||
*
|
||||
* Sets the TSA NIC binding ticket used for binding process between the TSA NIC
|
||||
* and the TSA Controller
|
||||
*
|
||||
* NOTE: This TAG is temporarily placed in the dynamic config partition and will
|
||||
* be moved to a private partition during TSA development. It is not used in any
|
||||
* released code yet.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TMP_BINDING_TICKET (0x10240000)
|
||||
|
||||
typedef struct tlv_binding_ticket {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
} tlv_binding_ticket_t;
|
||||
|
||||
/* Solarflare private key (DEPRECATED)
|
||||
*
|
||||
* Sets the Solareflare private key used for signing during the binding process
|
||||
*
|
||||
* NOTE: This TAG is temporarily placed in the dynamic config partition and will
|
||||
* be moved to a private partition during TSA development. It is not used in any
|
||||
* released code yet.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TMP_PIK_SF (0x10250000) /* DEPRECATED */
|
||||
|
||||
typedef struct tlv_pik_sf {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
} tlv_pik_sf_t;
|
||||
|
||||
/* CA root certificate
|
||||
*
|
||||
* Sets the CA root certificate used for TSA Controller verfication during
|
||||
* TLS connection setup between the TSA NIC and the TSA Controller
|
||||
*
|
||||
* NOTE: This TAG is temporarily placed in the dynamic config partition and will
|
||||
* be moved to a private partition during TSA development. It is not used in any
|
||||
* released code yet.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TMP_CA_ROOT_CERT (0x10260000)
|
||||
|
||||
typedef struct tlv_ca_root_cert {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t bytes[];
|
||||
} tlv_ca_root_cert_t;
|
||||
|
||||
/* Tx vFIFO Low latency configuration
|
||||
*
|
||||
* To keep the desired booting behaviour for the switch, it just requires to
|
||||
* know if the low latency mode is enabled.
|
||||
*/
|
||||
|
||||
#define TLV_TAG_TX_VFIFO_ULL_MODE (0x10270000)
|
||||
struct tlv_tx_vfifo_ull_mode {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t mode;
|
||||
#define TLV_TX_VFIFO_ULL_MODE_DEFAULT 0
|
||||
};
|
||||
|
||||
/* BIU mode
|
||||
*
|
||||
* Medford2 tag for selecting VI window decode (see values below)
|
||||
*/
|
||||
#define TLV_TAG_BIU_VI_WINDOW_MODE (0x10280000)
|
||||
struct tlv_biu_vi_window_mode {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t mode;
|
||||
#define TLV_BIU_VI_WINDOW_MODE_8K 0 /* 8k per VI, CTPIO not mapped, medford/hunt compatible */
|
||||
#define TLV_BIU_VI_WINDOW_MODE_16K 1 /* 16k per VI, CTPIO mapped */
|
||||
#define TLV_BIU_VI_WINDOW_MODE_64K 2 /* 64k per VI, CTPIO mapped, POWER-friendly */
|
||||
};
|
||||
|
||||
/* FastPD mode
|
||||
*
|
||||
* Medford2 tag for configuring the FastPD mode (see values below)
|
||||
*/
|
||||
#define TLV_TAG_FASTPD_MODE(port) (0x10290000 + (port))
|
||||
struct tlv_fastpd_mode {
|
||||
uint32_t tag;
|
||||
uint32_t length;
|
||||
uint8_t mode;
|
||||
#define TLV_FASTPD_MODE_SOFT_ALL 0 /* All packets to the SoftPD */
|
||||
#define TLV_FASTPD_MODE_FAST_ALL 1 /* All packets to the FastPD */
|
||||
#define TLV_FASTPD_MODE_FAST_SUPPORTED 2 /* Supported packet types to the FastPD; everything else to the SoftPD */
|
||||
};
|
||||
|
||||
#endif /* CI_MGMT_TLV_LAYOUT_H */
|
683
drivers/net/sfc/base/ef10_tx.c
Normal file
683
drivers/net/sfc/base/ef10_tx.c
Normal file
@ -0,0 +1,683 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
#define EFX_TX_QSTAT_INCR(_etp, _stat)
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_init_txq(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t size,
|
||||
__in uint32_t target_evq,
|
||||
__in uint32_t label,
|
||||
__in uint32_t instance,
|
||||
__in uint16_t flags,
|
||||
__in efsys_mem_t *esmp)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_MAX_BUFS),
|
||||
MC_CMD_INIT_TXQ_OUT_LEN)];
|
||||
efx_qword_t *dma_addr;
|
||||
uint64_t addr;
|
||||
int npages;
|
||||
int i;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(EFX_TXQ_MAX_BUFS >=
|
||||
EFX_TXQ_NBUFS(enp->en_nic_cfg.enc_txq_max_ndescs));
|
||||
|
||||
npages = EFX_TXQ_NBUFS(size);
|
||||
if (npages > MC_CMD_INIT_TXQ_IN_DMA_ADDR_MAXNUM) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_INIT_TXQ;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages);
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_INIT_TXQ_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_SIZE, size);
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_TARGET_EVQ, target_evq);
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label);
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance);
|
||||
|
||||
MCDI_IN_POPULATE_DWORD_7(req, INIT_TXQ_IN_FLAGS,
|
||||
INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
|
||||
INIT_TXQ_IN_FLAG_IP_CSUM_DIS,
|
||||
(flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1,
|
||||
INIT_TXQ_IN_FLAG_TCP_CSUM_DIS,
|
||||
(flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1,
|
||||
INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0,
|
||||
INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
|
||||
INIT_TXQ_IN_CRC_MODE, 0,
|
||||
INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
|
||||
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_OWNER_ID, 0);
|
||||
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
|
||||
|
||||
dma_addr = MCDI_IN2(req, efx_qword_t, INIT_TXQ_IN_DMA_ADDR);
|
||||
addr = EFSYS_MEM_ADDR(esmp);
|
||||
|
||||
for (i = 0; i < npages; i++) {
|
||||
EFX_POPULATE_QWORD_2(*dma_addr,
|
||||
EFX_DWORD_1, (uint32_t)(addr >> 32),
|
||||
EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
|
||||
|
||||
dma_addr++;
|
||||
addr += EFX_BUF_SIZE;
|
||||
}
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
efx_mcdi_fini_txq(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t instance)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_FINI_TXQ_IN_LEN,
|
||||
MC_CMD_FINI_TXQ_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_FINI_TXQ;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_FINI_TXQ_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_FINI_TXQ_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, FINI_TXQ_IN_INSTANCE, instance);
|
||||
|
||||
efx_mcdi_execute_quiet(enp, &req);
|
||||
|
||||
if ((req.emr_rc != 0) && (req.emr_rc != MC_CMD_ERR_EALREADY)) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_init(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_fini(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qcreate(
|
||||
__in efx_nic_t *enp,
|
||||
__in unsigned int index,
|
||||
__in unsigned int label,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in size_t n,
|
||||
__in uint32_t id,
|
||||
__in uint16_t flags,
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_txq_t *etp,
|
||||
__out unsigned int *addedp)
|
||||
{
|
||||
efx_qword_t desc;
|
||||
efx_rc_t rc;
|
||||
|
||||
_NOTE(ARGUNUSED(id))
|
||||
|
||||
if ((rc = efx_mcdi_init_txq(enp, n, eep->ee_index, label, index, flags,
|
||||
esmp)) != 0)
|
||||
goto fail1;
|
||||
|
||||
/*
|
||||
* A previous user of this TX queue may have written a descriptor to the
|
||||
* TX push collector, but not pushed the doorbell (e.g. after a crash).
|
||||
* The next doorbell write would then push the stale descriptor.
|
||||
*
|
||||
* Ensure the (per network port) TX push collector is cleared by writing
|
||||
* a no-op TX option descriptor. See bug29981 for details.
|
||||
*/
|
||||
*addedp = 1;
|
||||
EFX_POPULATE_QWORD_4(desc,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
|
||||
ESF_DZ_TX_OPTION_UDP_TCP_CSUM,
|
||||
(flags & EFX_TXQ_CKSUM_TCPUDP) ? 1 : 0,
|
||||
ESF_DZ_TX_OPTION_IP_CSUM,
|
||||
(flags & EFX_TXQ_CKSUM_IPV4) ? 1 : 0);
|
||||
|
||||
EFSYS_MEM_WRITEQ(etp->et_esmp, 0, &desc);
|
||||
ef10_tx_qpush(etp, *addedp, 0);
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qdestroy(
|
||||
__in efx_txq_t *etp)
|
||||
{
|
||||
/* FIXME */
|
||||
_NOTE(ARGUNUSED(etp))
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qpio_enable(
|
||||
__in efx_txq_t *etp)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
efx_piobuf_handle_t handle;
|
||||
efx_rc_t rc;
|
||||
|
||||
if (etp->et_pio_size != 0) {
|
||||
rc = EALREADY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/* Sub-allocate a PIO block from a piobuf */
|
||||
if ((rc = ef10_nic_pio_alloc(enp,
|
||||
&etp->et_pio_bufnum,
|
||||
&handle,
|
||||
&etp->et_pio_blknum,
|
||||
&etp->et_pio_offset,
|
||||
&etp->et_pio_size)) != 0) {
|
||||
goto fail2;
|
||||
}
|
||||
EFSYS_ASSERT3U(etp->et_pio_size, !=, 0);
|
||||
|
||||
/* Link the piobuf to this TXQ */
|
||||
if ((rc = ef10_nic_pio_link(enp, etp->et_index, handle)) != 0) {
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
/*
|
||||
* et_pio_offset is the offset of the sub-allocated block within the
|
||||
* hardware PIO buffer. It is used as the buffer address in the PIO
|
||||
* option descriptor.
|
||||
*
|
||||
* et_pio_write_offset is the offset of the sub-allocated block from the
|
||||
* start of the write-combined memory mapping, and is used for writing
|
||||
* data into the PIO buffer.
|
||||
*/
|
||||
etp->et_pio_write_offset =
|
||||
(etp->et_pio_bufnum * ER_DZ_TX_PIOBUF_STEP) +
|
||||
ER_DZ_TX_PIOBUF_OFST + etp->et_pio_offset;
|
||||
|
||||
return (0);
|
||||
|
||||
fail3:
|
||||
EFSYS_PROBE(fail3);
|
||||
ef10_nic_pio_free(enp, etp->et_pio_bufnum, etp->et_pio_blknum);
|
||||
etp->et_pio_size = 0;
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qpio_disable(
|
||||
__in efx_txq_t *etp)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
|
||||
if (etp->et_pio_size != 0) {
|
||||
/* Unlink the piobuf from this TXQ */
|
||||
ef10_nic_pio_unlink(enp, etp->et_index);
|
||||
|
||||
/* Free the sub-allocated PIO block */
|
||||
ef10_nic_pio_free(enp, etp->et_pio_bufnum, etp->et_pio_blknum);
|
||||
etp->et_pio_size = 0;
|
||||
etp->et_pio_write_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qpio_write(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(length) uint8_t *buffer,
|
||||
__in size_t length,
|
||||
__in size_t offset)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
efsys_bar_t *esbp = enp->en_esbp;
|
||||
uint32_t write_offset;
|
||||
uint32_t write_offset_limit;
|
||||
efx_qword_t *eqp;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT(length % sizeof (efx_qword_t) == 0);
|
||||
|
||||
if (etp->et_pio_size == 0) {
|
||||
rc = ENOENT;
|
||||
goto fail1;
|
||||
}
|
||||
if (offset + length > etp->et_pio_size) {
|
||||
rc = ENOSPC;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes to PIO buffers must be 64 bit aligned, and multiples of
|
||||
* 64 bits.
|
||||
*/
|
||||
write_offset = etp->et_pio_write_offset + offset;
|
||||
write_offset_limit = write_offset + length;
|
||||
eqp = (efx_qword_t *)buffer;
|
||||
while (write_offset < write_offset_limit) {
|
||||
EFSYS_BAR_WC_WRITEQ(esbp, write_offset, eqp);
|
||||
eqp++;
|
||||
write_offset += sizeof (efx_qword_t);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qpio_post(
|
||||
__in efx_txq_t *etp,
|
||||
__in size_t pkt_length,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp)
|
||||
{
|
||||
efx_qword_t pio_desc;
|
||||
unsigned int id;
|
||||
size_t offset;
|
||||
unsigned int added = *addedp;
|
||||
efx_rc_t rc;
|
||||
|
||||
|
||||
if (added - completed + 1 > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
|
||||
rc = ENOSPC;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (etp->et_pio_size == 0) {
|
||||
rc = ENOENT;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
id = added++ & etp->et_mask;
|
||||
offset = id * sizeof (efx_qword_t);
|
||||
|
||||
EFSYS_PROBE4(tx_pio_post, unsigned int, etp->et_index,
|
||||
unsigned int, id, uint32_t, etp->et_pio_offset,
|
||||
size_t, pkt_length);
|
||||
|
||||
EFX_POPULATE_QWORD_5(pio_desc,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE, 1,
|
||||
ESF_DZ_TX_PIO_CONT, 0,
|
||||
ESF_DZ_TX_PIO_BYTE_CNT, pkt_length,
|
||||
ESF_DZ_TX_PIO_BUF_ADDR, etp->et_pio_offset);
|
||||
|
||||
EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &pio_desc);
|
||||
|
||||
EFX_TX_QSTAT_INCR(etp, TX_POST_PIO);
|
||||
|
||||
*addedp = added;
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qpost(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(n) efx_buffer_t *eb,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp)
|
||||
{
|
||||
unsigned int added = *addedp;
|
||||
unsigned int i;
|
||||
efx_rc_t rc;
|
||||
|
||||
if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
|
||||
rc = ENOSPC;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
efx_buffer_t *ebp = &eb[i];
|
||||
efsys_dma_addr_t addr = ebp->eb_addr;
|
||||
size_t size = ebp->eb_size;
|
||||
boolean_t eop = ebp->eb_eop;
|
||||
unsigned int id;
|
||||
size_t offset;
|
||||
efx_qword_t qword;
|
||||
|
||||
/* Fragments must not span 4k boundaries. */
|
||||
EFSYS_ASSERT(P2ROUNDUP(addr + 1, 4096) >= (addr + size));
|
||||
|
||||
id = added++ & etp->et_mask;
|
||||
offset = id * sizeof (efx_qword_t);
|
||||
|
||||
EFSYS_PROBE5(tx_post, unsigned int, etp->et_index,
|
||||
unsigned int, id, efsys_dma_addr_t, addr,
|
||||
size_t, size, boolean_t, eop);
|
||||
|
||||
EFX_POPULATE_QWORD_5(qword,
|
||||
ESF_DZ_TX_KER_TYPE, 0,
|
||||
ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
|
||||
ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
|
||||
ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
|
||||
ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
|
||||
|
||||
EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &qword);
|
||||
}
|
||||
|
||||
EFX_TX_QSTAT_INCR(etp, TX_POST);
|
||||
|
||||
*addedp = added;
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* This improves performance by pushing a TX descriptor at the same time as the
|
||||
* doorbell. The descriptor must be added to the TXQ, so that can be used if the
|
||||
* hardware decides not to use the pushed descriptor.
|
||||
*/
|
||||
void
|
||||
ef10_tx_qpush(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int added,
|
||||
__in unsigned int pushed)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
unsigned int wptr;
|
||||
unsigned int id;
|
||||
size_t offset;
|
||||
efx_qword_t desc;
|
||||
efx_oword_t oword;
|
||||
|
||||
wptr = added & etp->et_mask;
|
||||
id = pushed & etp->et_mask;
|
||||
offset = id * sizeof (efx_qword_t);
|
||||
|
||||
EFSYS_MEM_READQ(etp->et_esmp, offset, &desc);
|
||||
EFX_POPULATE_OWORD_3(oword,
|
||||
ERF_DZ_TX_DESC_WPTR, wptr,
|
||||
ERF_DZ_TX_DESC_HWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_1),
|
||||
ERF_DZ_TX_DESC_LWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_0));
|
||||
|
||||
/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
|
||||
EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1, wptr, id);
|
||||
EFSYS_PIO_WRITE_BARRIER();
|
||||
EFX_BAR_TBL_DOORBELL_WRITEO(enp, ER_DZ_TX_DESC_UPD_REG, etp->et_index,
|
||||
&oword);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qdesc_post(
|
||||
__in efx_txq_t *etp,
|
||||
__in_ecount(n) efx_desc_t *ed,
|
||||
__in unsigned int n,
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp)
|
||||
{
|
||||
unsigned int added = *addedp;
|
||||
unsigned int i;
|
||||
efx_rc_t rc;
|
||||
|
||||
if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
|
||||
rc = ENOSPC;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
efx_desc_t *edp = &ed[i];
|
||||
unsigned int id;
|
||||
size_t offset;
|
||||
|
||||
id = added++ & etp->et_mask;
|
||||
offset = id * sizeof (efx_desc_t);
|
||||
|
||||
EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
|
||||
}
|
||||
|
||||
EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
|
||||
unsigned int, added, unsigned int, n);
|
||||
|
||||
EFX_TX_QSTAT_INCR(etp, TX_POST);
|
||||
|
||||
*addedp = added;
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qdesc_dma_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in efsys_dma_addr_t addr,
|
||||
__in size_t size,
|
||||
__in boolean_t eop,
|
||||
__out efx_desc_t *edp)
|
||||
{
|
||||
/* Fragments must not span 4k boundaries. */
|
||||
EFSYS_ASSERT(P2ROUNDUP(addr + 1, 4096) >= addr + size);
|
||||
|
||||
EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
|
||||
efsys_dma_addr_t, addr,
|
||||
size_t, size, boolean_t, eop);
|
||||
|
||||
EFX_POPULATE_QWORD_5(edp->ed_eq,
|
||||
ESF_DZ_TX_KER_TYPE, 0,
|
||||
ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
|
||||
ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
|
||||
ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
|
||||
ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qdesc_tso_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t ipv4_id,
|
||||
__in uint32_t tcp_seq,
|
||||
__in uint8_t tcp_flags,
|
||||
__out efx_desc_t *edp)
|
||||
{
|
||||
EFSYS_PROBE4(tx_desc_tso_create, unsigned int, etp->et_index,
|
||||
uint16_t, ipv4_id, uint32_t, tcp_seq,
|
||||
uint8_t, tcp_flags);
|
||||
|
||||
EFX_POPULATE_QWORD_5(edp->ed_eq,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE,
|
||||
ESE_DZ_TX_OPTION_DESC_TSO,
|
||||
ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
|
||||
ESF_DZ_TX_TSO_IP_ID, ipv4_id,
|
||||
ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qdesc_tso2_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t ipv4_id,
|
||||
__in uint32_t tcp_seq,
|
||||
__in uint16_t tcp_mss,
|
||||
__out_ecount(count) efx_desc_t *edp,
|
||||
__in int count)
|
||||
{
|
||||
EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index,
|
||||
uint16_t, ipv4_id, uint32_t, tcp_seq,
|
||||
uint16_t, tcp_mss);
|
||||
|
||||
EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS);
|
||||
|
||||
EFX_POPULATE_QWORD_5(edp[0].ed_eq,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE,
|
||||
ESE_DZ_TX_OPTION_DESC_TSO,
|
||||
ESF_DZ_TX_TSO_OPTION_TYPE,
|
||||
ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
|
||||
ESF_DZ_TX_TSO_IP_ID, ipv4_id,
|
||||
ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
|
||||
EFX_POPULATE_QWORD_4(edp[1].ed_eq,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE,
|
||||
ESE_DZ_TX_OPTION_DESC_TSO,
|
||||
ESF_DZ_TX_TSO_OPTION_TYPE,
|
||||
ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
|
||||
ESF_DZ_TX_TSO_TCP_MSS, tcp_mss);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qdesc_vlantci_create(
|
||||
__in efx_txq_t *etp,
|
||||
__in uint16_t tci,
|
||||
__out efx_desc_t *edp)
|
||||
{
|
||||
EFSYS_PROBE2(tx_desc_vlantci_create, unsigned int, etp->et_index,
|
||||
uint16_t, tci);
|
||||
|
||||
EFX_POPULATE_QWORD_4(edp->ed_eq,
|
||||
ESF_DZ_TX_DESC_IS_OPT, 1,
|
||||
ESF_DZ_TX_OPTION_TYPE,
|
||||
ESE_DZ_TX_OPTION_DESC_VLAN,
|
||||
ESF_DZ_TX_VLAN_OP, tci ? 1 : 0,
|
||||
ESF_DZ_TX_VLAN_TAG1, tci);
|
||||
}
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qpace(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int ns)
|
||||
{
|
||||
efx_rc_t rc;
|
||||
|
||||
/* FIXME */
|
||||
_NOTE(ARGUNUSED(etp, ns))
|
||||
_NOTE(CONSTANTCONDITION)
|
||||
if (B_FALSE) {
|
||||
rc = ENOTSUP;
|
||||
goto fail1;
|
||||
}
|
||||
/* FIXME */
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_tx_qflush(
|
||||
__in efx_txq_t *etp)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_fini_txq(enp, etp->et_index)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
ef10_tx_qenable(
|
||||
__in efx_txq_t *etp)
|
||||
{
|
||||
/* FIXME */
|
||||
_NOTE(ARGUNUSED(etp))
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
@ -184,6 +184,11 @@ efx_nic_check_pcie_link_speed(
|
||||
|
||||
#if EFSYS_OPT_MCDI
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
/* Huntington and Medford require MCDIv2 commands */
|
||||
#define WITH_MCDI_V2 1
|
||||
#endif
|
||||
|
||||
typedef struct efx_mcdi_req_s efx_mcdi_req_t;
|
||||
|
||||
typedef enum efx_mcdi_exception_e {
|
||||
@ -581,6 +586,11 @@ typedef struct efx_nic_cfg_s {
|
||||
#if EFSYS_OPT_MCDI
|
||||
uint8_t enc_mcdi_mdio_channel;
|
||||
#endif /* EFSYS_OPT_MCDI */
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
uint32_t enc_pf;
|
||||
uint32_t enc_vf;
|
||||
uint32_t enc_privilege_mask;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
boolean_t enc_bug26807_workaround;
|
||||
boolean_t enc_bug35388_workaround;
|
||||
boolean_t enc_bug41750_workaround;
|
||||
|
@ -70,6 +70,12 @@
|
||||
# endif
|
||||
#endif /* EFSYS_OPT_FILTER */
|
||||
|
||||
#if (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
|
||||
# if !EFSYS_OPT_FILTER
|
||||
# error "HUNTINGTON or MEDFORD requires FILTER"
|
||||
# endif
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
#ifdef EFSYS_OPT_MAC_FALCON_GMAC
|
||||
# error "MAC_FALCON_GMAC is obsolete and is not supported."
|
||||
#endif
|
||||
|
@ -93,6 +93,18 @@ static const efx_ev_ops_t __efx_ev_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_ev_ops_t __efx_ev_ef10_ops = {
|
||||
ef10_ev_init, /* eevo_init */
|
||||
ef10_ev_fini, /* eevo_fini */
|
||||
ef10_ev_qcreate, /* eevo_qcreate */
|
||||
ef10_ev_qdestroy, /* eevo_qdestroy */
|
||||
ef10_ev_qprime, /* eevo_qprime */
|
||||
ef10_ev_qpost, /* eevo_qpost */
|
||||
ef10_ev_qmoderate, /* eevo_qmoderate */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_ev_init(
|
||||
@ -116,6 +128,12 @@ efx_ev_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
eevop = &__efx_ev_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(0);
|
||||
rc = ENOTSUP;
|
||||
|
@ -79,6 +79,18 @@ static const efx_filter_ops_t __efx_filter_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_filter_ops_t __efx_filter_ef10_ops = {
|
||||
ef10_filter_init, /* efo_init */
|
||||
ef10_filter_fini, /* efo_fini */
|
||||
ef10_filter_restore, /* efo_restore */
|
||||
ef10_filter_add, /* efo_add */
|
||||
ef10_filter_delete, /* efo_delete */
|
||||
ef10_filter_supported_filters, /* efo_supported_filters */
|
||||
ef10_filter_reconfigure, /* efo_reconfigure */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_filter_insert(
|
||||
__in efx_nic_t *enp,
|
||||
@ -147,6 +159,12 @@ efx_filter_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
efop = &__efx_filter_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(0);
|
||||
rc = ENOTSUP;
|
||||
|
@ -45,6 +45,14 @@
|
||||
#include "siena_impl.h"
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
#include "hunt_impl.h"
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
#if (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
|
||||
#include "ef10_impl.h"
|
||||
#endif /* (EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -331,6 +339,9 @@ 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;
|
||||
|
||||
#if EFSYS_OPT_SIENA
|
||||
@ -413,6 +424,24 @@ struct efx_nic_s {
|
||||
#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;
|
||||
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) */
|
||||
};
|
||||
|
||||
|
||||
@ -469,6 +498,13 @@ struct efx_txq_s {
|
||||
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
|
||||
};
|
||||
|
||||
#define EFX_TXQ_MAGIC 0x05092005
|
||||
|
@ -99,6 +99,20 @@ static const efx_intr_ops_t __efx_intr_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_intr_ops_t __efx_intr_ef10_ops = {
|
||||
ef10_intr_init, /* eio_init */
|
||||
ef10_intr_enable, /* eio_enable */
|
||||
ef10_intr_disable, /* eio_disable */
|
||||
ef10_intr_disable_unlocked, /* eio_disable_unlocked */
|
||||
ef10_intr_trigger, /* eio_trigger */
|
||||
ef10_intr_status_line, /* eio_status_line */
|
||||
ef10_intr_status_message, /* eio_status_message */
|
||||
ef10_intr_fatal, /* eio_fatal */
|
||||
ef10_intr_fini, /* eio_fini */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_intr_init(
|
||||
__in efx_nic_t *enp,
|
||||
@ -130,6 +144,12 @@ efx_intr_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
eiop = &__efx_intr_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(B_FALSE);
|
||||
rc = ENOTSUP;
|
||||
|
@ -53,6 +53,21 @@ static const efx_mac_ops_t __efx_siena_mac_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_mac_ops_t __efx_ef10_mac_ops = {
|
||||
ef10_mac_poll, /* emo_poll */
|
||||
ef10_mac_up, /* emo_up */
|
||||
ef10_mac_addr_set, /* emo_addr_set */
|
||||
ef10_mac_pdu_set, /* emo_pdu_set */
|
||||
ef10_mac_pdu_get, /* emo_pdu_get */
|
||||
ef10_mac_reconfigure, /* emo_reconfigure */
|
||||
ef10_mac_multicast_list_set, /* emo_multicast_list_set */
|
||||
ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
|
||||
ef10_mac_filter_default_rxq_clear,
|
||||
/* emo_filter_default_rxq_clear */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_mac_pdu_set(
|
||||
__in efx_nic_t *enp,
|
||||
@ -494,6 +509,13 @@ efx_mac_select(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
emop = &__efx_ef10_mac_ops;
|
||||
type = EFX_MAC_HUNTINGTON;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
|
@ -69,6 +69,21 @@ static const efx_mcdi_ops_t __efx_mcdi_siena_ops = {
|
||||
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
static const efx_mcdi_ops_t __efx_mcdi_ef10_ops = {
|
||||
ef10_mcdi_init, /* emco_init */
|
||||
ef10_mcdi_send_request, /* emco_send_request */
|
||||
ef10_mcdi_poll_reboot, /* emco_poll_reboot */
|
||||
ef10_mcdi_poll_response, /* emco_poll_response */
|
||||
ef10_mcdi_read_response, /* emco_read_response */
|
||||
ef10_mcdi_fini, /* emco_fini */
|
||||
ef10_mcdi_feature_supported, /* emco_feature_supported */
|
||||
ef10_mcdi_get_timeout, /* emco_get_timeout */
|
||||
};
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
@ -89,6 +104,12 @@ efx_mcdi_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
emcop = &__efx_mcdi_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(0);
|
||||
rc = ENOTSUP;
|
||||
@ -1553,6 +1574,107 @@ efx_mcdi_log_ctrl(
|
||||
}
|
||||
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
|
||||
/*
|
||||
* This function returns the pf and vf number of a function. If it is a pf the
|
||||
* vf number is 0xffff. The vf number is the index of the vf on that
|
||||
* function. So if you have 3 vfs on pf 0 the 3 vfs will return (pf=0,vf=0),
|
||||
* (pf=0,vf=1), (pf=0,vf=2) aand the pf will return (pf=0, vf=0xffff).
|
||||
*/
|
||||
__checkReturn efx_rc_t
|
||||
efx_mcdi_get_function_info(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *pfp,
|
||||
__out_opt uint32_t *vfp)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_GET_FUNCTION_INFO_IN_LEN,
|
||||
MC_CMD_GET_FUNCTION_INFO_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_GET_FUNCTION_INFO;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_GET_FUNCTION_INFO_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_GET_FUNCTION_INFO_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_FUNCTION_INFO_OUT_LEN) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
*pfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_PF);
|
||||
if (vfp != NULL)
|
||||
*vfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_VF);
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_mcdi_privilege_mask(
|
||||
__in efx_nic_t *enp,
|
||||
__in uint32_t pf,
|
||||
__in uint32_t vf,
|
||||
__out uint32_t *maskp)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_PRIVILEGE_MASK_IN_LEN,
|
||||
MC_CMD_PRIVILEGE_MASK_OUT_LEN)];
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
|
||||
|
||||
MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
|
||||
PRIVILEGE_MASK_IN_FUNCTION_PF, pf,
|
||||
PRIVILEGE_MASK_IN_FUNCTION_VF, vf);
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (req.emr_out_length_used < MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
*maskp = MCDI_OUT_DWORD(req, PRIVILEGE_MASK_OUT_OLD_MASK);
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_mcdi_set_workaround(
|
||||
__in efx_nic_t *enp,
|
||||
|
@ -54,6 +54,26 @@ efx_family(
|
||||
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 */
|
||||
|
||||
case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */
|
||||
default:
|
||||
break;
|
||||
@ -152,6 +172,22 @@ static const efx_nic_ops_t __efx_nic_siena_ops = {
|
||||
|
||||
#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 */
|
||||
ef10_nic_fini, /* eno_fini */
|
||||
ef10_nic_unprobe, /* eno_unprobe */
|
||||
};
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_nic_create(
|
||||
@ -193,6 +229,23 @@ efx_nic_create(
|
||||
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 |
|
||||
EFX_FEATURE_PACKED_STREAM;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
rc = ENOTSUP;
|
||||
goto fail2;
|
||||
|
@ -42,6 +42,16 @@ static const efx_phy_ops_t __efx_phy_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_phy_ops_t __efx_phy_ef10_ops = {
|
||||
ef10_phy_power, /* epo_power */
|
||||
NULL, /* epo_reset */
|
||||
ef10_phy_reconfigure, /* epo_reconfigure */
|
||||
ef10_phy_verify, /* epo_verify */
|
||||
ef10_phy_oui_get, /* epo_oui_get */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_phy_probe(
|
||||
__in efx_nic_t *enp)
|
||||
@ -63,6 +73,11 @@ efx_phy_probe(
|
||||
epop = &__efx_phy_siena_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
epop = &__efx_phy_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
default:
|
||||
rc = ENOTSUP;
|
||||
goto fail1;
|
||||
|
571
drivers/net/sfc/base/efx_regs_ef10.h
Normal file
571
drivers/net/sfc/base/efx_regs_ef10.h
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_EFX_EF10_REGS_H
|
||||
#define _SYS_EFX_EF10_REGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
* NOTE: the line below marks the start of the autogenerated section
|
||||
* EF10 registers and descriptors
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* BIU_HW_REV_ID_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_BIU_HW_REV_ID_REG_OFST 0x00000000
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_BIU_HW_REV_ID_REG_RESET 0xeb14face
|
||||
|
||||
|
||||
#define ERF_DZ_HW_REV_ID_LBN 0
|
||||
#define ERF_DZ_HW_REV_ID_WIDTH 32
|
||||
|
||||
|
||||
/*
|
||||
* BIU_MC_SFT_STATUS_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_BIU_MC_SFT_STATUS_REG_OFST 0x00000010
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_BIU_MC_SFT_STATUS_REG_STEP 4
|
||||
#define ER_DZ_BIU_MC_SFT_STATUS_REG_ROWS 8
|
||||
#define ER_DZ_BIU_MC_SFT_STATUS_REG_RESET 0x1111face
|
||||
|
||||
|
||||
#define ERF_DZ_MC_SFT_STATUS_LBN 0
|
||||
#define ERF_DZ_MC_SFT_STATUS_WIDTH 32
|
||||
|
||||
|
||||
/*
|
||||
* BIU_INT_ISR_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_BIU_INT_ISR_REG_OFST 0x00000090
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_BIU_INT_ISR_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_ISR_REG_LBN 0
|
||||
#define ERF_DZ_ISR_REG_WIDTH 32
|
||||
|
||||
|
||||
/*
|
||||
* MC_DB_LWRD_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_MC_DB_LWRD_REG_OFST 0x00000200
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_MC_DB_LWRD_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_MC_DOORBELL_L_LBN 0
|
||||
#define ERF_DZ_MC_DOORBELL_L_WIDTH 32
|
||||
|
||||
|
||||
/*
|
||||
* MC_DB_HWRD_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_MC_DB_HWRD_REG_OFST 0x00000204
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_MC_DB_HWRD_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_MC_DOORBELL_H_LBN 0
|
||||
#define ERF_DZ_MC_DOORBELL_H_WIDTH 32
|
||||
|
||||
|
||||
/*
|
||||
* EVQ_RPTR_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_EVQ_RPTR_REG_OFST 0x00000400
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_EVQ_RPTR_REG_STEP 8192
|
||||
#define ER_DZ_EVQ_RPTR_REG_ROWS 2048
|
||||
#define ER_DZ_EVQ_RPTR_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_EVQ_RPTR_VLD_LBN 15
|
||||
#define ERF_DZ_EVQ_RPTR_VLD_WIDTH 1
|
||||
#define ERF_DZ_EVQ_RPTR_LBN 0
|
||||
#define ERF_DZ_EVQ_RPTR_WIDTH 15
|
||||
|
||||
|
||||
/*
|
||||
* EVQ_TMR_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_EVQ_TMR_REG_OFST 0x00000420
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_EVQ_TMR_REG_STEP 8192
|
||||
#define ER_DZ_EVQ_TMR_REG_ROWS 2048
|
||||
#define ER_DZ_EVQ_TMR_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_TC_TIMER_MODE_LBN 14
|
||||
#define ERF_DZ_TC_TIMER_MODE_WIDTH 2
|
||||
#define ERF_DZ_TC_TIMER_VAL_LBN 0
|
||||
#define ERF_DZ_TC_TIMER_VAL_WIDTH 14
|
||||
|
||||
|
||||
/*
|
||||
* RX_DESC_UPD_REG(32bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_RX_DESC_UPD_REG_OFST 0x00000830
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_RX_DESC_UPD_REG_STEP 8192
|
||||
#define ER_DZ_RX_DESC_UPD_REG_ROWS 2048
|
||||
#define ER_DZ_RX_DESC_UPD_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_RX_DESC_WPTR_LBN 0
|
||||
#define ERF_DZ_RX_DESC_WPTR_WIDTH 12
|
||||
|
||||
/*
|
||||
* TX_DESC_UPD_REG(96bit):
|
||||
*
|
||||
*/
|
||||
|
||||
#define ER_DZ_TX_DESC_UPD_REG_OFST 0x00000a10
|
||||
/* hunta0,medforda0=pcie_pf_bar2 */
|
||||
#define ER_DZ_TX_DESC_UPD_REG_STEP 8192
|
||||
#define ER_DZ_TX_DESC_UPD_REG_ROWS 2048
|
||||
#define ER_DZ_TX_DESC_UPD_REG_RESET 0x0
|
||||
|
||||
|
||||
#define ERF_DZ_RSVD_LBN 76
|
||||
#define ERF_DZ_RSVD_WIDTH 20
|
||||
#define ERF_DZ_TX_DESC_WPTR_LBN 64
|
||||
#define ERF_DZ_TX_DESC_WPTR_WIDTH 12
|
||||
#define ERF_DZ_TX_DESC_HWORD_LBN 32
|
||||
#define ERF_DZ_TX_DESC_HWORD_WIDTH 32
|
||||
#define ERF_DZ_TX_DESC_LWORD_LBN 0
|
||||
#define ERF_DZ_TX_DESC_LWORD_WIDTH 32
|
||||
|
||||
|
||||
/* ES_DRIVER_EV */
|
||||
#define ESF_DZ_DRV_CODE_LBN 60
|
||||
#define ESF_DZ_DRV_CODE_WIDTH 4
|
||||
#define ESF_DZ_DRV_SUB_CODE_LBN 56
|
||||
#define ESF_DZ_DRV_SUB_CODE_WIDTH 4
|
||||
#define ESE_DZ_DRV_TIMER_EV 3
|
||||
#define ESE_DZ_DRV_START_UP_EV 2
|
||||
#define ESE_DZ_DRV_WAKE_UP_EV 1
|
||||
#define ESF_DZ_DRV_SUB_DATA_DW0_LBN 0
|
||||
#define ESF_DZ_DRV_SUB_DATA_DW0_WIDTH 32
|
||||
#define ESF_DZ_DRV_SUB_DATA_DW1_LBN 32
|
||||
#define ESF_DZ_DRV_SUB_DATA_DW1_WIDTH 24
|
||||
#define ESF_DZ_DRV_SUB_DATA_LBN 0
|
||||
#define ESF_DZ_DRV_SUB_DATA_WIDTH 56
|
||||
#define ESF_DZ_DRV_EVQ_ID_LBN 0
|
||||
#define ESF_DZ_DRV_EVQ_ID_WIDTH 14
|
||||
#define ESF_DZ_DRV_TMR_ID_LBN 0
|
||||
#define ESF_DZ_DRV_TMR_ID_WIDTH 14
|
||||
|
||||
|
||||
/* ES_EVENT_ENTRY */
|
||||
#define ESF_DZ_EV_CODE_LBN 60
|
||||
#define ESF_DZ_EV_CODE_WIDTH 4
|
||||
#define ESE_DZ_EV_CODE_MCDI_EV 12
|
||||
#define ESE_DZ_EV_CODE_DRIVER_EV 5
|
||||
#define ESE_DZ_EV_CODE_TX_EV 2
|
||||
#define ESE_DZ_EV_CODE_RX_EV 0
|
||||
#define ESE_DZ_OTHER other
|
||||
#define ESF_DZ_EV_DATA_DW0_LBN 0
|
||||
#define ESF_DZ_EV_DATA_DW0_WIDTH 32
|
||||
#define ESF_DZ_EV_DATA_DW1_LBN 32
|
||||
#define ESF_DZ_EV_DATA_DW1_WIDTH 28
|
||||
#define ESF_DZ_EV_DATA_LBN 0
|
||||
#define ESF_DZ_EV_DATA_WIDTH 60
|
||||
|
||||
|
||||
/* ES_MC_EVENT */
|
||||
#define ESF_DZ_MC_CODE_LBN 60
|
||||
#define ESF_DZ_MC_CODE_WIDTH 4
|
||||
#define ESF_DZ_MC_OVERRIDE_HOLDOFF_LBN 59
|
||||
#define ESF_DZ_MC_OVERRIDE_HOLDOFF_WIDTH 1
|
||||
#define ESF_DZ_MC_DROP_EVENT_LBN 58
|
||||
#define ESF_DZ_MC_DROP_EVENT_WIDTH 1
|
||||
#define ESF_DZ_MC_SOFT_DW0_LBN 0
|
||||
#define ESF_DZ_MC_SOFT_DW0_WIDTH 32
|
||||
#define ESF_DZ_MC_SOFT_DW1_LBN 32
|
||||
#define ESF_DZ_MC_SOFT_DW1_WIDTH 26
|
||||
#define ESF_DZ_MC_SOFT_LBN 0
|
||||
#define ESF_DZ_MC_SOFT_WIDTH 58
|
||||
|
||||
|
||||
/* ES_RX_EVENT */
|
||||
#define ESF_DZ_RX_CODE_LBN 60
|
||||
#define ESF_DZ_RX_CODE_WIDTH 4
|
||||
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_LBN 59
|
||||
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_WIDTH 1
|
||||
#define ESF_DZ_RX_DROP_EVENT_LBN 58
|
||||
#define ESF_DZ_RX_DROP_EVENT_WIDTH 1
|
||||
#define ESF_DD_RX_EV_RSVD2_LBN 54
|
||||
#define ESF_DD_RX_EV_RSVD2_WIDTH 4
|
||||
#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
|
||||
#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
|
||||
#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_LBN 56
|
||||
#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_WIDTH 1
|
||||
#define ESF_EZ_RX_EV_RSVD2_LBN 54
|
||||
#define ESF_EZ_RX_EV_RSVD2_WIDTH 2
|
||||
#define ESF_DZ_RX_EV_SOFT2_LBN 52
|
||||
#define ESF_DZ_RX_EV_SOFT2_WIDTH 2
|
||||
#define ESF_DZ_RX_DSC_PTR_LBITS_LBN 48
|
||||
#define ESF_DZ_RX_DSC_PTR_LBITS_WIDTH 4
|
||||
#define ESF_DZ_RX_L4_CLASS_LBN 45
|
||||
#define ESF_DZ_RX_L4_CLASS_WIDTH 3
|
||||
#define ESE_DZ_L4_CLASS_RSVD7 7
|
||||
#define ESE_DZ_L4_CLASS_RSVD6 6
|
||||
#define ESE_DZ_L4_CLASS_RSVD5 5
|
||||
#define ESE_DZ_L4_CLASS_RSVD4 4
|
||||
#define ESE_DZ_L4_CLASS_RSVD3 3
|
||||
#define ESE_DZ_L4_CLASS_UDP 2
|
||||
#define ESE_DZ_L4_CLASS_TCP 1
|
||||
#define ESE_DZ_L4_CLASS_UNKNOWN 0
|
||||
#define ESF_DZ_RX_L3_CLASS_LBN 42
|
||||
#define ESF_DZ_RX_L3_CLASS_WIDTH 3
|
||||
#define ESE_DZ_L3_CLASS_RSVD7 7
|
||||
#define ESE_DZ_L3_CLASS_IP6_FRAG 6
|
||||
#define ESE_DZ_L3_CLASS_ARP 5
|
||||
#define ESE_DZ_L3_CLASS_IP4_FRAG 4
|
||||
#define ESE_DZ_L3_CLASS_FCOE 3
|
||||
#define ESE_DZ_L3_CLASS_IP6 2
|
||||
#define ESE_DZ_L3_CLASS_IP4 1
|
||||
#define ESE_DZ_L3_CLASS_UNKNOWN 0
|
||||
#define ESF_DZ_RX_ETH_TAG_CLASS_LBN 39
|
||||
#define ESF_DZ_RX_ETH_TAG_CLASS_WIDTH 3
|
||||
#define ESE_DZ_ETH_TAG_CLASS_RSVD7 7
|
||||
#define ESE_DZ_ETH_TAG_CLASS_RSVD6 6
|
||||
#define ESE_DZ_ETH_TAG_CLASS_RSVD5 5
|
||||
#define ESE_DZ_ETH_TAG_CLASS_RSVD4 4
|
||||
#define ESE_DZ_ETH_TAG_CLASS_RSVD3 3
|
||||
#define ESE_DZ_ETH_TAG_CLASS_VLAN2 2
|
||||
#define ESE_DZ_ETH_TAG_CLASS_VLAN1 1
|
||||
#define ESE_DZ_ETH_TAG_CLASS_NONE 0
|
||||
#define ESF_DZ_RX_ETH_BASE_CLASS_LBN 36
|
||||
#define ESF_DZ_RX_ETH_BASE_CLASS_WIDTH 3
|
||||
#define ESE_DZ_ETH_BASE_CLASS_LLC_SNAP 2
|
||||
#define ESE_DZ_ETH_BASE_CLASS_LLC 1
|
||||
#define ESE_DZ_ETH_BASE_CLASS_ETH2 0
|
||||
#define ESF_DZ_RX_MAC_CLASS_LBN 35
|
||||
#define ESF_DZ_RX_MAC_CLASS_WIDTH 1
|
||||
#define ESE_DZ_MAC_CLASS_MCAST 1
|
||||
#define ESE_DZ_MAC_CLASS_UCAST 0
|
||||
#define ESF_DD_RX_EV_SOFT1_LBN 32
|
||||
#define ESF_DD_RX_EV_SOFT1_WIDTH 3
|
||||
#define ESF_EZ_RX_EV_SOFT1_LBN 34
|
||||
#define ESF_EZ_RX_EV_SOFT1_WIDTH 1
|
||||
#define ESF_EZ_RX_ENCAP_HDR_LBN 32
|
||||
#define ESF_EZ_RX_ENCAP_HDR_WIDTH 2
|
||||
#define ESE_EZ_ENCAP_HDR_GRE 2
|
||||
#define ESE_EZ_ENCAP_HDR_VXLAN 1
|
||||
#define ESE_EZ_ENCAP_HDR_NONE 0
|
||||
#define ESF_DD_RX_EV_RSVD1_LBN 30
|
||||
#define ESF_DD_RX_EV_RSVD1_WIDTH 2
|
||||
#define ESF_EZ_RX_EV_RSVD1_LBN 31
|
||||
#define ESF_EZ_RX_EV_RSVD1_WIDTH 1
|
||||
#define ESF_EZ_RX_ABORT_LBN 30
|
||||
#define ESF_EZ_RX_ABORT_WIDTH 1
|
||||
#define ESF_DZ_RX_ECC_ERR_LBN 29
|
||||
#define ESF_DZ_RX_ECC_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_CRC1_ERR_LBN 28
|
||||
#define ESF_DZ_RX_CRC1_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_CRC0_ERR_LBN 27
|
||||
#define ESF_DZ_RX_CRC0_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_TCPUDP_CKSUM_ERR_LBN 26
|
||||
#define ESF_DZ_RX_TCPUDP_CKSUM_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_IPCKSUM_ERR_LBN 25
|
||||
#define ESF_DZ_RX_IPCKSUM_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_ECRC_ERR_LBN 24
|
||||
#define ESF_DZ_RX_ECRC_ERR_WIDTH 1
|
||||
#define ESF_DZ_RX_QLABEL_LBN 16
|
||||
#define ESF_DZ_RX_QLABEL_WIDTH 5
|
||||
#define ESF_DZ_RX_PARSE_INCOMPLETE_LBN 15
|
||||
#define ESF_DZ_RX_PARSE_INCOMPLETE_WIDTH 1
|
||||
#define ESF_DZ_RX_CONT_LBN 14
|
||||
#define ESF_DZ_RX_CONT_WIDTH 1
|
||||
#define ESF_DZ_RX_BYTES_LBN 0
|
||||
#define ESF_DZ_RX_BYTES_WIDTH 14
|
||||
|
||||
|
||||
/* ES_RX_KER_DESC */
|
||||
#define ESF_DZ_RX_KER_RESERVED_LBN 62
|
||||
#define ESF_DZ_RX_KER_RESERVED_WIDTH 2
|
||||
#define ESF_DZ_RX_KER_BYTE_CNT_LBN 48
|
||||
#define ESF_DZ_RX_KER_BYTE_CNT_WIDTH 14
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_DW0_LBN 0
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_DW0_WIDTH 32
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_DW1_LBN 32
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_DW1_WIDTH 16
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_LBN 0
|
||||
#define ESF_DZ_RX_KER_BUF_ADDR_WIDTH 48
|
||||
|
||||
|
||||
/* ES_TX_CSUM_TSTAMP_DESC */
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
|
||||
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_DESC_TSO 7
|
||||
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
|
||||
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
|
||||
#define ESF_DZ_TX_OPTION_TS_AT_TXDP_LBN 8
|
||||
#define ESF_DZ_TX_OPTION_TS_AT_TXDP_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM_LBN 7
|
||||
#define ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_INNER_IP_CSUM_LBN 6
|
||||
#define ESF_DZ_TX_OPTION_INNER_IP_CSUM_WIDTH 1
|
||||
#define ESF_DZ_TX_TIMESTAMP_LBN 5
|
||||
#define ESF_DZ_TX_TIMESTAMP_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_CRC_MODE_LBN 2
|
||||
#define ESF_DZ_TX_OPTION_CRC_MODE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_CRC_FCOIP_MPA 5
|
||||
#define ESE_DZ_TX_OPTION_CRC_FCOIP_FCOE 4
|
||||
#define ESE_DZ_TX_OPTION_CRC_ISCSI_HDR_AND_PYLD 3
|
||||
#define ESE_DZ_TX_OPTION_CRC_ISCSI_HDR 2
|
||||
#define ESE_DZ_TX_OPTION_CRC_FCOE 1
|
||||
#define ESE_DZ_TX_OPTION_CRC_OFF 0
|
||||
#define ESF_DZ_TX_OPTION_UDP_TCP_CSUM_LBN 1
|
||||
#define ESF_DZ_TX_OPTION_UDP_TCP_CSUM_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_IP_CSUM_LBN 0
|
||||
#define ESF_DZ_TX_OPTION_IP_CSUM_WIDTH 1
|
||||
|
||||
|
||||
/* ES_TX_EVENT */
|
||||
#define ESF_DZ_TX_CODE_LBN 60
|
||||
#define ESF_DZ_TX_CODE_WIDTH 4
|
||||
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_LBN 59
|
||||
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_WIDTH 1
|
||||
#define ESF_DZ_TX_DROP_EVENT_LBN 58
|
||||
#define ESF_DZ_TX_DROP_EVENT_WIDTH 1
|
||||
#define ESF_DD_TX_EV_RSVD_LBN 48
|
||||
#define ESF_DD_TX_EV_RSVD_WIDTH 10
|
||||
#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
|
||||
#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
|
||||
#define ESF_EZ_IP_INNER_CHKSUM_ERR_LBN 56
|
||||
#define ESF_EZ_IP_INNER_CHKSUM_ERR_WIDTH 1
|
||||
#define ESF_EZ_TX_EV_RSVD_LBN 48
|
||||
#define ESF_EZ_TX_EV_RSVD_WIDTH 8
|
||||
#define ESF_DZ_TX_SOFT2_LBN 32
|
||||
#define ESF_DZ_TX_SOFT2_WIDTH 16
|
||||
#define ESF_DD_TX_SOFT1_LBN 24
|
||||
#define ESF_DD_TX_SOFT1_WIDTH 8
|
||||
#define ESF_EZ_TX_CAN_MERGE_LBN 31
|
||||
#define ESF_EZ_TX_CAN_MERGE_WIDTH 1
|
||||
#define ESF_EZ_TX_SOFT1_LBN 24
|
||||
#define ESF_EZ_TX_SOFT1_WIDTH 7
|
||||
#define ESF_DZ_TX_QLABEL_LBN 16
|
||||
#define ESF_DZ_TX_QLABEL_WIDTH 5
|
||||
#define ESF_DZ_TX_DESCR_INDX_LBN 0
|
||||
#define ESF_DZ_TX_DESCR_INDX_WIDTH 16
|
||||
|
||||
|
||||
/* ES_TX_KER_DESC */
|
||||
#define ESF_DZ_TX_KER_TYPE_LBN 63
|
||||
#define ESF_DZ_TX_KER_TYPE_WIDTH 1
|
||||
#define ESF_DZ_TX_KER_CONT_LBN 62
|
||||
#define ESF_DZ_TX_KER_CONT_WIDTH 1
|
||||
#define ESF_DZ_TX_KER_BYTE_CNT_LBN 48
|
||||
#define ESF_DZ_TX_KER_BYTE_CNT_WIDTH 14
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_DW0_LBN 0
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_DW0_WIDTH 32
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_DW1_LBN 32
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_DW1_WIDTH 16
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_LBN 0
|
||||
#define ESF_DZ_TX_KER_BUF_ADDR_WIDTH 48
|
||||
|
||||
|
||||
/* ES_TX_PIO_DESC */
|
||||
#define ESF_DZ_TX_PIO_TYPE_LBN 63
|
||||
#define ESF_DZ_TX_PIO_TYPE_WIDTH 1
|
||||
#define ESF_DZ_TX_PIO_OPT_LBN 60
|
||||
#define ESF_DZ_TX_PIO_OPT_WIDTH 3
|
||||
#define ESF_DZ_TX_PIO_CONT_LBN 59
|
||||
#define ESF_DZ_TX_PIO_CONT_WIDTH 1
|
||||
#define ESF_DZ_TX_PIO_BYTE_CNT_LBN 32
|
||||
#define ESF_DZ_TX_PIO_BYTE_CNT_WIDTH 12
|
||||
#define ESF_DZ_TX_PIO_BUF_ADDR_LBN 0
|
||||
#define ESF_DZ_TX_PIO_BUF_ADDR_WIDTH 12
|
||||
|
||||
|
||||
/* ES_TX_TSO_DESC */
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
|
||||
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_DESC_TSO 7
|
||||
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
|
||||
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
|
||||
#define ESF_DZ_TX_TSO_TCP_FLAGS_LBN 48
|
||||
#define ESF_DZ_TX_TSO_TCP_FLAGS_WIDTH 8
|
||||
#define ESF_DZ_TX_TSO_IP_ID_LBN 32
|
||||
#define ESF_DZ_TX_TSO_IP_ID_WIDTH 16
|
||||
#define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
|
||||
#define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
|
||||
|
||||
|
||||
/* TX_TSO_FATSO2A_DESC */
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
|
||||
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_DESC_TSO 7
|
||||
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
|
||||
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B 3
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A 2
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
|
||||
#define ESF_DZ_TX_TSO_IP_ID_LBN 32
|
||||
#define ESF_DZ_TX_TSO_IP_ID_WIDTH 16
|
||||
#define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
|
||||
#define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
|
||||
|
||||
|
||||
/* TX_TSO_FATSO2B_DESC */
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
|
||||
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_DESC_TSO 7
|
||||
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
|
||||
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
|
||||
#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B 3
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A 2
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
|
||||
#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
|
||||
#define ESF_DZ_TX_TSO_OUTER_IP_ID_LBN 16
|
||||
#define ESF_DZ_TX_TSO_OUTER_IP_ID_WIDTH 16
|
||||
#define ESF_DZ_TX_TSO_TCP_MSS_LBN 32
|
||||
#define ESF_DZ_TX_TSO_TCP_MSS_WIDTH 16
|
||||
#define ESF_DZ_TX_TSO_INNER_PE_CSUM_LBN 0
|
||||
#define ESF_DZ_TX_TSO_INNER_PE_CSUM_WIDTH 16
|
||||
|
||||
|
||||
/* ES_TX_VLAN_DESC */
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
|
||||
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
|
||||
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
|
||||
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
|
||||
#define ESE_DZ_TX_OPTION_DESC_TSO 7
|
||||
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
|
||||
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
|
||||
#define ESF_DZ_TX_VLAN_OP_LBN 32
|
||||
#define ESF_DZ_TX_VLAN_OP_WIDTH 2
|
||||
#define ESF_DZ_TX_VLAN_TAG2_LBN 16
|
||||
#define ESF_DZ_TX_VLAN_TAG2_WIDTH 16
|
||||
#define ESF_DZ_TX_VLAN_TAG1_LBN 0
|
||||
#define ESF_DZ_TX_VLAN_TAG1_WIDTH 16
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* NOTE: the comment line above marks the end of the autogenerated section
|
||||
*/
|
||||
|
||||
/*
|
||||
* The workaround for bug 35388 requires multiplexing writes through
|
||||
* the ERF_DZ_TX_DESC_WPTR address.
|
||||
* TX_DESC_UPD: 0ppppppppppp (bit 11 lost)
|
||||
* EVQ_RPTR: 1000hhhhhhhh, 1001llllllll (split into high and low bits)
|
||||
* EVQ_TMR: 11mmvvvvvvvv (bits 8:13 of value lost)
|
||||
*/
|
||||
#define ER_DD_EVQ_INDIRECT_OFST (ER_DZ_TX_DESC_UPD_REG_OFST + 2 * 4)
|
||||
#define ER_DD_EVQ_INDIRECT_STEP ER_DZ_TX_DESC_UPD_REG_STEP
|
||||
#define ERF_DD_EVQ_IND_RPTR_FLAGS_LBN 8
|
||||
#define ERF_DD_EVQ_IND_RPTR_FLAGS_WIDTH 4
|
||||
#define EFE_DD_EVQ_IND_RPTR_FLAGS_HIGH 8
|
||||
#define EFE_DD_EVQ_IND_RPTR_FLAGS_LOW 9
|
||||
#define ERF_DD_EVQ_IND_RPTR_LBN 0
|
||||
#define ERF_DD_EVQ_IND_RPTR_WIDTH 8
|
||||
#define ERF_DD_EVQ_IND_TIMER_FLAGS_LBN 10
|
||||
#define ERF_DD_EVQ_IND_TIMER_FLAGS_WIDTH 2
|
||||
#define EFE_DD_EVQ_IND_TIMER_FLAGS 3
|
||||
#define ERF_DD_EVQ_IND_TIMER_MODE_LBN 8
|
||||
#define ERF_DD_EVQ_IND_TIMER_MODE_WIDTH 2
|
||||
#define ERF_DD_EVQ_IND_TIMER_VAL_LBN 0
|
||||
#define ERF_DD_EVQ_IND_TIMER_VAL_WIDTH 8
|
||||
|
||||
/* Packed stream magic doorbell command */
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DOORBELL_LBN 11
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DOORBELL_WIDTH 1
|
||||
|
||||
#define ERF_DZ_RX_DESC_MAGIC_CMD_LBN 8
|
||||
#define ERF_DZ_RX_DESC_MAGIC_CMD_WIDTH 3
|
||||
#define ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS 0
|
||||
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DATA_LBN 0
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DATA_WIDTH 8
|
||||
|
||||
/* Packed stream RX packet prefix */
|
||||
#define ES_DZ_PS_RX_PREFIX_TSTAMP_LBN 0
|
||||
#define ES_DZ_PS_RX_PREFIX_TSTAMP_WIDTH 32
|
||||
#define ES_DZ_PS_RX_PREFIX_CAP_LEN_LBN 32
|
||||
#define ES_DZ_PS_RX_PREFIX_CAP_LEN_WIDTH 16
|
||||
#define ES_DZ_PS_RX_PREFIX_ORIG_LEN_LBN 48
|
||||
#define ES_DZ_PS_RX_PREFIX_ORIG_LEN_WIDTH 16
|
||||
|
||||
/*
|
||||
* An extra flag for the packed stream mode,
|
||||
* signalling the start of a new buffer
|
||||
*/
|
||||
#define ESF_DZ_RX_EV_ROTATE_LBN 53
|
||||
#define ESF_DZ_RX_EV_ROTATE_WIDTH 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_EFX_EF10_REGS_H */
|
@ -104,6 +104,20 @@ static const efx_rx_ops_t __efx_rx_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
static const efx_rx_ops_t __efx_rx_ef10_ops = {
|
||||
ef10_rx_init, /* erxo_init */
|
||||
ef10_rx_fini, /* erxo_fini */
|
||||
ef10_rx_prefix_pktlen, /* erxo_prefix_pktlen */
|
||||
ef10_rx_qpost, /* erxo_qpost */
|
||||
ef10_rx_qpush, /* erxo_qpush */
|
||||
ef10_rx_qflush, /* erxo_qflush */
|
||||
ef10_rx_qenable, /* erxo_qenable */
|
||||
ef10_rx_qcreate, /* erxo_qcreate */
|
||||
ef10_rx_qdestroy, /* erxo_qdestroy */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_rx_init(
|
||||
@ -132,6 +146,12 @@ efx_rx_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
erxop = &__efx_rx_ef10_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(0);
|
||||
rc = ENOTSUP;
|
||||
|
@ -49,6 +49,22 @@ efx_sram_buf_tbl_set(
|
||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD) {
|
||||
/*
|
||||
* FIXME: the efx_sram_buf_tbl_*() functionality needs to be
|
||||
* pulled inside the Falcon/Siena queue create/destroy code,
|
||||
* and then the original functions can be removed (see bug30834
|
||||
* comment #1). But, for now, we just ensure that they are
|
||||
* no-ops for EF10, to allow bringing up existing drivers
|
||||
* without modification.
|
||||
*/
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
if (stop >= EFX_BUF_TBL_SIZE) {
|
||||
rc = EFBIG;
|
||||
goto fail1;
|
||||
@ -155,6 +171,22 @@ efx_sram_buf_tbl_clear(
|
||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
|
||||
if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
|
||||
enp->en_family == EFX_FAMILY_MEDFORD) {
|
||||
/*
|
||||
* FIXME: the efx_sram_buf_tbl_*() functionality needs to be
|
||||
* pulled inside the Falcon/Siena queue create/destroy code,
|
||||
* and then the original functions can be removed (see bug30834
|
||||
* comment #1). But, for now, we just ensure that they are
|
||||
* no-ops for EF10, to allow bringing up existing drivers
|
||||
* without modification.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
||||
EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
|
||||
|
||||
EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
|
||||
|
@ -129,6 +129,29 @@ static const efx_tx_ops_t __efx_tx_siena_ops = {
|
||||
};
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
static const efx_tx_ops_t __efx_tx_hunt_ops = {
|
||||
ef10_tx_init, /* etxo_init */
|
||||
ef10_tx_fini, /* etxo_fini */
|
||||
ef10_tx_qcreate, /* etxo_qcreate */
|
||||
ef10_tx_qdestroy, /* etxo_qdestroy */
|
||||
ef10_tx_qpost, /* etxo_qpost */
|
||||
ef10_tx_qpush, /* etxo_qpush */
|
||||
ef10_tx_qpace, /* etxo_qpace */
|
||||
ef10_tx_qflush, /* etxo_qflush */
|
||||
ef10_tx_qenable, /* etxo_qenable */
|
||||
ef10_tx_qpio_enable, /* etxo_qpio_enable */
|
||||
ef10_tx_qpio_disable, /* etxo_qpio_disable */
|
||||
ef10_tx_qpio_write, /* etxo_qpio_write */
|
||||
ef10_tx_qpio_post, /* etxo_qpio_post */
|
||||
ef10_tx_qdesc_post, /* etxo_qdesc_post */
|
||||
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
||||
ef10_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
|
||||
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
|
||||
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
|
||||
};
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_tx_init(
|
||||
__in efx_nic_t *enp)
|
||||
@ -156,6 +179,12 @@ efx_tx_init(
|
||||
break;
|
||||
#endif /* EFSYS_OPT_SIENA */
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
case EFX_FAMILY_HUNTINGTON:
|
||||
etxop = &__efx_tx_hunt_ops;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
default:
|
||||
EFSYS_ASSERT(0);
|
||||
rc = ENOTSUP;
|
||||
|
74
drivers/net/sfc/base/hunt_impl.h
Normal file
74
drivers/net/sfc/base/hunt_impl.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_HUNT_IMPL_H
|
||||
#define _SYS_HUNT_IMPL_H
|
||||
|
||||
#include "efx.h"
|
||||
#include "efx_regs.h"
|
||||
#include "efx_regs_ef10.h"
|
||||
#include "efx_mcdi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Missing register definitions */
|
||||
#ifndef ER_DZ_TX_PIOBUF_OFST
|
||||
#define ER_DZ_TX_PIOBUF_OFST 0x00001000
|
||||
#endif
|
||||
#ifndef ER_DZ_TX_PIOBUF_STEP
|
||||
#define ER_DZ_TX_PIOBUF_STEP 8192
|
||||
#endif
|
||||
#ifndef ER_DZ_TX_PIOBUF_ROWS
|
||||
#define ER_DZ_TX_PIOBUF_ROWS 2048
|
||||
#endif
|
||||
|
||||
#ifndef ER_DZ_TX_PIOBUF_SIZE
|
||||
#define ER_DZ_TX_PIOBUF_SIZE 2048
|
||||
#endif
|
||||
|
||||
#define HUNT_PIOBUF_NBUFS (16)
|
||||
#define HUNT_PIOBUF_SIZE (ER_DZ_TX_PIOBUF_SIZE)
|
||||
|
||||
#define HUNT_MIN_PIO_ALLOC_SIZE (HUNT_PIOBUF_SIZE / 32)
|
||||
|
||||
|
||||
/* NIC */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
hunt_board_cfg(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_HUNT_IMPL_H */
|
395
drivers/net/sfc/base/hunt_nic.c
Normal file
395
drivers/net/sfc/base/hunt_nic.c
Normal file
@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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 "efx.h"
|
||||
#include "efx_impl.h"
|
||||
|
||||
#if EFSYS_OPT_HUNTINGTON
|
||||
|
||||
#include "ef10_tlv_layout.h"
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
hunt_nic_get_required_pcie_bandwidth(
|
||||
__in efx_nic_t *enp,
|
||||
__out uint32_t *bandwidth_mbpsp)
|
||||
{
|
||||
uint32_t port_modes;
|
||||
uint32_t max_port_mode;
|
||||
uint32_t bandwidth;
|
||||
efx_rc_t rc;
|
||||
|
||||
/*
|
||||
* On Huntington, the firmware may not give us the current port mode, so
|
||||
* we need to go by the set of available port modes and assume the most
|
||||
* capable mode is in use.
|
||||
*/
|
||||
|
||||
if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, NULL)) != 0) {
|
||||
/* No port mode info available */
|
||||
bandwidth = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (port_modes & (1 << TLV_PORT_MODE_40G_40G)) {
|
||||
/*
|
||||
* This needs the full PCIe bandwidth (and could use
|
||||
* more) - roughly 64 Gbit/s for 8 lanes of Gen3.
|
||||
*/
|
||||
if ((rc = efx_nic_calculate_pcie_link_bandwidth(8,
|
||||
EFX_PCIE_LINK_SPEED_GEN3, &bandwidth)) != 0)
|
||||
goto fail1;
|
||||
} else {
|
||||
if (port_modes & (1 << TLV_PORT_MODE_40G)) {
|
||||
max_port_mode = TLV_PORT_MODE_40G;
|
||||
} else if (port_modes & (1 << TLV_PORT_MODE_10G_10G_10G_10G)) {
|
||||
max_port_mode = TLV_PORT_MODE_10G_10G_10G_10G;
|
||||
} else {
|
||||
/* Assume two 10G ports */
|
||||
max_port_mode = TLV_PORT_MODE_10G_10G;
|
||||
}
|
||||
|
||||
if ((rc = ef10_nic_get_port_mode_bandwidth(max_port_mode,
|
||||
&bandwidth)) != 0)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
out:
|
||||
*bandwidth_mbpsp = bandwidth;
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
hunt_board_cfg(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
uint8_t mac_addr[6] = { 0 };
|
||||
uint32_t board_type = 0;
|
||||
ef10_link_state_t els;
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
uint32_t port;
|
||||
uint32_t pf;
|
||||
uint32_t vf;
|
||||
uint32_t mask;
|
||||
uint32_t flags;
|
||||
uint32_t sysclk, dpcpu_clk;
|
||||
uint32_t base, nvec;
|
||||
uint32_t bandwidth;
|
||||
efx_rc_t rc;
|
||||
|
||||
if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
|
||||
goto fail1;
|
||||
|
||||
/*
|
||||
* NOTE: The MCDI protocol numbers ports from zero.
|
||||
* The common code MCDI interface numbers ports from one.
|
||||
*/
|
||||
emip->emi_port = port + 1;
|
||||
|
||||
if ((rc = ef10_external_port_mapping(enp, port,
|
||||
&encp->enc_external_port)) != 0)
|
||||
goto fail2;
|
||||
|
||||
/*
|
||||
* Get PCIe function number from firmware (used for
|
||||
* per-function privilege and dynamic config info).
|
||||
* - PCIe PF: pf = PF number, vf = 0xffff.
|
||||
* - PCIe VF: pf = parent PF, vf = VF number.
|
||||
*/
|
||||
if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
|
||||
goto fail3;
|
||||
|
||||
encp->enc_pf = pf;
|
||||
encp->enc_vf = vf;
|
||||
|
||||
/* MAC address for this function */
|
||||
if (EFX_PCI_FUNCTION_IS_PF(encp)) {
|
||||
rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
|
||||
if ((rc == 0) && (mac_addr[0] & 0x02)) {
|
||||
/*
|
||||
* If the static config does not include a global MAC
|
||||
* address pool then the board may return a locally
|
||||
* administered MAC address (this should only happen on
|
||||
* incorrectly programmed boards).
|
||||
*/
|
||||
rc = EINVAL;
|
||||
}
|
||||
} else {
|
||||
rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
|
||||
}
|
||||
if (rc != 0)
|
||||
goto fail4;
|
||||
|
||||
EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
|
||||
|
||||
/* Board configuration */
|
||||
rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
|
||||
if (rc != 0) {
|
||||
/* Unprivileged functions may not be able to read board cfg */
|
||||
if (rc == EACCES)
|
||||
board_type = 0;
|
||||
else
|
||||
goto fail5;
|
||||
}
|
||||
|
||||
encp->enc_board_type = board_type;
|
||||
encp->enc_clk_mult = 1; /* not used for Huntington */
|
||||
|
||||
/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
|
||||
if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
|
||||
goto fail6;
|
||||
|
||||
/* Obtain the default PHY advertised capabilities */
|
||||
if ((rc = ef10_phy_get_link(enp, &els)) != 0)
|
||||
goto fail7;
|
||||
epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
|
||||
epp->ep_adv_cap_mask = els.els_adv_cap_mask;
|
||||
|
||||
/*
|
||||
* Enable firmware workarounds for hardware errata.
|
||||
* Expected responses are:
|
||||
* - 0 (zero):
|
||||
* Success: workaround enabled or disabled as requested.
|
||||
* - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
|
||||
* Firmware does not support the MC_CMD_WORKAROUND request.
|
||||
* (assume that the workaround is not supported).
|
||||
* - MC_CMD_ERR_ENOENT (reported as ENOENT):
|
||||
* Firmware does not support the requested workaround.
|
||||
* - MC_CMD_ERR_EPERM (reported as EACCES):
|
||||
* Unprivileged function cannot enable/disable workarounds.
|
||||
*
|
||||
* See efx_mcdi_request_errcode() for MCDI error translations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If the bug35388 workaround is enabled, then use an indirect access
|
||||
* method to avoid unsafe EVQ writes.
|
||||
*/
|
||||
rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE,
|
||||
NULL);
|
||||
if ((rc == 0) || (rc == EACCES))
|
||||
encp->enc_bug35388_workaround = B_TRUE;
|
||||
else if ((rc == ENOTSUP) || (rc == ENOENT))
|
||||
encp->enc_bug35388_workaround = B_FALSE;
|
||||
else
|
||||
goto fail8;
|
||||
|
||||
/*
|
||||
* If the bug41750 workaround is enabled, then do not test interrupts,
|
||||
* as the test will fail (seen with Greenport controllers).
|
||||
*/
|
||||
rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE,
|
||||
NULL);
|
||||
if (rc == 0) {
|
||||
encp->enc_bug41750_workaround = B_TRUE;
|
||||
} else if (rc == EACCES) {
|
||||
/* Assume a controller with 40G ports needs the workaround. */
|
||||
if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX)
|
||||
encp->enc_bug41750_workaround = B_TRUE;
|
||||
else
|
||||
encp->enc_bug41750_workaround = B_FALSE;
|
||||
} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
|
||||
encp->enc_bug41750_workaround = B_FALSE;
|
||||
} else {
|
||||
goto fail9;
|
||||
}
|
||||
if (EFX_PCI_FUNCTION_IS_VF(encp)) {
|
||||
/* Interrupt testing does not work for VFs. See bug50084. */
|
||||
encp->enc_bug41750_workaround = B_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the bug26807 workaround is enabled, then firmware has enabled
|
||||
* support for chained multicast filters. Firmware will reset (FLR)
|
||||
* functions which have filters in the hardware filter table when the
|
||||
* workaround is enabled/disabled.
|
||||
*
|
||||
* We must recheck if the workaround is enabled after inserting the
|
||||
* first hardware filter, in case it has been changed since this check.
|
||||
*/
|
||||
rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
|
||||
B_TRUE, &flags);
|
||||
if (rc == 0) {
|
||||
encp->enc_bug26807_workaround = B_TRUE;
|
||||
if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
|
||||
/*
|
||||
* Other functions had installed filters before the
|
||||
* workaround was enabled, and they have been reset
|
||||
* by firmware.
|
||||
*/
|
||||
EFSYS_PROBE(bug26807_workaround_flr_done);
|
||||
/* FIXME: bump MC warm boot count ? */
|
||||
}
|
||||
} else if (rc == EACCES) {
|
||||
/*
|
||||
* Unprivileged functions cannot enable the workaround in older
|
||||
* firmware.
|
||||
*/
|
||||
encp->enc_bug26807_workaround = B_FALSE;
|
||||
} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
|
||||
encp->enc_bug26807_workaround = B_FALSE;
|
||||
} else {
|
||||
goto fail10;
|
||||
}
|
||||
|
||||
/* Get clock frequencies (in MHz). */
|
||||
if ((rc = efx_mcdi_get_clock(enp, &sysclk, &dpcpu_clk)) != 0)
|
||||
goto fail11;
|
||||
|
||||
/*
|
||||
* The Huntington timer quantum is 1536 sysclk cycles, documented for
|
||||
* the EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
|
||||
*/
|
||||
encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
|
||||
if (encp->enc_bug35388_workaround) {
|
||||
encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
|
||||
ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000;
|
||||
} else {
|
||||
encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
|
||||
FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
|
||||
}
|
||||
|
||||
encp->enc_bug61265_workaround = B_FALSE; /* Medford only */
|
||||
|
||||
/* Check capabilities of running datapath firmware */
|
||||
if ((rc = ef10_get_datapath_caps(enp)) != 0)
|
||||
goto fail12;
|
||||
|
||||
/* Alignment for receive packet DMA buffers */
|
||||
encp->enc_rx_buf_align_start = 1;
|
||||
encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */
|
||||
|
||||
/* Alignment for WPTR updates */
|
||||
encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
|
||||
|
||||
/*
|
||||
* Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
|
||||
* MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
|
||||
* resources (allocated to this PCIe function), which is zero until
|
||||
* after we have allocated VIs.
|
||||
*/
|
||||
encp->enc_evq_limit = 1024;
|
||||
encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
|
||||
encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
|
||||
|
||||
/*
|
||||
* The workaround for bug35388 uses the top bit of transmit queue
|
||||
* descriptor writes, preventing the use of 4096 descriptor TXQs.
|
||||
*/
|
||||
encp->enc_txq_max_ndescs = encp->enc_bug35388_workaround ? 2048 : 4096;
|
||||
|
||||
encp->enc_buftbl_limit = 0xFFFFFFFF;
|
||||
|
||||
encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS;
|
||||
encp->enc_piobuf_size = HUNT_PIOBUF_SIZE;
|
||||
encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE;
|
||||
|
||||
/*
|
||||
* Get the current privilege mask. Note that this may be modified
|
||||
* dynamically, so this value is informational only. DO NOT use
|
||||
* the privilege mask to check for sufficient privileges, as that
|
||||
* can result in time-of-check/time-of-use bugs.
|
||||
*/
|
||||
if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
|
||||
goto fail13;
|
||||
encp->enc_privilege_mask = mask;
|
||||
|
||||
/* Get interrupt vector limits */
|
||||
if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
|
||||
if (EFX_PCI_FUNCTION_IS_PF(encp))
|
||||
goto fail14;
|
||||
|
||||
/* Ignore error (cannot query vector limits from a VF). */
|
||||
base = 0;
|
||||
nvec = 1024;
|
||||
}
|
||||
encp->enc_intr_vec_base = base;
|
||||
encp->enc_intr_limit = nvec;
|
||||
|
||||
/*
|
||||
* Maximum number of bytes into the frame the TCP header can start for
|
||||
* firmware assisted TSO to work.
|
||||
*/
|
||||
encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
|
||||
|
||||
if ((rc = hunt_nic_get_required_pcie_bandwidth(enp, &bandwidth)) != 0)
|
||||
goto fail15;
|
||||
encp->enc_required_pcie_bandwidth_mbps = bandwidth;
|
||||
|
||||
/* All Huntington devices have a PCIe Gen3, 8 lane connector */
|
||||
encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
|
||||
|
||||
return (0);
|
||||
|
||||
fail15:
|
||||
EFSYS_PROBE(fail15);
|
||||
fail14:
|
||||
EFSYS_PROBE(fail14);
|
||||
fail13:
|
||||
EFSYS_PROBE(fail13);
|
||||
fail12:
|
||||
EFSYS_PROBE(fail12);
|
||||
fail11:
|
||||
EFSYS_PROBE(fail11);
|
||||
fail10:
|
||||
EFSYS_PROBE(fail10);
|
||||
fail9:
|
||||
EFSYS_PROBE(fail9);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
Loading…
Reference in New Issue
Block a user