1*2af541bfSCheng Xu // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2*2af541bfSCheng Xu 3*2af541bfSCheng Xu /* Authors: Cheng Xu <chengyou@linux.alibaba.com> */ 4*2af541bfSCheng Xu /* Kai Shen <kaishen@linux.alibaba.com> */ 5*2af541bfSCheng Xu /* Copyright (c) 2020-2022, Alibaba Group. */ 6*2af541bfSCheng Xu 7*2af541bfSCheng Xu #include <linux/kernel.h> 8*2af541bfSCheng Xu #include <linux/pci.h> 9*2af541bfSCheng Xu #include <linux/types.h> 10*2af541bfSCheng Xu 11*2af541bfSCheng Xu #include "erdma.h" 12*2af541bfSCheng Xu #include "erdma_hw.h" 13*2af541bfSCheng Xu #include "erdma_verbs.h" 14*2af541bfSCheng Xu 15*2af541bfSCheng Xu static void arm_cmdq_cq(struct erdma_cmdq *cmdq) 16*2af541bfSCheng Xu { 17*2af541bfSCheng Xu struct erdma_dev *dev = container_of(cmdq, struct erdma_dev, cmdq); 18*2af541bfSCheng Xu u64 db_data = FIELD_PREP(ERDMA_CQDB_CI_MASK, cmdq->cq.ci) | 19*2af541bfSCheng Xu FIELD_PREP(ERDMA_CQDB_ARM_MASK, 1) | 20*2af541bfSCheng Xu FIELD_PREP(ERDMA_CQDB_CMDSN_MASK, cmdq->cq.cmdsn) | 21*2af541bfSCheng Xu FIELD_PREP(ERDMA_CQDB_IDX_MASK, cmdq->cq.cmdsn); 22*2af541bfSCheng Xu 23*2af541bfSCheng Xu *cmdq->cq.db_record = db_data; 24*2af541bfSCheng Xu writeq(db_data, dev->func_bar + ERDMA_CMDQ_CQDB_REG); 25*2af541bfSCheng Xu 26*2af541bfSCheng Xu atomic64_inc(&cmdq->cq.armed_num); 27*2af541bfSCheng Xu } 28*2af541bfSCheng Xu 29*2af541bfSCheng Xu static void kick_cmdq_db(struct erdma_cmdq *cmdq) 30*2af541bfSCheng Xu { 31*2af541bfSCheng Xu struct erdma_dev *dev = container_of(cmdq, struct erdma_dev, cmdq); 32*2af541bfSCheng Xu u64 db_data = FIELD_PREP(ERDMA_CMD_HDR_WQEBB_INDEX_MASK, cmdq->sq.pi); 33*2af541bfSCheng Xu 34*2af541bfSCheng Xu *cmdq->sq.db_record = db_data; 35*2af541bfSCheng Xu writeq(db_data, dev->func_bar + ERDMA_CMDQ_SQDB_REG); 36*2af541bfSCheng Xu } 37*2af541bfSCheng Xu 38*2af541bfSCheng Xu static struct erdma_comp_wait *get_comp_wait(struct erdma_cmdq *cmdq) 39*2af541bfSCheng Xu { 40*2af541bfSCheng Xu int comp_idx; 41*2af541bfSCheng Xu 42*2af541bfSCheng Xu spin_lock(&cmdq->lock); 43*2af541bfSCheng Xu comp_idx = find_first_zero_bit(cmdq->comp_wait_bitmap, 44*2af541bfSCheng Xu cmdq->max_outstandings); 45*2af541bfSCheng Xu if (comp_idx == cmdq->max_outstandings) { 46*2af541bfSCheng Xu spin_unlock(&cmdq->lock); 47*2af541bfSCheng Xu return ERR_PTR(-ENOMEM); 48*2af541bfSCheng Xu } 49*2af541bfSCheng Xu 50*2af541bfSCheng Xu __set_bit(comp_idx, cmdq->comp_wait_bitmap); 51*2af541bfSCheng Xu spin_unlock(&cmdq->lock); 52*2af541bfSCheng Xu 53*2af541bfSCheng Xu return &cmdq->wait_pool[comp_idx]; 54*2af541bfSCheng Xu } 55*2af541bfSCheng Xu 56*2af541bfSCheng Xu static void put_comp_wait(struct erdma_cmdq *cmdq, 57*2af541bfSCheng Xu struct erdma_comp_wait *comp_wait) 58*2af541bfSCheng Xu { 59*2af541bfSCheng Xu int used; 60*2af541bfSCheng Xu 61*2af541bfSCheng Xu cmdq->wait_pool[comp_wait->ctx_id].cmd_status = ERDMA_CMD_STATUS_INIT; 62*2af541bfSCheng Xu spin_lock(&cmdq->lock); 63*2af541bfSCheng Xu used = __test_and_clear_bit(comp_wait->ctx_id, cmdq->comp_wait_bitmap); 64*2af541bfSCheng Xu spin_unlock(&cmdq->lock); 65*2af541bfSCheng Xu 66*2af541bfSCheng Xu WARN_ON(!used); 67*2af541bfSCheng Xu } 68*2af541bfSCheng Xu 69*2af541bfSCheng Xu static int erdma_cmdq_wait_res_init(struct erdma_dev *dev, 70*2af541bfSCheng Xu struct erdma_cmdq *cmdq) 71*2af541bfSCheng Xu { 72*2af541bfSCheng Xu int i; 73*2af541bfSCheng Xu 74*2af541bfSCheng Xu cmdq->wait_pool = 75*2af541bfSCheng Xu devm_kcalloc(&dev->pdev->dev, cmdq->max_outstandings, 76*2af541bfSCheng Xu sizeof(struct erdma_comp_wait), GFP_KERNEL); 77*2af541bfSCheng Xu if (!cmdq->wait_pool) 78*2af541bfSCheng Xu return -ENOMEM; 79*2af541bfSCheng Xu 80*2af541bfSCheng Xu spin_lock_init(&cmdq->lock); 81*2af541bfSCheng Xu cmdq->comp_wait_bitmap = devm_bitmap_zalloc( 82*2af541bfSCheng Xu &dev->pdev->dev, cmdq->max_outstandings, GFP_KERNEL); 83*2af541bfSCheng Xu if (!cmdq->comp_wait_bitmap) 84*2af541bfSCheng Xu return -ENOMEM; 85*2af541bfSCheng Xu 86*2af541bfSCheng Xu for (i = 0; i < cmdq->max_outstandings; i++) { 87*2af541bfSCheng Xu init_completion(&cmdq->wait_pool[i].wait_event); 88*2af541bfSCheng Xu cmdq->wait_pool[i].ctx_id = i; 89*2af541bfSCheng Xu } 90*2af541bfSCheng Xu 91*2af541bfSCheng Xu return 0; 92*2af541bfSCheng Xu } 93*2af541bfSCheng Xu 94*2af541bfSCheng Xu static int erdma_cmdq_sq_init(struct erdma_dev *dev) 95*2af541bfSCheng Xu { 96*2af541bfSCheng Xu struct erdma_cmdq *cmdq = &dev->cmdq; 97*2af541bfSCheng Xu struct erdma_cmdq_sq *sq = &cmdq->sq; 98*2af541bfSCheng Xu u32 buf_size; 99*2af541bfSCheng Xu 100*2af541bfSCheng Xu sq->wqebb_cnt = SQEBB_COUNT(ERDMA_CMDQ_SQE_SIZE); 101*2af541bfSCheng Xu sq->depth = cmdq->max_outstandings * sq->wqebb_cnt; 102*2af541bfSCheng Xu 103*2af541bfSCheng Xu buf_size = sq->depth << SQEBB_SHIFT; 104*2af541bfSCheng Xu 105*2af541bfSCheng Xu sq->qbuf = 106*2af541bfSCheng Xu dma_alloc_coherent(&dev->pdev->dev, WARPPED_BUFSIZE(buf_size), 107*2af541bfSCheng Xu &sq->qbuf_dma_addr, GFP_KERNEL); 108*2af541bfSCheng Xu if (!sq->qbuf) 109*2af541bfSCheng Xu return -ENOMEM; 110*2af541bfSCheng Xu 111*2af541bfSCheng Xu sq->db_record = (u64 *)(sq->qbuf + buf_size); 112*2af541bfSCheng Xu 113*2af541bfSCheng Xu spin_lock_init(&sq->lock); 114*2af541bfSCheng Xu 115*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_SQ_ADDR_H_REG, 116*2af541bfSCheng Xu upper_32_bits(sq->qbuf_dma_addr)); 117*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_SQ_ADDR_L_REG, 118*2af541bfSCheng Xu lower_32_bits(sq->qbuf_dma_addr)); 119*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_DEPTH_REG, sq->depth); 120*2af541bfSCheng Xu erdma_reg_write64(dev, ERDMA_CMDQ_SQ_DB_HOST_ADDR_REG, 121*2af541bfSCheng Xu sq->qbuf_dma_addr + buf_size); 122*2af541bfSCheng Xu 123*2af541bfSCheng Xu return 0; 124*2af541bfSCheng Xu } 125*2af541bfSCheng Xu 126*2af541bfSCheng Xu static int erdma_cmdq_cq_init(struct erdma_dev *dev) 127*2af541bfSCheng Xu { 128*2af541bfSCheng Xu struct erdma_cmdq *cmdq = &dev->cmdq; 129*2af541bfSCheng Xu struct erdma_cmdq_cq *cq = &cmdq->cq; 130*2af541bfSCheng Xu u32 buf_size; 131*2af541bfSCheng Xu 132*2af541bfSCheng Xu cq->depth = cmdq->sq.depth; 133*2af541bfSCheng Xu buf_size = cq->depth << CQE_SHIFT; 134*2af541bfSCheng Xu 135*2af541bfSCheng Xu cq->qbuf = 136*2af541bfSCheng Xu dma_alloc_coherent(&dev->pdev->dev, WARPPED_BUFSIZE(buf_size), 137*2af541bfSCheng Xu &cq->qbuf_dma_addr, GFP_KERNEL | __GFP_ZERO); 138*2af541bfSCheng Xu if (!cq->qbuf) 139*2af541bfSCheng Xu return -ENOMEM; 140*2af541bfSCheng Xu 141*2af541bfSCheng Xu spin_lock_init(&cq->lock); 142*2af541bfSCheng Xu 143*2af541bfSCheng Xu cq->db_record = (u64 *)(cq->qbuf + buf_size); 144*2af541bfSCheng Xu 145*2af541bfSCheng Xu atomic64_set(&cq->armed_num, 0); 146*2af541bfSCheng Xu 147*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_CQ_ADDR_H_REG, 148*2af541bfSCheng Xu upper_32_bits(cq->qbuf_dma_addr)); 149*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_CQ_ADDR_L_REG, 150*2af541bfSCheng Xu lower_32_bits(cq->qbuf_dma_addr)); 151*2af541bfSCheng Xu erdma_reg_write64(dev, ERDMA_CMDQ_CQ_DB_HOST_ADDR_REG, 152*2af541bfSCheng Xu cq->qbuf_dma_addr + buf_size); 153*2af541bfSCheng Xu 154*2af541bfSCheng Xu return 0; 155*2af541bfSCheng Xu } 156*2af541bfSCheng Xu 157*2af541bfSCheng Xu static int erdma_cmdq_eq_init(struct erdma_dev *dev) 158*2af541bfSCheng Xu { 159*2af541bfSCheng Xu struct erdma_cmdq *cmdq = &dev->cmdq; 160*2af541bfSCheng Xu struct erdma_eq *eq = &cmdq->eq; 161*2af541bfSCheng Xu u32 buf_size; 162*2af541bfSCheng Xu 163*2af541bfSCheng Xu eq->depth = cmdq->max_outstandings; 164*2af541bfSCheng Xu buf_size = eq->depth << EQE_SHIFT; 165*2af541bfSCheng Xu 166*2af541bfSCheng Xu eq->qbuf = 167*2af541bfSCheng Xu dma_alloc_coherent(&dev->pdev->dev, WARPPED_BUFSIZE(buf_size), 168*2af541bfSCheng Xu &eq->qbuf_dma_addr, GFP_KERNEL | __GFP_ZERO); 169*2af541bfSCheng Xu if (!eq->qbuf) 170*2af541bfSCheng Xu return -ENOMEM; 171*2af541bfSCheng Xu 172*2af541bfSCheng Xu spin_lock_init(&eq->lock); 173*2af541bfSCheng Xu atomic64_set(&eq->event_num, 0); 174*2af541bfSCheng Xu 175*2af541bfSCheng Xu eq->db_addr = 176*2af541bfSCheng Xu (u64 __iomem *)(dev->func_bar + ERDMA_REGS_CEQ_DB_BASE_REG); 177*2af541bfSCheng Xu eq->db_record = (u64 *)(eq->qbuf + buf_size); 178*2af541bfSCheng Xu 179*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_EQ_ADDR_H_REG, 180*2af541bfSCheng Xu upper_32_bits(eq->qbuf_dma_addr)); 181*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_EQ_ADDR_L_REG, 182*2af541bfSCheng Xu lower_32_bits(eq->qbuf_dma_addr)); 183*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_CMDQ_EQ_DEPTH_REG, eq->depth); 184*2af541bfSCheng Xu erdma_reg_write64(dev, ERDMA_CMDQ_EQ_DB_HOST_ADDR_REG, 185*2af541bfSCheng Xu eq->qbuf_dma_addr + buf_size); 186*2af541bfSCheng Xu 187*2af541bfSCheng Xu return 0; 188*2af541bfSCheng Xu } 189*2af541bfSCheng Xu 190*2af541bfSCheng Xu int erdma_cmdq_init(struct erdma_dev *dev) 191*2af541bfSCheng Xu { 192*2af541bfSCheng Xu int err, i; 193*2af541bfSCheng Xu struct erdma_cmdq *cmdq = &dev->cmdq; 194*2af541bfSCheng Xu u32 sts, ctrl; 195*2af541bfSCheng Xu 196*2af541bfSCheng Xu cmdq->max_outstandings = ERDMA_CMDQ_MAX_OUTSTANDING; 197*2af541bfSCheng Xu cmdq->use_event = false; 198*2af541bfSCheng Xu 199*2af541bfSCheng Xu sema_init(&cmdq->credits, cmdq->max_outstandings); 200*2af541bfSCheng Xu 201*2af541bfSCheng Xu err = erdma_cmdq_wait_res_init(dev, cmdq); 202*2af541bfSCheng Xu if (err) 203*2af541bfSCheng Xu return err; 204*2af541bfSCheng Xu 205*2af541bfSCheng Xu err = erdma_cmdq_sq_init(dev); 206*2af541bfSCheng Xu if (err) 207*2af541bfSCheng Xu return err; 208*2af541bfSCheng Xu 209*2af541bfSCheng Xu err = erdma_cmdq_cq_init(dev); 210*2af541bfSCheng Xu if (err) 211*2af541bfSCheng Xu goto err_destroy_sq; 212*2af541bfSCheng Xu 213*2af541bfSCheng Xu err = erdma_cmdq_eq_init(dev); 214*2af541bfSCheng Xu if (err) 215*2af541bfSCheng Xu goto err_destroy_cq; 216*2af541bfSCheng Xu 217*2af541bfSCheng Xu ctrl = FIELD_PREP(ERDMA_REG_DEV_CTRL_INIT_MASK, 1); 218*2af541bfSCheng Xu erdma_reg_write32(dev, ERDMA_REGS_DEV_CTRL_REG, ctrl); 219*2af541bfSCheng Xu 220*2af541bfSCheng Xu for (i = 0; i < ERDMA_WAIT_DEV_DONE_CNT; i++) { 221*2af541bfSCheng Xu sts = erdma_reg_read32_filed(dev, ERDMA_REGS_DEV_ST_REG, 222*2af541bfSCheng Xu ERDMA_REG_DEV_ST_INIT_DONE_MASK); 223*2af541bfSCheng Xu if (sts) 224*2af541bfSCheng Xu break; 225*2af541bfSCheng Xu 226*2af541bfSCheng Xu msleep(ERDMA_REG_ACCESS_WAIT_MS); 227*2af541bfSCheng Xu } 228*2af541bfSCheng Xu 229*2af541bfSCheng Xu if (i == ERDMA_WAIT_DEV_DONE_CNT) { 230*2af541bfSCheng Xu dev_err(&dev->pdev->dev, "wait init done failed.\n"); 231*2af541bfSCheng Xu err = -ETIMEDOUT; 232*2af541bfSCheng Xu goto err_destroy_eq; 233*2af541bfSCheng Xu } 234*2af541bfSCheng Xu 235*2af541bfSCheng Xu set_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state); 236*2af541bfSCheng Xu 237*2af541bfSCheng Xu return 0; 238*2af541bfSCheng Xu 239*2af541bfSCheng Xu err_destroy_eq: 240*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 241*2af541bfSCheng Xu (cmdq->eq.depth << EQE_SHIFT) + 242*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 243*2af541bfSCheng Xu cmdq->eq.qbuf, cmdq->eq.qbuf_dma_addr); 244*2af541bfSCheng Xu 245*2af541bfSCheng Xu err_destroy_cq: 246*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 247*2af541bfSCheng Xu (cmdq->cq.depth << CQE_SHIFT) + 248*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 249*2af541bfSCheng Xu cmdq->cq.qbuf, cmdq->cq.qbuf_dma_addr); 250*2af541bfSCheng Xu 251*2af541bfSCheng Xu err_destroy_sq: 252*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 253*2af541bfSCheng Xu (cmdq->sq.depth << SQEBB_SHIFT) + 254*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 255*2af541bfSCheng Xu cmdq->sq.qbuf, cmdq->sq.qbuf_dma_addr); 256*2af541bfSCheng Xu 257*2af541bfSCheng Xu return err; 258*2af541bfSCheng Xu } 259*2af541bfSCheng Xu 260*2af541bfSCheng Xu void erdma_finish_cmdq_init(struct erdma_dev *dev) 261*2af541bfSCheng Xu { 262*2af541bfSCheng Xu /* after device init successfully, change cmdq to event mode. */ 263*2af541bfSCheng Xu dev->cmdq.use_event = true; 264*2af541bfSCheng Xu arm_cmdq_cq(&dev->cmdq); 265*2af541bfSCheng Xu } 266*2af541bfSCheng Xu 267*2af541bfSCheng Xu void erdma_cmdq_destroy(struct erdma_dev *dev) 268*2af541bfSCheng Xu { 269*2af541bfSCheng Xu struct erdma_cmdq *cmdq = &dev->cmdq; 270*2af541bfSCheng Xu 271*2af541bfSCheng Xu clear_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state); 272*2af541bfSCheng Xu 273*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 274*2af541bfSCheng Xu (cmdq->eq.depth << EQE_SHIFT) + 275*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 276*2af541bfSCheng Xu cmdq->eq.qbuf, cmdq->eq.qbuf_dma_addr); 277*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 278*2af541bfSCheng Xu (cmdq->sq.depth << SQEBB_SHIFT) + 279*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 280*2af541bfSCheng Xu cmdq->sq.qbuf, cmdq->sq.qbuf_dma_addr); 281*2af541bfSCheng Xu dma_free_coherent(&dev->pdev->dev, 282*2af541bfSCheng Xu (cmdq->cq.depth << CQE_SHIFT) + 283*2af541bfSCheng Xu ERDMA_EXTRA_BUFFER_SIZE, 284*2af541bfSCheng Xu cmdq->cq.qbuf, cmdq->cq.qbuf_dma_addr); 285*2af541bfSCheng Xu } 286*2af541bfSCheng Xu 287*2af541bfSCheng Xu static void *get_next_valid_cmdq_cqe(struct erdma_cmdq *cmdq) 288*2af541bfSCheng Xu { 289*2af541bfSCheng Xu __be32 *cqe = get_queue_entry(cmdq->cq.qbuf, cmdq->cq.ci, 290*2af541bfSCheng Xu cmdq->cq.depth, CQE_SHIFT); 291*2af541bfSCheng Xu u32 owner = FIELD_GET(ERDMA_CQE_HDR_OWNER_MASK, 292*2af541bfSCheng Xu __be32_to_cpu(READ_ONCE(*cqe))); 293*2af541bfSCheng Xu 294*2af541bfSCheng Xu return owner ^ !!(cmdq->cq.ci & cmdq->cq.depth) ? cqe : NULL; 295*2af541bfSCheng Xu } 296*2af541bfSCheng Xu 297*2af541bfSCheng Xu static void push_cmdq_sqe(struct erdma_cmdq *cmdq, u64 *req, size_t req_len, 298*2af541bfSCheng Xu struct erdma_comp_wait *comp_wait) 299*2af541bfSCheng Xu { 300*2af541bfSCheng Xu __le64 *wqe; 301*2af541bfSCheng Xu u64 hdr = *req; 302*2af541bfSCheng Xu 303*2af541bfSCheng Xu comp_wait->cmd_status = ERDMA_CMD_STATUS_ISSUED; 304*2af541bfSCheng Xu reinit_completion(&comp_wait->wait_event); 305*2af541bfSCheng Xu comp_wait->sq_pi = cmdq->sq.pi; 306*2af541bfSCheng Xu 307*2af541bfSCheng Xu wqe = get_queue_entry(cmdq->sq.qbuf, cmdq->sq.pi, cmdq->sq.depth, 308*2af541bfSCheng Xu SQEBB_SHIFT); 309*2af541bfSCheng Xu memcpy(wqe, req, req_len); 310*2af541bfSCheng Xu 311*2af541bfSCheng Xu cmdq->sq.pi += cmdq->sq.wqebb_cnt; 312*2af541bfSCheng Xu hdr |= FIELD_PREP(ERDMA_CMD_HDR_WQEBB_INDEX_MASK, cmdq->sq.pi) | 313*2af541bfSCheng Xu FIELD_PREP(ERDMA_CMD_HDR_CONTEXT_COOKIE_MASK, 314*2af541bfSCheng Xu comp_wait->ctx_id) | 315*2af541bfSCheng Xu FIELD_PREP(ERDMA_CMD_HDR_WQEBB_CNT_MASK, cmdq->sq.wqebb_cnt - 1); 316*2af541bfSCheng Xu *wqe = cpu_to_le64(hdr); 317*2af541bfSCheng Xu 318*2af541bfSCheng Xu kick_cmdq_db(cmdq); 319*2af541bfSCheng Xu } 320*2af541bfSCheng Xu 321*2af541bfSCheng Xu static int erdma_poll_single_cmd_completion(struct erdma_cmdq *cmdq) 322*2af541bfSCheng Xu { 323*2af541bfSCheng Xu struct erdma_comp_wait *comp_wait; 324*2af541bfSCheng Xu u32 hdr0, sqe_idx; 325*2af541bfSCheng Xu __be32 *cqe; 326*2af541bfSCheng Xu u16 ctx_id; 327*2af541bfSCheng Xu u64 *sqe; 328*2af541bfSCheng Xu int i; 329*2af541bfSCheng Xu 330*2af541bfSCheng Xu cqe = get_next_valid_cmdq_cqe(cmdq); 331*2af541bfSCheng Xu if (!cqe) 332*2af541bfSCheng Xu return -EAGAIN; 333*2af541bfSCheng Xu 334*2af541bfSCheng Xu cmdq->cq.ci++; 335*2af541bfSCheng Xu 336*2af541bfSCheng Xu dma_rmb(); 337*2af541bfSCheng Xu hdr0 = __be32_to_cpu(*cqe); 338*2af541bfSCheng Xu sqe_idx = __be32_to_cpu(*(cqe + 1)); 339*2af541bfSCheng Xu 340*2af541bfSCheng Xu sqe = get_queue_entry(cmdq->sq.qbuf, sqe_idx, cmdq->sq.depth, 341*2af541bfSCheng Xu SQEBB_SHIFT); 342*2af541bfSCheng Xu ctx_id = FIELD_GET(ERDMA_CMD_HDR_CONTEXT_COOKIE_MASK, *sqe); 343*2af541bfSCheng Xu comp_wait = &cmdq->wait_pool[ctx_id]; 344*2af541bfSCheng Xu if (comp_wait->cmd_status != ERDMA_CMD_STATUS_ISSUED) 345*2af541bfSCheng Xu return -EIO; 346*2af541bfSCheng Xu 347*2af541bfSCheng Xu comp_wait->cmd_status = ERDMA_CMD_STATUS_FINISHED; 348*2af541bfSCheng Xu comp_wait->comp_status = FIELD_GET(ERDMA_CQE_HDR_SYNDROME_MASK, hdr0); 349*2af541bfSCheng Xu cmdq->sq.ci += cmdq->sq.wqebb_cnt; 350*2af541bfSCheng Xu 351*2af541bfSCheng Xu for (i = 0; i < 4; i++) 352*2af541bfSCheng Xu comp_wait->comp_data[i] = __be32_to_cpu(*(cqe + 2 + i)); 353*2af541bfSCheng Xu 354*2af541bfSCheng Xu if (cmdq->use_event) 355*2af541bfSCheng Xu complete(&comp_wait->wait_event); 356*2af541bfSCheng Xu 357*2af541bfSCheng Xu return 0; 358*2af541bfSCheng Xu } 359*2af541bfSCheng Xu 360*2af541bfSCheng Xu static void erdma_polling_cmd_completions(struct erdma_cmdq *cmdq) 361*2af541bfSCheng Xu { 362*2af541bfSCheng Xu unsigned long flags; 363*2af541bfSCheng Xu u16 comp_num; 364*2af541bfSCheng Xu 365*2af541bfSCheng Xu spin_lock_irqsave(&cmdq->cq.lock, flags); 366*2af541bfSCheng Xu 367*2af541bfSCheng Xu /* We must have less than # of max_outstandings 368*2af541bfSCheng Xu * completions at one time. 369*2af541bfSCheng Xu */ 370*2af541bfSCheng Xu for (comp_num = 0; comp_num < cmdq->max_outstandings; comp_num++) 371*2af541bfSCheng Xu if (erdma_poll_single_cmd_completion(cmdq)) 372*2af541bfSCheng Xu break; 373*2af541bfSCheng Xu 374*2af541bfSCheng Xu if (comp_num && cmdq->use_event) 375*2af541bfSCheng Xu arm_cmdq_cq(cmdq); 376*2af541bfSCheng Xu 377*2af541bfSCheng Xu spin_unlock_irqrestore(&cmdq->cq.lock, flags); 378*2af541bfSCheng Xu } 379*2af541bfSCheng Xu 380*2af541bfSCheng Xu void erdma_cmdq_completion_handler(struct erdma_cmdq *cmdq) 381*2af541bfSCheng Xu { 382*2af541bfSCheng Xu int got_event = 0; 383*2af541bfSCheng Xu 384*2af541bfSCheng Xu if (!test_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state) || 385*2af541bfSCheng Xu !cmdq->use_event) 386*2af541bfSCheng Xu return; 387*2af541bfSCheng Xu 388*2af541bfSCheng Xu while (get_next_valid_eqe(&cmdq->eq)) { 389*2af541bfSCheng Xu cmdq->eq.ci++; 390*2af541bfSCheng Xu got_event++; 391*2af541bfSCheng Xu } 392*2af541bfSCheng Xu 393*2af541bfSCheng Xu if (got_event) { 394*2af541bfSCheng Xu cmdq->cq.cmdsn++; 395*2af541bfSCheng Xu erdma_polling_cmd_completions(cmdq); 396*2af541bfSCheng Xu } 397*2af541bfSCheng Xu 398*2af541bfSCheng Xu notify_eq(&cmdq->eq); 399*2af541bfSCheng Xu } 400*2af541bfSCheng Xu 401*2af541bfSCheng Xu static int erdma_poll_cmd_completion(struct erdma_comp_wait *comp_ctx, 402*2af541bfSCheng Xu struct erdma_cmdq *cmdq, u32 timeout) 403*2af541bfSCheng Xu { 404*2af541bfSCheng Xu unsigned long comp_timeout = jiffies + msecs_to_jiffies(timeout); 405*2af541bfSCheng Xu 406*2af541bfSCheng Xu while (1) { 407*2af541bfSCheng Xu erdma_polling_cmd_completions(cmdq); 408*2af541bfSCheng Xu if (comp_ctx->cmd_status != ERDMA_CMD_STATUS_ISSUED) 409*2af541bfSCheng Xu break; 410*2af541bfSCheng Xu 411*2af541bfSCheng Xu if (time_is_before_jiffies(comp_timeout)) 412*2af541bfSCheng Xu return -ETIME; 413*2af541bfSCheng Xu 414*2af541bfSCheng Xu msleep(20); 415*2af541bfSCheng Xu } 416*2af541bfSCheng Xu 417*2af541bfSCheng Xu return 0; 418*2af541bfSCheng Xu } 419*2af541bfSCheng Xu 420*2af541bfSCheng Xu static int erdma_wait_cmd_completion(struct erdma_comp_wait *comp_ctx, 421*2af541bfSCheng Xu struct erdma_cmdq *cmdq, u32 timeout) 422*2af541bfSCheng Xu { 423*2af541bfSCheng Xu unsigned long flags = 0; 424*2af541bfSCheng Xu 425*2af541bfSCheng Xu wait_for_completion_timeout(&comp_ctx->wait_event, 426*2af541bfSCheng Xu msecs_to_jiffies(timeout)); 427*2af541bfSCheng Xu 428*2af541bfSCheng Xu if (unlikely(comp_ctx->cmd_status != ERDMA_CMD_STATUS_FINISHED)) { 429*2af541bfSCheng Xu spin_lock_irqsave(&cmdq->cq.lock, flags); 430*2af541bfSCheng Xu comp_ctx->cmd_status = ERDMA_CMD_STATUS_TIMEOUT; 431*2af541bfSCheng Xu spin_unlock_irqrestore(&cmdq->cq.lock, flags); 432*2af541bfSCheng Xu return -ETIME; 433*2af541bfSCheng Xu } 434*2af541bfSCheng Xu 435*2af541bfSCheng Xu return 0; 436*2af541bfSCheng Xu } 437*2af541bfSCheng Xu 438*2af541bfSCheng Xu void erdma_cmdq_build_reqhdr(u64 *hdr, u32 mod, u32 op) 439*2af541bfSCheng Xu { 440*2af541bfSCheng Xu *hdr = FIELD_PREP(ERDMA_CMD_HDR_SUB_MOD_MASK, mod) | 441*2af541bfSCheng Xu FIELD_PREP(ERDMA_CMD_HDR_OPCODE_MASK, op); 442*2af541bfSCheng Xu } 443*2af541bfSCheng Xu 444*2af541bfSCheng Xu int erdma_post_cmd_wait(struct erdma_cmdq *cmdq, u64 *req, u32 req_size, 445*2af541bfSCheng Xu u64 *resp0, u64 *resp1) 446*2af541bfSCheng Xu { 447*2af541bfSCheng Xu struct erdma_comp_wait *comp_wait; 448*2af541bfSCheng Xu int ret; 449*2af541bfSCheng Xu 450*2af541bfSCheng Xu if (!test_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state)) 451*2af541bfSCheng Xu return -ENODEV; 452*2af541bfSCheng Xu 453*2af541bfSCheng Xu down(&cmdq->credits); 454*2af541bfSCheng Xu 455*2af541bfSCheng Xu comp_wait = get_comp_wait(cmdq); 456*2af541bfSCheng Xu if (IS_ERR(comp_wait)) { 457*2af541bfSCheng Xu clear_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state); 458*2af541bfSCheng Xu set_bit(ERDMA_CMDQ_STATE_CTX_ERR_BIT, &cmdq->state); 459*2af541bfSCheng Xu up(&cmdq->credits); 460*2af541bfSCheng Xu return PTR_ERR(comp_wait); 461*2af541bfSCheng Xu } 462*2af541bfSCheng Xu 463*2af541bfSCheng Xu spin_lock(&cmdq->sq.lock); 464*2af541bfSCheng Xu push_cmdq_sqe(cmdq, req, req_size, comp_wait); 465*2af541bfSCheng Xu spin_unlock(&cmdq->sq.lock); 466*2af541bfSCheng Xu 467*2af541bfSCheng Xu if (cmdq->use_event) 468*2af541bfSCheng Xu ret = erdma_wait_cmd_completion(comp_wait, cmdq, 469*2af541bfSCheng Xu ERDMA_CMDQ_TIMEOUT_MS); 470*2af541bfSCheng Xu else 471*2af541bfSCheng Xu ret = erdma_poll_cmd_completion(comp_wait, cmdq, 472*2af541bfSCheng Xu ERDMA_CMDQ_TIMEOUT_MS); 473*2af541bfSCheng Xu 474*2af541bfSCheng Xu if (ret) { 475*2af541bfSCheng Xu set_bit(ERDMA_CMDQ_STATE_TIMEOUT_BIT, &cmdq->state); 476*2af541bfSCheng Xu clear_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state); 477*2af541bfSCheng Xu goto out; 478*2af541bfSCheng Xu } 479*2af541bfSCheng Xu 480*2af541bfSCheng Xu if (comp_wait->comp_status) 481*2af541bfSCheng Xu ret = -EIO; 482*2af541bfSCheng Xu 483*2af541bfSCheng Xu if (resp0 && resp1) { 484*2af541bfSCheng Xu *resp0 = *((u64 *)&comp_wait->comp_data[0]); 485*2af541bfSCheng Xu *resp1 = *((u64 *)&comp_wait->comp_data[2]); 486*2af541bfSCheng Xu } 487*2af541bfSCheng Xu put_comp_wait(cmdq, comp_wait); 488*2af541bfSCheng Xu 489*2af541bfSCheng Xu out: 490*2af541bfSCheng Xu up(&cmdq->credits); 491*2af541bfSCheng Xu 492*2af541bfSCheng Xu return ret; 493*2af541bfSCheng Xu } 494