/* * 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_RING_H_ #define _AQ_RING_H_ #include "aq_hw.h" #define REFILL_THRESHOLD 128 typedef volatile struct { uint32_t rss_type:4; uint32_t pkt_type:8; uint32_t rdm_err:1; uint32_t rsvd:6; uint32_t rx_cntl:2; uint32_t sph:1; uint32_t hdr_len:10; uint32_t rss_hash; uint16_t dd:1; uint16_t eop:1; uint16_t rx_stat:4; uint16_t rx_estat:6; uint16_t rsc_cnt:4; uint16_t pkt_len; uint16_t next_desp; uint16_t vlan; } __attribute__((__packed__)) aq_rx_wb_t; typedef volatile struct { union { /* HW RX descriptor */ struct __packed { uint64_t buf_addr; uint64_t hdr_addr; } read; /* HW RX descriptor writeback */ aq_rx_wb_t wb; }; } __attribute__((__packed__)) aq_rx_desc_t; /* Hardware tx descriptor */ typedef volatile struct { uint64_t buf_addr; union { struct { uint32_t type:3; uint32_t :1; uint32_t len:16; uint32_t dd:1; uint32_t eop:1; uint32_t cmd:8; uint32_t :14; uint32_t ct_idx:1; uint32_t ct_en:1; uint32_t pay_len:18; } __attribute__((__packed__)); uint64_t flags; }; } __attribute__((__packed__)) aq_tx_desc_t; enum aq_tx_desc_type { tx_desc_type_desc = 1, tx_desc_type_ctx = 2, }; enum aq_tx_desc_cmd { tx_desc_cmd_vlan = 1, tx_desc_cmd_fcs = 2, tx_desc_cmd_ipv4 = 4, tx_desc_cmd_l4cs = 8, tx_desc_cmd_lso = 0x10, tx_desc_cmd_wb = 0x20, }; /* Hardware tx context descriptor */ typedef volatile union { struct __packed { uint64_t flags1; uint64_t flags2; }; struct __packed { uint64_t :40; uint32_t tun_len:8; uint32_t out_len:16; uint32_t type:3; uint32_t idx:1; uint32_t vlan_tag:16; uint32_t cmd:4; uint32_t l2_len:7; uint32_t l3_len:9; uint32_t l4_len:8; uint32_t mss_len:16; }; } __attribute__((__packed__)) aq_txc_desc_t; struct aq_ring_stats { uint64_t rx_pkts; uint64_t rx_bytes; uint64_t jumbo_pkts; uint64_t rx_err; uint64_t irq; uint64_t tx_pkts; uint64_t tx_bytes; uint64_t tx_drops; uint64_t tx_queue_full; }; struct aq_dev; struct aq_ring { struct aq_dev *dev; int index; struct if_irq irq; int msix; /* RX */ qidx_t rx_size; int rx_max_frame_size; void *rx_desc_area_ptr; aq_rx_desc_t *rx_descs; uint64_t rx_descs_phys; /* TX */ int tx_head, tx_tail; qidx_t tx_size; void *tx_desc_area_ptr; aq_tx_desc_t *tx_descs; uint64_t tx_descs_phys; struct aq_ring_stats stats; }; int aq_ring_rx_init(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_tx_init(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_tx_start(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_tx_stop(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_rx_start(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_rx_stop(struct aq_hw *hw, struct aq_ring *ring); int aq_ring_tx_tail_update(struct aq_hw *hw, struct aq_ring *ring, uint32_t tail); extern struct if_txrx aq_txrx; int aq_intr(void *arg); #endif /* _AQ_RING_H_ */