ec78fa7f7f
Obtained from: Semihalf Submitted by: Michal Stanek <mst@semihalf.com> Sponsored by: Annapurna Labs Reviewed by: wma Differential Revision: https://reviews.freebsd.org/D7814
367 lines
10 KiB
C
367 lines
10 KiB
C
/*-
|
|
* Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
|
|
* All rights reserved.
|
|
*
|
|
* Developed by Semihalf.
|
|
*
|
|
* 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 AUTHOR 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 AUTHOR 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.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef __AL_ETH_H__
|
|
#define __AL_ETH_H__
|
|
|
|
#include "al_init_eth_lm.h"
|
|
#include "al_hal_eth.h"
|
|
#include "al_hal_udma_iofic.h"
|
|
#include "al_hal_udma_debug.h"
|
|
#include "al_serdes.h"
|
|
|
|
enum board_t {
|
|
ALPINE_INTEGRATED = 0,
|
|
ALPINE_NIC = 1,
|
|
ALPINE_FPGA_NIC = 2,
|
|
};
|
|
|
|
#define AL_ETH_MAX_HW_QUEUES 4
|
|
#define AL_ETH_NUM_QUEUES 4
|
|
#define AL_ETH_MAX_MSIX_VEC (1 + 2 * AL_ETH_MAX_HW_QUEUES)
|
|
|
|
#define AL_ETH_DEFAULT_TX_SW_DESCS (512)
|
|
#define AL_ETH_DEFAULT_TX_HW_DESCS (512)
|
|
#define AL_ETH_DEFAULT_RX_DESCS (512)
|
|
|
|
#if ((AL_ETH_DEFAULT_TX_SW_DESCS / 4) < (AL_ETH_PKT_MAX_BUFS + 2))
|
|
#define AL_ETH_TX_WAKEUP_THRESH (AL_ETH_DEFAULT_TX_SW_DESCS / 4)
|
|
#else
|
|
#define AL_ETH_TX_WAKEUP_THRESH (AL_ETH_PKT_MAX_BUFS + 2)
|
|
#endif
|
|
|
|
#define NET_IP_ALIGN 2
|
|
#define AL_ETH_DEFAULT_SMALL_PACKET_LEN (128 - NET_IP_ALIGN)
|
|
#define AL_ETH_HEADER_COPY_SIZE (128 - NET_IP_ALIGN)
|
|
|
|
#define AL_ETH_DEFAULT_MAX_RX_BUFF_ALLOC_SIZE 9216
|
|
/*
|
|
* Minimum the buffer size to 600 to avoid situation the mtu will be changed
|
|
* from too little buffer to very big one and then the number of buffer per
|
|
* packet could reach the maximum AL_ETH_PKT_MAX_BUFS
|
|
*/
|
|
#define AL_ETH_DEFAULT_MIN_RX_BUFF_ALLOC_SIZE 600
|
|
#define AL_ETH_DEFAULT_FORCE_1000_BASEX FALSE
|
|
|
|
#define AL_ETH_DEFAULT_LINK_POLL_INTERVAL 100
|
|
#define AL_ETH_FIRST_LINK_POLL_INTERVAL 1
|
|
|
|
#define AL_ETH_NAME_MAX_LEN 20
|
|
#define AL_ETH_IRQNAME_SIZE 40
|
|
|
|
#define AL_ETH_DEFAULT_MDIO_FREQ_KHZ 2500
|
|
#define AL_ETH_MDIO_FREQ_1000_KHZ 1000
|
|
|
|
struct al_eth_irq {
|
|
driver_filter_t *handler;
|
|
void *data;
|
|
unsigned int vector;
|
|
uint8_t requested;
|
|
char name[AL_ETH_IRQNAME_SIZE];
|
|
struct resource *res;
|
|
void *cookie;
|
|
};
|
|
|
|
struct al_eth_tx_buffer {
|
|
struct mbuf *m;
|
|
struct al_eth_pkt hal_pkt;
|
|
bus_dmamap_t dma_map;
|
|
unsigned int tx_descs;
|
|
};
|
|
|
|
struct al_eth_rx_buffer {
|
|
struct mbuf *m;
|
|
unsigned int data_size;
|
|
bus_dmamap_t dma_map;
|
|
struct al_buf al_buf;
|
|
};
|
|
|
|
struct al_eth_ring {
|
|
device_t dev;
|
|
struct al_eth_adapter *adapter;
|
|
/* Used to get rx packets from hal */
|
|
struct al_eth_pkt hal_pkt;
|
|
/* Udma queue handler */
|
|
struct al_udma_q *dma_q;
|
|
uint32_t ring_id;
|
|
uint16_t next_to_use;
|
|
uint16_t next_to_clean;
|
|
/* The offset of the interrupt unmask register */
|
|
uint32_t *unmask_reg_offset;
|
|
/*
|
|
* The value to write to the above register to
|
|
* unmask the interrupt of this ring
|
|
*/
|
|
uint32_t unmask_val;
|
|
struct al_eth_meta_data hal_meta;
|
|
/* Contex of tx packet */
|
|
struct al_eth_tx_buffer *tx_buffer_info;
|
|
/* Contex of rx packet */
|
|
struct al_eth_rx_buffer *rx_buffer_info;
|
|
/* Number of tx/rx_buffer_info's entries */
|
|
int sw_count;
|
|
/* Number of hw descriptors */
|
|
int hw_count;
|
|
/* Size (in bytes) of hw descriptors */
|
|
size_t descs_size;
|
|
/* Size (in bytes) of hw completion descriptors, used for rx */
|
|
size_t cdescs_size;
|
|
struct ifnet *netdev;
|
|
struct al_udma_q_params q_params;
|
|
struct buf_ring *br;
|
|
struct mtx br_mtx;
|
|
struct task enqueue_task;
|
|
struct taskqueue *enqueue_tq;
|
|
volatile uint32_t enqueue_is_running;
|
|
struct task cmpl_task;
|
|
struct taskqueue *cmpl_tq;
|
|
volatile uint32_t cmpl_is_running;
|
|
uint32_t lro_enabled;
|
|
struct lro_ctrl lro;
|
|
bus_dma_tag_t dma_buf_tag;
|
|
volatile uint32_t stall;
|
|
};
|
|
|
|
#define AL_ETH_TX_RING_IDX_NEXT(tx_ring, idx) (((idx) + 1) & (AL_ETH_DEFAULT_TX_SW_DESCS - 1))
|
|
|
|
#define AL_ETH_RX_RING_IDX_NEXT(rx_ring, idx) (((idx) + 1) & (AL_ETH_DEFAULT_RX_DESCS - 1))
|
|
#define AL_ETH_RX_RING_IDX_ADD(rx_ring, idx, n) (((idx) + (n)) & (AL_ETH_DEFAULT_RX_DESCS - 1))
|
|
|
|
/* flow control configuration */
|
|
#define AL_ETH_FLOW_CTRL_RX_FIFO_TH_HIGH 0x160
|
|
#define AL_ETH_FLOW_CTRL_RX_FIFO_TH_LOW 0x90
|
|
#define AL_ETH_FLOW_CTRL_QUANTA 0xffff
|
|
#define AL_ETH_FLOW_CTRL_QUANTA_TH 0x8000
|
|
|
|
#define AL_ETH_FLOW_CTRL_AUTONEG 1
|
|
#define AL_ETH_FLOW_CTRL_RX_PAUSE 2
|
|
#define AL_ETH_FLOW_CTRL_TX_PAUSE 4
|
|
|
|
/* link configuration for 1G port */
|
|
struct al_eth_link_config {
|
|
int old_link;
|
|
/* Describes what we actually have. */
|
|
int active_duplex;
|
|
int active_speed;
|
|
|
|
/* current flow control status */
|
|
uint8_t flow_ctrl_active;
|
|
/* supported configuration (can be changed from ethtool) */
|
|
uint8_t flow_ctrl_supported;
|
|
|
|
/* the following are not relevant to RGMII */
|
|
boolean_t force_1000_base_x;
|
|
boolean_t autoneg;
|
|
};
|
|
|
|
/* SFP detection event */
|
|
enum al_eth_sfp_detect_evt {
|
|
/* No change (no connect, disconnect, or new SFP module */
|
|
AL_ETH_SFP_DETECT_EVT_NO_CHANGE,
|
|
/* SFP module connected */
|
|
AL_ETH_SFP_DETECT_EVT_CONNECTED,
|
|
/* SFP module disconnected */
|
|
AL_ETH_SFP_DETECT_EVT_DISCONNECTED,
|
|
/* SFP module replaced */
|
|
AL_ETH_SFP_DETECT_EVT_CHANGED,
|
|
};
|
|
|
|
/* SFP detection status */
|
|
struct al_eth_sfp_detect_stat {
|
|
/* Status is valid (i.e. rest of fields are valid) */
|
|
boolean_t valid;
|
|
boolean_t connected;
|
|
uint8_t sfp_10g;
|
|
uint8_t sfp_1g;
|
|
uint8_t sfp_cable_tech;
|
|
boolean_t lt_en;
|
|
boolean_t an_en;
|
|
enum al_eth_mac_mode mac_mode;
|
|
};
|
|
|
|
struct al_eth_retimer_params {
|
|
boolean_t exist;
|
|
uint8_t bus_id;
|
|
uint8_t i2c_addr;
|
|
enum al_eth_retimer_channel channel;
|
|
};
|
|
|
|
struct msix_entry {
|
|
int entry;
|
|
int vector;
|
|
};
|
|
|
|
/* board specific private data structure */
|
|
struct al_eth_adapter {
|
|
enum board_t board_type;
|
|
device_t miibus;
|
|
struct mii_data *mii;
|
|
uint16_t dev_id;
|
|
uint8_t rev_id;
|
|
|
|
device_t dev;
|
|
struct ifnet *netdev;
|
|
struct ifmedia media;
|
|
struct resource *udma_res;
|
|
struct resource *mac_res;
|
|
struct resource *ec_res;
|
|
int if_flags;
|
|
struct callout wd_callout;
|
|
struct mtx wd_mtx;
|
|
struct callout stats_callout;
|
|
struct mtx stats_mtx;
|
|
|
|
/* this is for intx mode */
|
|
void *irq_cookie;
|
|
struct resource *irq_res;
|
|
|
|
/*
|
|
* Some features need tri-state capability,
|
|
* thus the additional *_CAPABLE flags.
|
|
*/
|
|
uint32_t flags;
|
|
#define AL_ETH_FLAG_MSIX_CAPABLE (uint32_t)(1 << 1)
|
|
#define AL_ETH_FLAG_MSIX_ENABLED (uint32_t)(1 << 2)
|
|
#define AL_ETH_FLAG_IN_NETPOLL (uint32_t)(1 << 3)
|
|
#define AL_ETH_FLAG_MQ_CAPABLE (uint32_t)(1 << 4)
|
|
#define AL_ETH_FLAG_SRIOV_CAPABLE (uint32_t)(1 << 5)
|
|
#define AL_ETH_FLAG_SRIOV_ENABLED (uint32_t)(1 << 6)
|
|
#define AL_ETH_FLAG_RESET_REQUESTED (uint32_t)(1 << 7)
|
|
|
|
struct al_hal_eth_adapter hal_adapter;
|
|
|
|
/*
|
|
* Rx packets that shorter that this len will be copied to the mbuf
|
|
*/
|
|
unsigned int small_copy_len;
|
|
|
|
/* Maximum size for rx buffer */
|
|
unsigned int max_rx_buff_alloc_size;
|
|
uint32_t rx_mbuf_sz;
|
|
|
|
/* Tx fast path data */
|
|
int num_tx_queues;
|
|
|
|
/* Rx fast path data */
|
|
int num_rx_queues;
|
|
|
|
/* TX */
|
|
struct al_eth_ring tx_ring[AL_ETH_NUM_QUEUES];
|
|
|
|
/* RX */
|
|
struct al_eth_ring rx_ring[AL_ETH_NUM_QUEUES];
|
|
|
|
enum al_iofic_mode int_mode;
|
|
|
|
#define AL_ETH_MGMT_IRQ_IDX 0
|
|
#define AL_ETH_RXQ_IRQ_IDX(adapter, q) (1 + (q))
|
|
#define AL_ETH_TXQ_IRQ_IDX(adapter, q) (1 + (adapter)->num_rx_queues + (q))
|
|
struct al_eth_irq irq_tbl[AL_ETH_MAX_MSIX_VEC];
|
|
struct msix_entry *msix_entries;
|
|
int msix_vecs;
|
|
int irq_vecs;
|
|
|
|
unsigned int tx_usecs, rx_usecs; /* interrupt coalescing */
|
|
|
|
unsigned int tx_ring_count;
|
|
unsigned int tx_descs_count;
|
|
unsigned int rx_ring_count;
|
|
unsigned int rx_descs_count;
|
|
|
|
/* RSS */
|
|
uint32_t toeplitz_hash_key[AL_ETH_RX_HASH_KEY_NUM];
|
|
#define AL_ETH_RX_RSS_TABLE_SIZE AL_ETH_RX_THASH_TABLE_SIZE
|
|
uint8_t rss_ind_tbl[AL_ETH_RX_RSS_TABLE_SIZE];
|
|
|
|
uint32_t msg_enable;
|
|
struct al_eth_mac_stats mac_stats;
|
|
|
|
enum al_eth_mac_mode mac_mode;
|
|
boolean_t mac_mode_set; /* Relevant only when 'auto_speed' is set */
|
|
uint8_t mac_addr[ETHER_ADDR_LEN];
|
|
/* mdio and phy*/
|
|
boolean_t phy_exist;
|
|
struct mii_bus *mdio_bus;
|
|
struct phy_device *phydev;
|
|
uint8_t phy_addr;
|
|
struct al_eth_link_config link_config;
|
|
|
|
/* HAL layer data */
|
|
int id_number;
|
|
char name[AL_ETH_NAME_MAX_LEN];
|
|
void *internal_pcie_base; /* use for ALPINE_NIC devices */
|
|
void *udma_base;
|
|
void *ec_base;
|
|
void *mac_base;
|
|
|
|
struct al_eth_flow_control_params flow_ctrl_params;
|
|
|
|
struct al_eth_adapter_params eth_hal_params;
|
|
|
|
struct task link_status_task;
|
|
uint32_t link_poll_interval; /* task interval in mSec */
|
|
|
|
boolean_t serdes_init;
|
|
struct al_serdes_grp_obj serdes_obj;
|
|
uint8_t serdes_grp;
|
|
uint8_t serdes_lane;
|
|
|
|
boolean_t an_en; /* run kr auto-negotiation */
|
|
boolean_t lt_en; /* run kr link-training */
|
|
|
|
boolean_t sfp_detection_needed; /* true if need to run sfp detection */
|
|
boolean_t auto_speed; /* true if allowed to change SerDes speed configuration */
|
|
uint8_t i2c_adapter_id; /* identifier for the i2c adapter to use to access SFP+ module */
|
|
enum al_eth_ref_clk_freq ref_clk_freq; /* reference clock frequency */
|
|
unsigned int mdio_freq; /* MDIO frequency [Khz] */
|
|
|
|
boolean_t up;
|
|
|
|
boolean_t last_link;
|
|
boolean_t last_establish_failed;
|
|
struct al_eth_lm_context lm_context;
|
|
boolean_t use_lm;
|
|
|
|
boolean_t dont_override_serdes; /* avoid overriding serdes parameters
|
|
to preset static values */
|
|
struct mtx serdes_config_lock;
|
|
struct mtx if_rx_lock;
|
|
|
|
uint32_t wol;
|
|
|
|
struct al_eth_retimer_params retimer;
|
|
|
|
bool phy_fixup_needed;
|
|
|
|
enum al_eth_lm_max_speed max_speed;
|
|
};
|
|
|
|
#endif /* !(AL_ETH_H) */
|