diff --git a/src/cndm/modules/cndm/cndm.h b/src/cndm/modules/cndm/cndm.h index faa530a..4ab65a1 100644 --- a/src/cndm/modules/cndm/cndm.h +++ b/src/cndm/modules/cndm/cndm.h @@ -235,12 +235,17 @@ struct cndm_cq *cndm_create_cq(struct cndm_priv *priv); void cndm_destroy_cq(struct cndm_cq *cq); int cndm_open_cq(struct cndm_cq *cq, int irqn, int size); void cndm_close_cq(struct cndm_cq *cq); +void cndm_cq_write_cons_ptr(const struct cndm_cq *cq); +void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq); // cndm_sq.c struct cndm_ring *cndm_create_sq(struct cndm_priv *priv); void cndm_destroy_sq(struct cndm_ring *sq); int cndm_open_sq(struct cndm_ring *sq, struct cndm_priv *priv, struct cndm_cq *cq, int size); void cndm_close_sq(struct cndm_ring *sq); +bool cndm_is_sq_ring_empty(const struct cndm_ring *sq); +bool cndm_is_sq_ring_full(const struct cndm_ring *sq); +void cndm_sq_write_prod_ptr(const struct cndm_ring *sq); int cndm_free_tx_buf(struct cndm_ring *sq); int cndm_poll_tx_cq(struct napi_struct *napi, int budget); int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev); @@ -250,6 +255,9 @@ struct cndm_ring *cndm_create_rq(struct cndm_priv *priv); void cndm_destroy_rq(struct cndm_ring *rq); int cndm_open_rq(struct cndm_ring *rq, struct cndm_priv *priv, struct cndm_cq *cq, int size); void cndm_close_rq(struct cndm_ring *rq); +bool cndm_is_rq_ring_empty(const struct cndm_ring *rq); +bool cndm_is_rq_ring_full(const struct cndm_ring *rq); +void cndm_rq_write_prod_ptr(const struct cndm_ring *rq); int cndm_free_rx_buf(struct cndm_ring *rq); int cndm_refill_rx_buffers(struct cndm_ring *rq); int cndm_poll_rx_cq(struct napi_struct *napi, int budget); diff --git a/src/cndm/modules/cndm/cndm_cq.c b/src/cndm/modules/cndm/cndm_cq.c index 344ea10..c388902 100644 --- a/src/cndm/modules/cndm/cndm_cq.c +++ b/src/cndm/modules/cndm/cndm_cq.c @@ -89,6 +89,8 @@ int cndm_open_cq(struct cndm_cq *cq, int irqn, int size) cq->enabled = 1; + cndm_cq_write_cons_ptr_arm(cq); + netdev_dbg(cq->priv->ndev, "Opened CQ %d", cq->cqn); return 0; @@ -125,3 +127,13 @@ void cndm_close_cq(struct cndm_cq *cq) cq->buf_dma_addr = 0; } } + +void cndm_cq_write_cons_ptr(const struct cndm_cq *cq) +{ + iowrite32(cq->cons_ptr & 0xffff, cq->db_addr); +} + +void cndm_cq_write_cons_ptr_arm(const struct cndm_cq *cq) +{ + iowrite32((cq->cons_ptr & 0xffff) | 0x80000000, cq->db_addr); +} diff --git a/src/cndm/modules/cndm/cndm_rq.c b/src/cndm/modules/cndm/cndm_rq.c index 1dbfe2f..512619a 100644 --- a/src/cndm/modules/cndm/cndm_rq.c +++ b/src/cndm/modules/cndm/cndm_rq.c @@ -163,6 +163,21 @@ void cndm_close_rq(struct cndm_ring *rq) rq->priv = NULL; } +bool cndm_is_rq_ring_empty(const struct cndm_ring *rq) +{ + return rq->prod_ptr == rq->cons_ptr; +} + +bool cndm_is_rq_ring_full(const struct cndm_ring *rq) +{ + return (rq->prod_ptr - rq->cons_ptr) >= rq->size; +} + +void cndm_rq_write_prod_ptr(const struct cndm_ring *rq) +{ + iowrite32(rq->prod_ptr & 0xffff, rq->db_addr); +} + static void cndm_free_rx_desc(struct cndm_ring *rq, int index) { struct cndm_priv *priv = rq->priv; @@ -185,7 +200,7 @@ int cndm_free_rx_buf(struct cndm_ring *rq) u32 index; int cnt = 0; - while (rq->prod_ptr != rq->cons_ptr) { + while (!cndm_is_rq_ring_empty(rq)) { index = rq->cons_ptr & rq->size_mask; cndm_free_rx_desc(rq, index); rq->cons_ptr++; @@ -247,7 +262,7 @@ int cndm_refill_rx_buffers(struct cndm_ring *rq) } dma_wmb(); - iowrite32(rq->prod_ptr & 0xffff, rq->db_addr); + cndm_rq_write_prod_ptr(rq); return ret; } @@ -332,6 +347,7 @@ rx_drop: rq->cons_ptr = cons_ptr; cndm_refill_rx_buffers(rq); + cndm_cq_write_cons_ptr(cq); return done; } @@ -349,6 +365,7 @@ int cndm_poll_rx_cq(struct napi_struct *napi, int budget) napi_complete(napi); // TODO re-enable interrupts + cndm_cq_write_cons_ptr_arm(cq); return done; } diff --git a/src/cndm/modules/cndm/cndm_sq.c b/src/cndm/modules/cndm/cndm_sq.c index 8f3f446..d2e1d3f 100644 --- a/src/cndm/modules/cndm/cndm_sq.c +++ b/src/cndm/modules/cndm/cndm_sq.c @@ -152,6 +152,21 @@ void cndm_close_sq(struct cndm_ring *sq) sq->priv = NULL; } +bool cndm_is_sq_ring_empty(const struct cndm_ring *sq) +{ + return sq->prod_ptr == sq->cons_ptr; +} + +bool cndm_is_sq_ring_full(const struct cndm_ring *sq) +{ + return (sq->prod_ptr - sq->cons_ptr) >= sq->size; +} + +void cndm_sq_write_prod_ptr(const struct cndm_ring *sq) +{ + iowrite32(sq->prod_ptr & 0xffff, sq->db_addr); +} + static void cndm_free_tx_desc(struct cndm_ring *sq, int index, int napi_budget) { struct cndm_priv *priv = sq->priv; @@ -173,7 +188,7 @@ int cndm_free_tx_buf(struct cndm_ring *sq) u32 index; int cnt = 0; - while (sq->prod_ptr != sq->cons_ptr) { + while (!cndm_is_sq_ring_empty(sq)) { index = sq->cons_ptr & sq->size_mask; cndm_free_tx_desc(sq, index, 0); sq->cons_ptr++; @@ -229,6 +244,8 @@ static int cndm_process_tx_cq(struct cndm_cq *cq, int napi_budget) cq->cons_ptr = cq_cons_ptr; sq->cons_ptr = cons_ptr; + cndm_cq_write_cons_ptr(cq); + if (netif_tx_queue_stopped(sq->tx_queue) && (done != 0 || sq->prod_ptr == sq->cons_ptr)) netif_tx_wake_queue(sq->tx_queue); @@ -248,6 +265,7 @@ int cndm_poll_tx_cq(struct napi_struct *napi, int budget) napi_complete(napi); // TODO re-enable interrupts + cndm_cq_write_cons_ptr_arm(cq); return done; } @@ -315,7 +333,7 @@ int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev) } dma_wmb(); - iowrite32(sq->prod_ptr & 0xffff, sq->db_addr); + cndm_sq_write_prod_ptr(sq); return NETDEV_TX_OK; diff --git a/src/cndm/rtl/cndm_micro_cpl_wr.sv b/src/cndm/rtl/cndm_micro_cpl_wr.sv index a247bce..3e30f86 100644 --- a/src/cndm/rtl/cndm_micro_cpl_wr.sv +++ b/src/cndm/rtl/cndm_micro_cpl_wr.sv @@ -45,6 +45,9 @@ module cndm_micro_cpl_wr #( */ taxi_axis_if.src m_axis_irq, + /* + * Completion input + */ taxi_axis_if.snk s_axis_cpl ); @@ -58,6 +61,7 @@ logic cq_req_ready; logic [IRQN_W-1:0] cq_rsp_irqn; logic [DMA_ADDR_W-1:0] cq_rsp_addr; logic cq_rsp_phase_tag; +logic cq_rsp_arm; logic cq_rsp_error; logic cq_rsp_valid; logic cq_rsp_ready_reg = 1'b0; @@ -96,6 +100,7 @@ cq_mgr_inst ( .rsp_dqn(cq_rsp_irqn), .rsp_addr(cq_rsp_addr), .rsp_phase_tag(cq_rsp_phase_tag), + .rsp_arm(cq_rsp_arm), .rsp_error(cq_rsp_error), .rsp_valid(cq_rsp_valid), .rsp_ready(cq_rsp_ready_reg) @@ -110,6 +115,7 @@ typedef enum logic [1:0] { state_t state_reg = STATE_IDLE; logic phase_tag_reg = 1'b0; +logic arm_reg = 1'b0; logic [IRQN_W-1:0] m_axis_irq_irqn_reg = '0; logic m_axis_irq_tvalid_reg = 1'b0; @@ -167,6 +173,7 @@ always_ff @(posedge clk) begin m_axis_irq_irqn_reg <= cq_rsp_irqn; dma_wr_desc_req.req_dst_addr <= cq_rsp_addr; phase_tag_reg <= cq_rsp_phase_tag; + arm_reg <= cq_rsp_arm; if (cq_rsp_error) begin // drop completion @@ -181,7 +188,7 @@ always_ff @(posedge clk) begin STATE_WRITE_DATA: begin if (dma_wr_desc_sts.sts_valid) begin s_axis_cpl.tready <= 1'b1; - m_axis_irq_tvalid_reg <= 1'b1; + m_axis_irq_tvalid_reg <= arm_reg; // only generate interrupt when armed state_reg <= STATE_IDLE; end end diff --git a/src/cndm/rtl/cndm_micro_desc_rd.sv b/src/cndm/rtl/cndm_micro_desc_rd.sv index af46695..0ccf337 100644 --- a/src/cndm/rtl/cndm_micro_desc_rd.sv +++ b/src/cndm/rtl/cndm_micro_desc_rd.sv @@ -100,6 +100,7 @@ wq_mgr_inst ( .rsp_dqn(wq_rsp_cqn), .rsp_addr(wq_rsp_addr), .rsp_phase_tag(), + .rsp_arm(), .rsp_error(wq_rsp_error), .rsp_valid(wq_rsp_valid), .rsp_ready(wq_rsp_ready_reg) diff --git a/src/cndm/rtl/cndm_micro_dp_mgr.sv b/src/cndm/rtl/cndm_micro_dp_mgr.sv index 1ca51fd..b7854ff 100644 --- a/src/cndm/rtl/cndm_micro_dp_mgr.sv +++ b/src/cndm/rtl/cndm_micro_dp_mgr.sv @@ -694,7 +694,11 @@ always_comb begin // reset queue 2 // store doorbell offset - cmd_ram_wr_data = host_ptr_reg + 'h0008; + if (qtype_reg == QTYPE_SQ || qtype_reg == QTYPE_RQ) begin + cmd_ram_wr_data = host_ptr_reg + 'h0008; + end else begin + cmd_ram_wr_data = host_ptr_reg + 'h000C; + end cmd_ram_wr_addr = 7; cmd_ram_wr_en = 1'b1; diff --git a/src/cndm/rtl/cndm_micro_port.sv b/src/cndm/rtl/cndm_micro_port.sv index 3c5e57e..4f7e827 100644 --- a/src/cndm/rtl/cndm_micro_port.sv +++ b/src/cndm/rtl/cndm_micro_port.sv @@ -513,6 +513,9 @@ cpl_wr_inst ( */ .m_axis_irq(m_axis_irq), + /* + * Completion input + */ .s_axis_cpl(axis_cpl) ); diff --git a/src/cndm/rtl/cndm_micro_queue_state.sv b/src/cndm/rtl/cndm_micro_queue_state.sv index b5c3288..60bca2a 100644 --- a/src/cndm/rtl/cndm_micro_queue_state.sv +++ b/src/cndm/rtl/cndm_micro_queue_state.sv @@ -49,6 +49,7 @@ module cndm_micro_queue_state #( output wire logic [DQN_W-1:0] rsp_dqn, output wire logic [DMA_ADDR_W-1:0] rsp_addr, output wire logic rsp_phase_tag, + output wire logic rsp_arm, output wire logic rsp_error, output wire logic rsp_valid, input wire logic rsp_ready @@ -119,6 +120,7 @@ logic [QN_W-1:0] rsp_qn_reg = '0, rsp_qn_next; logic [DQN_W-1:0] rsp_dqn_reg = '0, rsp_dqn_next; logic [DMA_ADDR_W-1:0] rsp_addr_reg = '0, rsp_addr_next; logic rsp_phase_tag_reg = 1'b0, rsp_phase_tag_next; +logic rsp_arm_reg = 1'b0, rsp_arm_next; logic rsp_error_reg = 1'b0, rsp_error_next; logic rsp_valid_reg = 1'b0, rsp_valid_next; @@ -127,11 +129,14 @@ assign rsp_qn = rsp_qn_reg; assign rsp_dqn = rsp_dqn_reg; assign rsp_addr = rsp_addr_reg; assign rsp_phase_tag = rsp_phase_tag_reg; +assign rsp_arm = IS_CQ ? rsp_arm_reg : 1'b0; assign rsp_error = rsp_error_reg; assign rsp_valid = rsp_valid_reg; logic [2**QN_W-1:0] queue_enable_reg = '0; (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) +logic queue_mem_arm[2**QN_W] = '{default: '0}; +(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) logic [2:0] queue_mem_qtype[2**QN_W] = '{default: '0}; (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) logic [DQN_W-1:0] queue_mem_dqn[2**QN_W] = '{default: '0}; @@ -148,6 +153,7 @@ logic queue_mem_wr_en; logic [QN_W-1:0] queue_mem_addr; wire queue_mem_rd_enable = queue_enable_reg[queue_mem_addr]; +wire queue_mem_rd_arm = queue_mem_arm[queue_mem_addr]; wire [2:0] queue_mem_rd_qtype = queue_mem_qtype[queue_mem_addr]; wire [DQN_W-1:0] queue_mem_rd_dqn = queue_mem_dqn[queue_mem_addr]; wire [3:0] queue_mem_rd_log_size = queue_mem_log_size[queue_mem_addr]; @@ -155,7 +161,11 @@ wire [DMA_ADDR_W-1:0] queue_mem_rd_base_addr = queue_mem_base_addr[queue_mem_add wire [PTR_W-1:0] queue_mem_rd_prod_ptr = queue_mem_prod_ptr[queue_mem_addr]; wire [PTR_W-1:0] queue_mem_rd_cons_ptr = queue_mem_cons_ptr[queue_mem_addr]; +wire queue_mem_rd_status_empty = queue_mem_rd_prod_ptr == queue_mem_rd_cons_ptr; +wire queue_mem_rd_status_full = ($unsigned(queue_mem_rd_prod_ptr - queue_mem_rd_cons_ptr) & ({PTR_W{1'b1}} << queue_mem_rd_log_size)) != 0; + logic queue_mem_wr_enable; +logic queue_mem_wr_arm; logic [2:0] queue_mem_wr_qtype; logic [DQN_W-1:0] queue_mem_wr_dqn; logic [3:0] queue_mem_wr_log_size; @@ -180,6 +190,7 @@ always_comb begin rsp_dqn_next = rsp_dqn_reg; rsp_addr_next = rsp_addr_reg; rsp_phase_tag_next = rsp_phase_tag_reg; + rsp_arm_next = rsp_arm_reg; rsp_error_next = rsp_error_reg; rsp_valid_next = rsp_valid_reg && !rsp_ready; @@ -187,6 +198,7 @@ always_comb begin queue_mem_addr = '0; queue_mem_wr_enable = queue_mem_rd_enable; + queue_mem_wr_arm = queue_mem_rd_arm; queue_mem_wr_qtype = queue_mem_rd_qtype; queue_mem_wr_dqn = queue_mem_rd_dqn; queue_mem_wr_log_size = queue_mem_rd_log_size; @@ -194,13 +206,6 @@ always_comb begin queue_mem_wr_prod_ptr = queue_mem_rd_prod_ptr; queue_mem_wr_cons_ptr = queue_mem_rd_cons_ptr; - // terminate AXI lite writes - if (IS_CQ && s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin - s_axil_ctrl_awready_next = 1'b1; - s_axil_ctrl_wready_next = 1'b1; - s_axil_ctrl_bvalid_next = 1'b1; - end - // terminate AXI lite reads if (s_axil_ctrl_rd.arvalid && !s_axil_ctrl_rvalid_reg) begin s_axil_ctrl_rdata_next = '0; @@ -209,7 +214,7 @@ always_comb begin s_axil_ctrl_rvalid_next = 1'b1; end - if (!IS_CQ && s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin + if (s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin // AXI lite write s_axil_ctrl_awready_next = 1'b1; s_axil_ctrl_wready_next = 1'b1; @@ -219,7 +224,19 @@ always_comb begin queue_mem_addr = s_axil_ctrl_awaddr_queue_index; case (s_axil_ctrl_awaddr_reg_index) - 3'd2: queue_mem_wr_prod_ptr = s_axil_ctrl_wr.wdata[15:0]; + 3'd2: begin + if (!IS_CQ) begin + queue_mem_wr_prod_ptr = s_axil_ctrl_wr.wdata[15:0]; + end + end + 3'd3: begin + if (IS_CQ) begin + queue_mem_wr_cons_ptr = s_axil_ctrl_wr.wdata[15:0]; + if (s_axil_ctrl_wr.wdata[31]) begin + queue_mem_wr_arm = 1'b1; + end + end + end default: begin end endcase @@ -236,12 +253,18 @@ always_comb begin case (s_apb_dp_ctrl_paddr_reg_index) 3'd0: begin queue_mem_wr_enable = s_apb_dp_ctrl.pwdata[0]; + queue_mem_wr_arm = s_apb_dp_ctrl.pwdata[1]; queue_mem_wr_log_size = s_apb_dp_ctrl.pwdata[19:16]; queue_mem_wr_qtype = 3'(s_apb_dp_ctrl.pwdata[23:20]); end 3'd1: queue_mem_wr_dqn = s_apb_dp_ctrl.pwdata[DQN_W-1:0]; 3'd2: queue_mem_wr_prod_ptr = s_apb_dp_ctrl.pwdata[15:0]; - 3'd3: queue_mem_wr_cons_ptr = s_apb_dp_ctrl.pwdata[15:0]; + 3'd3: begin + queue_mem_wr_cons_ptr = s_apb_dp_ctrl.pwdata[15:0]; + if (s_apb_dp_ctrl.pwdata[31]) begin + queue_mem_wr_arm = 1'b1; + end + end 3'd6: queue_mem_wr_base_addr[31:0] = s_apb_dp_ctrl.pwdata; 3'd7: queue_mem_wr_base_addr[63:32] = s_apb_dp_ctrl.pwdata; default: begin end @@ -251,12 +274,13 @@ always_comb begin case (s_apb_dp_ctrl_paddr_reg_index) 3'd0: begin s_apb_dp_ctrl_prdata_next[0] = queue_mem_rd_enable; + s_apb_dp_ctrl_prdata_next[1] = IS_CQ ? queue_mem_rd_arm : 1'b0; s_apb_dp_ctrl_prdata_next[19:16] = queue_mem_rd_log_size; - s_apb_dp_ctrl_prdata_next[23:20] = 4'(queue_mem_rd_qtype); + s_apb_dp_ctrl_prdata_next[23:20] = QTYPE_EN ? 4'(queue_mem_rd_qtype) : '0; end 3'd1: s_apb_dp_ctrl_prdata_next = 32'(queue_mem_rd_dqn); - 3'd2: s_apb_dp_ctrl_prdata_next[15:0] = queue_mem_rd_prod_ptr; - 3'd3: s_apb_dp_ctrl_prdata_next[15:0] = IS_CQ ? '0 : queue_mem_rd_cons_ptr; + 3'd2: s_apb_dp_ctrl_prdata_next = 32'(queue_mem_rd_prod_ptr); + 3'd3: s_apb_dp_ctrl_prdata_next = 32'(queue_mem_rd_cons_ptr); 3'd6: s_apb_dp_ctrl_prdata_next = queue_mem_rd_base_addr[31:0]; 3'd7: s_apb_dp_ctrl_prdata_next = queue_mem_rd_base_addr[63:32]; default: begin end @@ -267,17 +291,21 @@ always_comb begin req_ready_next = 1'b1; queue_mem_addr = req_qn; + queue_mem_wr_arm = 1'b0; + rsp_arm_next = queue_mem_rd_arm; rsp_qn_next = req_qn; rsp_dqn_next = queue_mem_rd_dqn; rsp_error_next = !queue_mem_rd_enable || (QTYPE_EN && req_qtype != queue_mem_rd_qtype); if (IS_CQ) begin rsp_addr_next = queue_mem_rd_base_addr + DMA_ADDR_W'(16'(queue_mem_rd_prod_ptr & ({16{1'b1}} >> (16 - queue_mem_rd_log_size))) * QE_SIZE); rsp_phase_tag_next = !queue_mem_rd_prod_ptr[queue_mem_rd_log_size]; + if (queue_mem_rd_status_full) + rsp_error_next = 1'b1; queue_mem_wr_prod_ptr = queue_mem_rd_prod_ptr + 1; end else begin rsp_addr_next = queue_mem_rd_base_addr + DMA_ADDR_W'(16'(queue_mem_rd_cons_ptr & ({16{1'b1}} >> (16 - queue_mem_rd_log_size))) * QE_SIZE); - if (queue_mem_rd_prod_ptr == queue_mem_rd_cons_ptr) + if (queue_mem_rd_status_empty) rsp_error_next = 1'b1; queue_mem_wr_cons_ptr = queue_mem_rd_cons_ptr + 1; end @@ -306,11 +334,13 @@ always @(posedge clk) begin rsp_dqn_reg <= rsp_dqn_next; rsp_addr_reg <= rsp_addr_next; rsp_phase_tag_reg <= rsp_phase_tag_next; + rsp_arm_reg <= rsp_arm_next; rsp_error_reg <= rsp_error_next; rsp_valid_reg <= rsp_valid_next; if (queue_mem_wr_en) begin queue_enable_reg[queue_mem_addr] <= queue_mem_wr_enable; + queue_mem_arm[queue_mem_addr] <= queue_mem_wr_arm; queue_mem_qtype[queue_mem_addr] <= queue_mem_wr_qtype; queue_mem_dqn[queue_mem_addr] <= queue_mem_wr_dqn; queue_mem_log_size[queue_mem_addr] <= queue_mem_wr_log_size; diff --git a/src/cndm/tb/cndm.py b/src/cndm/tb/cndm.py index cddbc2a..d516f55 100644 --- a/src/cndm/tb/cndm.py +++ b/src/cndm/tb/cndm.py @@ -89,7 +89,6 @@ class Cq: self.cons_ptr = None self.db_offset = None - self.hw_regs = self.driver.hw_regs async def open(self, irqn, size): @@ -141,7 +140,10 @@ class Cq: self.log.error("Failed to allocate CQ") return + await self.write_cons_ptr_arm() + self.log.info("Opened CQ %d", self.cqn) + self.log.info("Using doorbell at offset 0x%08x", self.db_offset) self.enabled = True @@ -173,6 +175,12 @@ class Cq: # TODO free buffer + async def write_cons_ptr(self): + await self.hw_regs.write_dword(self.db_offset, self.cons_ptr & 0xffff) + + async def write_cons_ptr_arm(self): + await self.hw_regs.write_dword(self.db_offset, (self.cons_ptr & 0xffff) | 0x80000000) + class Sq: def __init__(self, driver, port): @@ -203,7 +211,6 @@ class Sq: self.bytes = 0 self.db_offset = None - self.hw_regs = self.driver.hw_regs async def open(self, cq, size): @@ -261,6 +268,7 @@ class Sq: return self.log.info("Opened SQ %d (CQ %d)", self.sqn, cq.cqn) + self.log.info("Using doorbell at offset 0x%08x", self.db_offset) self.enabled = True @@ -292,6 +300,15 @@ class Sq: # TODO free buffer + def is_ring_empty(self): + return self.prod_ptr == self.cons_ptr + + def is_ring_full(self): + return ((self.prod_ptr - self.cons_ptr) & 0xffffffff) > self.size + + async def write_prod_ptr(self): + await self.hw_regs.write_dword(self.db_offset, self.prod_ptr & 0xffff) + async def start_xmit(self, data): headroom = 10 tx_buf = self.driver.alloc_pkt() @@ -301,7 +318,7 @@ class Sq: struct.pack_into(' self.size + + async def write_prod_ptr(self): + await self.hw_regs.write_dword(self.db_offset, self.prod_ptr & 0xffff) + def free_rx_desc(self, index): pkt = self.rx_info[index] self.driver.free_pkt(pkt) self.rx_info[index] = None def free_rx_buf(self): - while self.cons_ptr != self.prod_ptr: + while not self.is_ring_empty(): index = self.cons_ptr & self.size_mask self.free_rx_desc(index) self.cons_ptr += 1 @@ -496,7 +524,7 @@ class Rq: self.prepare_rx_desc(self.prod_ptr & self.size_mask) self.prod_ptr += 1 - await self.hw_regs.write_dword(self.db_offset, self.prod_ptr & 0xffff) + await self.write_prod_ptr() @staticmethod async def process_rx_cq(cq): @@ -537,6 +565,7 @@ class Rq: rq.cons_ptr = cons_ptr await rq.refill_rx_buffers() + await cq.write_cons_ptr_arm() class Port: