/* * aQuantia Corporation Network Driver * Copyright (C) 2014-2017 aQuantia Corporation. 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. * * (3)The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. */ #ifndef _AQ_HW_H_ #define _AQ_HW_H_ #include #include #include #include #include #include "aq_common.h" #define AQ_WRITE_REG(hw, reg, value) writel(((hw)->hw_addr + (reg)), htole32(value)) #define AQ_READ_REG(hw, reg) le32toh(readl((hw)->hw_addr + reg)) #define AQ_WRITE_REG_BIT(hw, reg, msk, shift, value) do { \ if (msk ^ ~0) { \ uint32_t reg_old, reg_new = 0U; \ reg_old = AQ_READ_REG(hw, reg); \ reg_new = (reg_old & (~msk)) | (value << shift); \ if (reg_old != reg_new) \ AQ_WRITE_REG(hw, reg, reg_new); \ } else { \ AQ_WRITE_REG(hw, reg, value); \ } \ } while(0) #define AQ_READ_REG_BIT(a, reg, msk, shift) ( \ ((AQ_READ_REG(a, reg) & msk) >> shift)) #define AQ_HW_FLUSH() { (void)AQ_READ_REG(hw, 0x10); } #define aq_hw_write_reg_bit AQ_WRITE_REG_BIT #define aq_hw_write_reg AQ_WRITE_REG /* Statistics */ struct aq_hw_stats { uint64_t crcerrs; }; struct aq_hw_stats_s { uint32_t uprc; uint32_t mprc; uint32_t bprc; uint32_t erpt; uint32_t uptc; uint32_t mptc; uint32_t bptc; uint32_t erpr; uint32_t mbtc; uint32_t bbtc; uint32_t mbrc; uint32_t bbrc; uint32_t ubrc; uint32_t ubtc; uint32_t ptc; uint32_t prc; uint32_t dpc; uint32_t cprc; } __attribute__((__packed__)); union ip_addr { struct { uint8_t addr[16]; } v6; struct { uint8_t padding[12]; uint8_t addr[4]; } v4; } __attribute__((__packed__)); struct aq_hw_fw_mbox { uint32_t version; uint32_t transaction_id; int error; struct aq_hw_stats_s stats; } __attribute__((__packed__)); typedef struct aq_hw_fw_version { union { struct { uint16_t build_number; uint8_t minor_version; uint8_t major_version; }; uint32_t raw; }; } aq_hw_fw_version; enum aq_hw_irq_type { aq_irq_invalid = 0, aq_irq_legacy = 1, aq_irq_msi = 2, aq_irq_msix = 3, }; struct aq_hw_fc_info { bool fc_rx; bool fc_tx; }; struct aq_hw { void *aq_dev; uint8_t *hw_addr; uint32_t regs_size; uint8_t mac_addr[ETHER_ADDR_LEN]; enum aq_hw_irq_type irq_type; struct aq_hw_fc_info fc; uint16_t link_rate; uint16_t device_id; uint16_t subsystem_vendor_id; uint16_t subsystem_device_id; uint16_t vendor_id; uint8_t revision_id; /* Interrupt Moderation value. */ int itr; /* Firmware-related stuff. */ aq_hw_fw_version fw_version; const struct aq_firmware_ops* fw_ops; bool rbl_enabled; bool fast_start_enabled; bool flash_present; uint32_t chip_features; uint64_t fw_caps; bool lro_enabled; uint32_t mbox_addr; struct aq_hw_fw_mbox mbox; }; #define aq_hw_s aq_hw #define AQ_HW_MAC 0U #define AQ_HW_MAC_MIN 1U #define AQ_HW_MAC_MAX 33U #define HW_ATL_B0_MIN_RXD 32U #define HW_ATL_B0_MIN_TXD 32U #define HW_ATL_B0_MAX_RXD 4096U /* in fact up to 8184, but closest to power of 2 */ #define HW_ATL_B0_MAX_TXD 4096U /* in fact up to 8184, but closest to power of 2 */ #define HW_ATL_B0_MTU_JUMBO 16352U #define HW_ATL_B0_TSO_SIZE (160*1024) #define HW_ATL_B0_RINGS_MAX 32U #define HW_ATL_B0_LRO_RXD_MAX 16U #define AQ_HW_FW_SM_RAM 0x2U #define AQ_HW_MPI_STATE_MSK 0x00FFU #define AQ_HW_MPI_STATE_SHIFT 0U #define AQ_HW_MPI_CONTROL_ADR 0x0368U #define AQ_HW_MPI_STATE_ADR 0x036CU #define HW_ATL_RSS_INDIRECTION_TABLE_MAX 64U #define HW_ATL_RSS_HASHKEY_SIZE 40U /* PCI core control register */ #define AQ_HW_PCI_REG_CONTROL_6_ADR 0x1014U /* tx dma total request limit */ #define AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_ADR 0x00007b20U #define AQ_HW_TXBUF_MAX 160U #define AQ_HW_RXBUF_MAX 320U #define L2_FILTER_ACTION_DISCARD (0x0) #define L2_FILTER_ACTION_HOST (0x1) #define AQ_HW_UCP_0X370_REG (0x370) #define AQ_HW_CHIP_MIPS 0x00000001U #define AQ_HW_CHIP_TPO2 0x00000002U #define AQ_HW_CHIP_RPF2 0x00000004U #define AQ_HW_CHIP_MPI_AQ 0x00000010U #define AQ_HW_CHIP_REVISION_A0 0x01000000U #define AQ_HW_CHIP_REVISION_B0 0x02000000U #define AQ_HW_CHIP_REVISION_B1 0x04000000U #define IS_CHIP_FEATURE(HW, _F_) (AQ_HW_CHIP_##_F_ & \ (HW)->chip_features) #define AQ_HW_FW_VER_EXPECTED 0x01050006U #define AQ_RX_RSS_TYPE_NONE 0x0 #define AQ_RX_RSS_TYPE_IPV4 0x2 #define AQ_RX_RSS_TYPE_IPV6 0x3 #define AQ_RX_RSS_TYPE_IPV4_TCP 0x4 #define AQ_RX_RSS_TYPE_IPV6_TCP 0x5 #define AQ_RX_RSS_TYPE_IPV4_UDP 0x6 #define AQ_RX_RSS_TYPE_IPV6_UDP 0x7 enum hw_atl_rx_action_with_traffic { HW_ATL_RX_DISCARD, HW_ATL_RX_HOST, HW_ATL_RX_MNGMNT, HW_ATL_RX_HOST_AND_MNGMNT, HW_ATL_RX_WOL }; struct aq_rx_filter_vlan { uint8_t enable; uint8_t location; uint16_t vlan_id; uint8_t queue; }; #define AQ_HW_VLAN_MAX_FILTERS 16U #define AQ_HW_ETYPE_MAX_FILTERS 16U struct aq_rx_filter_l2 { uint8_t enable; int8_t queue; uint8_t location; uint8_t user_priority_en; uint8_t user_priority; uint16_t ethertype; }; enum hw_atl_rx_ctrl_registers_l2 { HW_ATL_RX_ENABLE_UNICAST_MNGNT_QUEUE_L2 = BIT(19), HW_ATL_RX_ENABLE_UNICAST_FLTR_L2 = BIT(31) }; struct aq_rx_filter_l3l4 { uint32_t cmd; uint8_t location; uint32_t ip_dst[4]; uint32_t ip_src[4]; uint16_t p_dst; uint16_t p_src; bool is_ipv6; }; enum hw_atl_rx_protocol_value_l3l4 { HW_ATL_RX_TCP, HW_ATL_RX_UDP, HW_ATL_RX_SCTP, HW_ATL_RX_ICMP }; enum hw_atl_rx_ctrl_registers_l3l4 { HW_ATL_RX_ENABLE_MNGMNT_QUEUE_L3L4 = BIT(22), HW_ATL_RX_ENABLE_QUEUE_L3L4 = BIT(23), HW_ATL_RX_ENABLE_ARP_FLTR_L3 = BIT(24), HW_ATL_RX_ENABLE_CMP_PROT_L4 = BIT(25), HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 = BIT(26), HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4 = BIT(27), HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3 = BIT(28), HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3 = BIT(29), HW_ATL_RX_ENABLE_L3_IPv6 = BIT(30), HW_ATL_RX_ENABLE_FLTR_L3L4 = BIT(31) }; #define HW_ATL_RX_BOFFSET_PROT_FL3L4 0U #define HW_ATL_RX_BOFFSET_QUEUE_FL3L4 8U #define HW_ATL_RX_BOFFSET_ACTION_FL3F4 16U #define HW_ATL_RX_CNT_REG_ADDR_IPV6 4U #define HW_ATL_GET_REG_LOCATION_FL3L4(location) \ ((location) - AQ_RX_FIRST_LOC_FL3L4) enum aq_hw_fw_mpi_state_e { MPI_DEINIT = 0, MPI_RESET = 1, MPI_INIT = 2, MPI_POWER = 4, }; int aq_hw_get_mac_permanent(struct aq_hw *hw, uint8_t *mac); int aq_hw_mac_addr_set(struct aq_hw *hw, uint8_t *mac_addr, uint8_t index); /* link speed in mbps. "0" - no link detected */ int aq_hw_get_link_state(struct aq_hw *hw, uint32_t *link_speed, struct aq_hw_fc_info *fc_neg); int aq_hw_set_link_speed(struct aq_hw *hw, uint32_t speed); int aq_hw_fw_downld_dwords(struct aq_hw *hw, uint32_t a, uint32_t *p, uint32_t cnt); int aq_hw_reset(struct aq_hw *hw); int aq_hw_mpi_create(struct aq_hw *hw); int aq_hw_mpi_read_stats(struct aq_hw *hw, struct aq_hw_fw_mbox *pmbox); int aq_hw_init(struct aq_hw *hw, uint8_t *mac_addr, uint8_t adm_irq, bool msix); int aq_hw_start(struct aq_hw *hw); int aq_hw_interrupt_moderation_set(struct aq_hw *hw); int aq_hw_get_fw_version(struct aq_hw *hw, uint32_t *fw_version); int aq_hw_deinit(struct aq_hw *hw); int aq_hw_ver_match(const aq_hw_fw_version* ver_expected, const aq_hw_fw_version* ver_actual); void aq_hw_set_promisc(struct aq_hw_s *self, bool l2_promisc, bool vlan_promisc, bool mc_promisc); int aq_hw_set_power(struct aq_hw *hw, unsigned int power_state); int aq_hw_err_from_flags(struct aq_hw *hw); int hw_atl_b0_hw_vlan_promisc_set(struct aq_hw_s *self, bool promisc); int hw_atl_b0_hw_vlan_set(struct aq_hw_s *self, struct aq_rx_filter_vlan *aq_vlans); int aq_hw_rss_hash_set(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]); int aq_hw_rss_hash_get(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]); int aq_hw_rss_set(struct aq_hw_s *self, uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX]); int aq_hw_udp_rss_enable(struct aq_hw_s *self, bool enable); #endif // _AQ_HW_H_