145c98dacSZbigniew Bodek /*- 245c98dacSZbigniew Bodek * BSD LICENSE 345c98dacSZbigniew Bodek * 445c98dacSZbigniew Bodek * Copyright (c) 2015-2017 Amazon.com, Inc. or its affiliates. 545c98dacSZbigniew Bodek * All rights reserved. 645c98dacSZbigniew Bodek * 745c98dacSZbigniew Bodek * Redistribution and use in source and binary forms, with or without 845c98dacSZbigniew Bodek * modification, are permitted provided that the following conditions 945c98dacSZbigniew Bodek * are met: 1045c98dacSZbigniew Bodek * 1145c98dacSZbigniew Bodek * * Redistributions of source code must retain the above copyright 1245c98dacSZbigniew Bodek * notice, this list of conditions and the following disclaimer. 1345c98dacSZbigniew Bodek * * Redistributions in binary form must reproduce the above copyright 1445c98dacSZbigniew Bodek * notice, this list of conditions and the following disclaimer in 1545c98dacSZbigniew Bodek * the documentation and/or other materials provided with the 1645c98dacSZbigniew Bodek * distribution. 1745c98dacSZbigniew Bodek * * Neither the name of copyright holder nor the names of its 1845c98dacSZbigniew Bodek * contributors may be used to endorse or promote products derived 1945c98dacSZbigniew Bodek * from this software without specific prior written permission. 2045c98dacSZbigniew Bodek * 2145c98dacSZbigniew Bodek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2245c98dacSZbigniew Bodek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2345c98dacSZbigniew Bodek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2445c98dacSZbigniew Bodek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2545c98dacSZbigniew Bodek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2645c98dacSZbigniew Bodek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2745c98dacSZbigniew Bodek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2845c98dacSZbigniew Bodek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2945c98dacSZbigniew Bodek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3045c98dacSZbigniew Bodek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3145c98dacSZbigniew Bodek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3245c98dacSZbigniew Bodek */ 3345c98dacSZbigniew Bodek 3445c98dacSZbigniew Bodek #ifndef ENA_ETH_COM_H_ 3545c98dacSZbigniew Bodek #define ENA_ETH_COM_H_ 3645c98dacSZbigniew Bodek 3745c98dacSZbigniew Bodek #if defined(__cplusplus) 3845c98dacSZbigniew Bodek extern "C" { 3945c98dacSZbigniew Bodek #endif 4045c98dacSZbigniew Bodek #include "ena_com.h" 4145c98dacSZbigniew Bodek 4245c98dacSZbigniew Bodek /* head update threshold in units of (queue size / ENA_COMP_HEAD_THRESH) */ 4345c98dacSZbigniew Bodek #define ENA_COMP_HEAD_THRESH 4 4445c98dacSZbigniew Bodek 4545c98dacSZbigniew Bodek struct ena_com_tx_ctx { 4645c98dacSZbigniew Bodek struct ena_com_tx_meta ena_meta; 4745c98dacSZbigniew Bodek struct ena_com_buf *ena_bufs; 4845c98dacSZbigniew Bodek /* For LLQ, header buffer - pushed to the device mem space */ 4945c98dacSZbigniew Bodek void *push_header; 5045c98dacSZbigniew Bodek 5145c98dacSZbigniew Bodek enum ena_eth_io_l3_proto_index l3_proto; 5245c98dacSZbigniew Bodek enum ena_eth_io_l4_proto_index l4_proto; 5345c98dacSZbigniew Bodek u16 num_bufs; 5445c98dacSZbigniew Bodek u16 req_id; 5545c98dacSZbigniew Bodek /* For regular queue, indicate the size of the header 5645c98dacSZbigniew Bodek * For LLQ, indicate the size of the pushed buffer 5745c98dacSZbigniew Bodek */ 5845c98dacSZbigniew Bodek u16 header_len; 5945c98dacSZbigniew Bodek 6045c98dacSZbigniew Bodek u8 meta_valid; 6145c98dacSZbigniew Bodek u8 tso_enable; 6245c98dacSZbigniew Bodek u8 l3_csum_enable; 6345c98dacSZbigniew Bodek u8 l4_csum_enable; 6445c98dacSZbigniew Bodek u8 l4_csum_partial; 6545c98dacSZbigniew Bodek u8 df; /* Don't fragment */ 6645c98dacSZbigniew Bodek }; 6745c98dacSZbigniew Bodek 6845c98dacSZbigniew Bodek struct ena_com_rx_ctx { 6945c98dacSZbigniew Bodek struct ena_com_rx_buf_info *ena_bufs; 7045c98dacSZbigniew Bodek enum ena_eth_io_l3_proto_index l3_proto; 7145c98dacSZbigniew Bodek enum ena_eth_io_l4_proto_index l4_proto; 7245c98dacSZbigniew Bodek bool l3_csum_err; 7345c98dacSZbigniew Bodek bool l4_csum_err; 7445c98dacSZbigniew Bodek /* fragmented packet */ 7545c98dacSZbigniew Bodek bool frag; 7645c98dacSZbigniew Bodek u32 hash; 7745c98dacSZbigniew Bodek u16 descs; 7845c98dacSZbigniew Bodek int max_bufs; 7945c98dacSZbigniew Bodek }; 8045c98dacSZbigniew Bodek 8145c98dacSZbigniew Bodek int ena_com_prepare_tx(struct ena_com_io_sq *io_sq, 8245c98dacSZbigniew Bodek struct ena_com_tx_ctx *ena_tx_ctx, 8345c98dacSZbigniew Bodek int *nb_hw_desc); 8445c98dacSZbigniew Bodek 8545c98dacSZbigniew Bodek int ena_com_rx_pkt(struct ena_com_io_cq *io_cq, 8645c98dacSZbigniew Bodek struct ena_com_io_sq *io_sq, 8745c98dacSZbigniew Bodek struct ena_com_rx_ctx *ena_rx_ctx); 8845c98dacSZbigniew Bodek 8945c98dacSZbigniew Bodek int ena_com_add_single_rx_desc(struct ena_com_io_sq *io_sq, 9045c98dacSZbigniew Bodek struct ena_com_buf *ena_buf, 9145c98dacSZbigniew Bodek u16 req_id); 9245c98dacSZbigniew Bodek 9345c98dacSZbigniew Bodek int ena_com_tx_comp_req_id_get(struct ena_com_io_cq *io_cq, u16 *req_id); 9445c98dacSZbigniew Bodek 9545c98dacSZbigniew Bodek static inline void ena_com_unmask_intr(struct ena_com_io_cq *io_cq, 9645c98dacSZbigniew Bodek struct ena_eth_io_intr_reg *intr_reg) 9745c98dacSZbigniew Bodek { 9845c98dacSZbigniew Bodek ENA_REG_WRITE32(io_cq->bus, intr_reg->intr_control, io_cq->unmask_reg); 9945c98dacSZbigniew Bodek } 10045c98dacSZbigniew Bodek 101*a195fab0SMarcin Wojtas static inline int ena_com_free_desc(struct ena_com_io_sq *io_sq) 10245c98dacSZbigniew Bodek { 10345c98dacSZbigniew Bodek u16 tail, next_to_comp, cnt; 10445c98dacSZbigniew Bodek 10545c98dacSZbigniew Bodek next_to_comp = io_sq->next_to_comp; 10645c98dacSZbigniew Bodek tail = io_sq->tail; 10745c98dacSZbigniew Bodek cnt = tail - next_to_comp; 10845c98dacSZbigniew Bodek 10945c98dacSZbigniew Bodek return io_sq->q_depth - 1 - cnt; 11045c98dacSZbigniew Bodek } 11145c98dacSZbigniew Bodek 112*a195fab0SMarcin Wojtas /* Check if the submission queue has enough space to hold required_buffers */ 113*a195fab0SMarcin Wojtas static inline bool ena_com_sq_have_enough_space(struct ena_com_io_sq *io_sq, 114*a195fab0SMarcin Wojtas u16 required_buffers) 115*a195fab0SMarcin Wojtas { 116*a195fab0SMarcin Wojtas int temp; 117*a195fab0SMarcin Wojtas 118*a195fab0SMarcin Wojtas if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 119*a195fab0SMarcin Wojtas return ena_com_free_desc(io_sq) >= required_buffers; 120*a195fab0SMarcin Wojtas 121*a195fab0SMarcin Wojtas /* This calculation doesn't need to be 100% accurate. So to reduce 122*a195fab0SMarcin Wojtas * the calculation overhead just Subtract 2 lines from the free descs 123*a195fab0SMarcin Wojtas * (one for the header line and one to compensate the devision 124*a195fab0SMarcin Wojtas * down calculation. 125*a195fab0SMarcin Wojtas */ 126*a195fab0SMarcin Wojtas temp = required_buffers / io_sq->llq_info.descs_per_entry + 2; 127*a195fab0SMarcin Wojtas 128*a195fab0SMarcin Wojtas return ena_com_free_desc(io_sq) > temp; 129*a195fab0SMarcin Wojtas } 130*a195fab0SMarcin Wojtas 13145c98dacSZbigniew Bodek static inline int ena_com_write_sq_doorbell(struct ena_com_io_sq *io_sq) 13245c98dacSZbigniew Bodek { 13345c98dacSZbigniew Bodek u16 tail; 13445c98dacSZbigniew Bodek 13545c98dacSZbigniew Bodek tail = io_sq->tail; 13645c98dacSZbigniew Bodek 13745c98dacSZbigniew Bodek ena_trc_dbg("write submission queue doorbell for queue: %d tail: %d\n", 13845c98dacSZbigniew Bodek io_sq->qid, tail); 13945c98dacSZbigniew Bodek 14045c98dacSZbigniew Bodek ENA_REG_WRITE32(io_sq->bus, tail, io_sq->db_addr); 14145c98dacSZbigniew Bodek 14245c98dacSZbigniew Bodek return 0; 14345c98dacSZbigniew Bodek } 14445c98dacSZbigniew Bodek 14545c98dacSZbigniew Bodek static inline int ena_com_update_dev_comp_head(struct ena_com_io_cq *io_cq) 14645c98dacSZbigniew Bodek { 14745c98dacSZbigniew Bodek u16 unreported_comp, head; 14845c98dacSZbigniew Bodek bool need_update; 14945c98dacSZbigniew Bodek 15045c98dacSZbigniew Bodek head = io_cq->head; 15145c98dacSZbigniew Bodek unreported_comp = head - io_cq->last_head_update; 15245c98dacSZbigniew Bodek need_update = unreported_comp > (io_cq->q_depth / ENA_COMP_HEAD_THRESH); 15345c98dacSZbigniew Bodek 15445c98dacSZbigniew Bodek if (io_cq->cq_head_db_reg && need_update) { 15545c98dacSZbigniew Bodek ena_trc_dbg("Write completion queue doorbell for queue %d: head: %d\n", 15645c98dacSZbigniew Bodek io_cq->qid, head); 15745c98dacSZbigniew Bodek ENA_REG_WRITE32(io_cq->bus, head, io_cq->cq_head_db_reg); 15845c98dacSZbigniew Bodek io_cq->last_head_update = head; 15945c98dacSZbigniew Bodek } 16045c98dacSZbigniew Bodek 16145c98dacSZbigniew Bodek return 0; 16245c98dacSZbigniew Bodek } 16345c98dacSZbigniew Bodek 16445c98dacSZbigniew Bodek static inline void ena_com_update_numa_node(struct ena_com_io_cq *io_cq, 16545c98dacSZbigniew Bodek u8 numa_node) 16645c98dacSZbigniew Bodek { 16745c98dacSZbigniew Bodek struct ena_eth_io_numa_node_cfg_reg numa_cfg; 16845c98dacSZbigniew Bodek 16945c98dacSZbigniew Bodek if (!io_cq->numa_node_cfg_reg) 17045c98dacSZbigniew Bodek return; 17145c98dacSZbigniew Bodek 17245c98dacSZbigniew Bodek numa_cfg.numa_cfg = (numa_node & ENA_ETH_IO_NUMA_NODE_CFG_REG_NUMA_MASK) 17345c98dacSZbigniew Bodek | ENA_ETH_IO_NUMA_NODE_CFG_REG_ENABLED_MASK; 17445c98dacSZbigniew Bodek 17545c98dacSZbigniew Bodek ENA_REG_WRITE32(io_cq->bus, numa_cfg.numa_cfg, io_cq->numa_node_cfg_reg); 17645c98dacSZbigniew Bodek } 17745c98dacSZbigniew Bodek 17845c98dacSZbigniew Bodek static inline void ena_com_comp_ack(struct ena_com_io_sq *io_sq, u16 elem) 17945c98dacSZbigniew Bodek { 18045c98dacSZbigniew Bodek io_sq->next_to_comp += elem; 18145c98dacSZbigniew Bodek } 18245c98dacSZbigniew Bodek 18345c98dacSZbigniew Bodek #if defined(__cplusplus) 18445c98dacSZbigniew Bodek } 18545c98dacSZbigniew Bodek #endif 18645c98dacSZbigniew Bodek #endif /* ENA_ETH_COM_H_ */ 187