1*db03a1ceSFan Gong // SPDX-License-Identifier: GPL-2.0 2*db03a1ceSFan Gong // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3*db03a1ceSFan Gong 4*db03a1ceSFan Gong #include <linux/bitfield.h> 5*db03a1ceSFan Gong #include <linux/dma-mapping.h> 6*db03a1ceSFan Gong 7*db03a1ceSFan Gong #include "hinic3_cmdq.h" 8*db03a1ceSFan Gong #include "hinic3_hwdev.h" 9*db03a1ceSFan Gong #include "hinic3_hwif.h" 10*db03a1ceSFan Gong #include "hinic3_mbox.h" 11*db03a1ceSFan Gong 12*db03a1ceSFan Gong #define CMDQ_BUF_SIZE 2048 13*db03a1ceSFan Gong #define CMDQ_WQEBB_SIZE 64 14*db03a1ceSFan Gong 15*db03a1ceSFan Gong #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK GENMASK_ULL(51, 0) 16*db03a1ceSFan Gong #define CMDQ_CTXT_EQ_ID_MASK GENMASK_ULL(60, 53) 17*db03a1ceSFan Gong #define CMDQ_CTXT_CEQ_ARM_MASK BIT_ULL(61) 18*db03a1ceSFan Gong #define CMDQ_CTXT_CEQ_EN_MASK BIT_ULL(62) 19*db03a1ceSFan Gong #define CMDQ_CTXT_HW_BUSY_BIT_MASK BIT_ULL(63) 20*db03a1ceSFan Gong 21*db03a1ceSFan Gong #define CMDQ_CTXT_WQ_BLOCK_PFN_MASK GENMASK_ULL(51, 0) 22*db03a1ceSFan Gong #define CMDQ_CTXT_CI_MASK GENMASK_ULL(63, 52) 23*db03a1ceSFan Gong #define CMDQ_CTXT_SET(val, member) \ 24*db03a1ceSFan Gong FIELD_PREP(CMDQ_CTXT_##member##_MASK, val) 25*db03a1ceSFan Gong 26*db03a1ceSFan Gong #define CMDQ_PFN(addr) ((addr) >> 12) 27*db03a1ceSFan Gong 28*db03a1ceSFan Gong /* cmdq work queue's chip logical address table is up to 512B */ 29*db03a1ceSFan Gong #define CMDQ_WQ_CLA_SIZE 512 30*db03a1ceSFan Gong 31*db03a1ceSFan Gong /* Completion codes: send, direct sync, force stop */ 32*db03a1ceSFan Gong #define CMDQ_SEND_CMPT_CODE 10 33*db03a1ceSFan Gong #define CMDQ_DIRECT_SYNC_CMPT_CODE 11 34*db03a1ceSFan Gong #define CMDQ_FORCE_STOP_CMPT_CODE 12 35*db03a1ceSFan Gong 36*db03a1ceSFan Gong #define CMDQ_WQE_NUM_WQEBBS 1 37*db03a1ceSFan Gong 38*db03a1ceSFan Gong static struct cmdq_wqe *cmdq_read_wqe(struct hinic3_wq *wq, u16 *ci) 39*db03a1ceSFan Gong { 40*db03a1ceSFan Gong if (hinic3_wq_get_used(wq) == 0) 41*db03a1ceSFan Gong return NULL; 42*db03a1ceSFan Gong 43*db03a1ceSFan Gong *ci = wq->cons_idx & wq->idx_mask; 44*db03a1ceSFan Gong 45*db03a1ceSFan Gong return get_q_element(&wq->qpages, wq->cons_idx, NULL); 46*db03a1ceSFan Gong } 47*db03a1ceSFan Gong 48*db03a1ceSFan Gong void hinic3_free_cmd_buf(struct hinic3_hwdev *hwdev, 49*db03a1ceSFan Gong struct hinic3_cmd_buf *cmd_buf) 50*db03a1ceSFan Gong { 51*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs; 52*db03a1ceSFan Gong 53*db03a1ceSFan Gong if (!refcount_dec_and_test(&cmd_buf->ref_cnt)) 54*db03a1ceSFan Gong return; 55*db03a1ceSFan Gong 56*db03a1ceSFan Gong cmdqs = hwdev->cmdqs; 57*db03a1ceSFan Gong 58*db03a1ceSFan Gong dma_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr); 59*db03a1ceSFan Gong kfree(cmd_buf); 60*db03a1ceSFan Gong } 61*db03a1ceSFan Gong 62*db03a1ceSFan Gong static void cmdq_clear_cmd_buf(struct hinic3_cmdq_cmd_info *cmd_info, 63*db03a1ceSFan Gong struct hinic3_hwdev *hwdev) 64*db03a1ceSFan Gong { 65*db03a1ceSFan Gong if (cmd_info->buf_in) { 66*db03a1ceSFan Gong hinic3_free_cmd_buf(hwdev, cmd_info->buf_in); 67*db03a1ceSFan Gong cmd_info->buf_in = NULL; 68*db03a1ceSFan Gong } 69*db03a1ceSFan Gong } 70*db03a1ceSFan Gong 71*db03a1ceSFan Gong static void cmdq_init_queue_ctxt(struct hinic3_hwdev *hwdev, u8 cmdq_id, 72*db03a1ceSFan Gong struct comm_cmdq_ctxt_info *ctxt_info) 73*db03a1ceSFan Gong { 74*db03a1ceSFan Gong const struct hinic3_cmdqs *cmdqs; 75*db03a1ceSFan Gong u64 cmdq_first_block_paddr, pfn; 76*db03a1ceSFan Gong const struct hinic3_wq *wq; 77*db03a1ceSFan Gong 78*db03a1ceSFan Gong cmdqs = hwdev->cmdqs; 79*db03a1ceSFan Gong wq = &cmdqs->cmdq[cmdq_id].wq; 80*db03a1ceSFan Gong pfn = CMDQ_PFN(hinic3_wq_get_first_wqe_page_addr(wq)); 81*db03a1ceSFan Gong 82*db03a1ceSFan Gong ctxt_info->curr_wqe_page_pfn = 83*db03a1ceSFan Gong cpu_to_le64(CMDQ_CTXT_SET(1, HW_BUSY_BIT) | 84*db03a1ceSFan Gong CMDQ_CTXT_SET(1, CEQ_EN) | 85*db03a1ceSFan Gong CMDQ_CTXT_SET(1, CEQ_ARM) | 86*db03a1ceSFan Gong CMDQ_CTXT_SET(0, EQ_ID) | 87*db03a1ceSFan Gong CMDQ_CTXT_SET(pfn, CURR_WQE_PAGE_PFN)); 88*db03a1ceSFan Gong 89*db03a1ceSFan Gong if (!hinic3_wq_is_0_level_cla(wq)) { 90*db03a1ceSFan Gong cmdq_first_block_paddr = cmdqs->wq_block_paddr; 91*db03a1ceSFan Gong pfn = CMDQ_PFN(cmdq_first_block_paddr); 92*db03a1ceSFan Gong } 93*db03a1ceSFan Gong 94*db03a1ceSFan Gong ctxt_info->wq_block_pfn = cpu_to_le64(CMDQ_CTXT_SET(wq->cons_idx, CI) | 95*db03a1ceSFan Gong CMDQ_CTXT_SET(pfn, WQ_BLOCK_PFN)); 96*db03a1ceSFan Gong } 97*db03a1ceSFan Gong 98*db03a1ceSFan Gong static int init_cmdq(struct hinic3_cmdq *cmdq, struct hinic3_hwdev *hwdev, 99*db03a1ceSFan Gong enum hinic3_cmdq_type q_type) 100*db03a1ceSFan Gong { 101*db03a1ceSFan Gong int err; 102*db03a1ceSFan Gong 103*db03a1ceSFan Gong cmdq->cmdq_type = q_type; 104*db03a1ceSFan Gong cmdq->wrapped = 1; 105*db03a1ceSFan Gong cmdq->hwdev = hwdev; 106*db03a1ceSFan Gong 107*db03a1ceSFan Gong spin_lock_init(&cmdq->cmdq_lock); 108*db03a1ceSFan Gong 109*db03a1ceSFan Gong cmdq->cmd_infos = kcalloc(cmdq->wq.q_depth, sizeof(*cmdq->cmd_infos), 110*db03a1ceSFan Gong GFP_KERNEL); 111*db03a1ceSFan Gong if (!cmdq->cmd_infos) { 112*db03a1ceSFan Gong err = -ENOMEM; 113*db03a1ceSFan Gong return err; 114*db03a1ceSFan Gong } 115*db03a1ceSFan Gong 116*db03a1ceSFan Gong return 0; 117*db03a1ceSFan Gong } 118*db03a1ceSFan Gong 119*db03a1ceSFan Gong static int hinic3_set_cmdq_ctxt(struct hinic3_hwdev *hwdev, u8 cmdq_id) 120*db03a1ceSFan Gong { 121*db03a1ceSFan Gong struct comm_cmd_set_cmdq_ctxt cmdq_ctxt = {}; 122*db03a1ceSFan Gong struct mgmt_msg_params msg_params = {}; 123*db03a1ceSFan Gong int err; 124*db03a1ceSFan Gong 125*db03a1ceSFan Gong cmdq_init_queue_ctxt(hwdev, cmdq_id, &cmdq_ctxt.ctxt); 126*db03a1ceSFan Gong cmdq_ctxt.func_id = hinic3_global_func_id(hwdev); 127*db03a1ceSFan Gong cmdq_ctxt.cmdq_id = cmdq_id; 128*db03a1ceSFan Gong 129*db03a1ceSFan Gong mgmt_msg_params_init_default(&msg_params, &cmdq_ctxt, 130*db03a1ceSFan Gong sizeof(cmdq_ctxt)); 131*db03a1ceSFan Gong 132*db03a1ceSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 133*db03a1ceSFan Gong COMM_CMD_SET_CMDQ_CTXT, &msg_params); 134*db03a1ceSFan Gong if (err || cmdq_ctxt.head.status) { 135*db03a1ceSFan Gong dev_err(hwdev->dev, "Failed to set cmdq ctxt, err: %d, status: 0x%x\n", 136*db03a1ceSFan Gong err, cmdq_ctxt.head.status); 137*db03a1ceSFan Gong return -EFAULT; 138*db03a1ceSFan Gong } 139*db03a1ceSFan Gong 140*db03a1ceSFan Gong return 0; 141*db03a1ceSFan Gong } 142*db03a1ceSFan Gong 143*db03a1ceSFan Gong static int hinic3_set_cmdq_ctxts(struct hinic3_hwdev *hwdev) 144*db03a1ceSFan Gong { 145*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs = hwdev->cmdqs; 146*db03a1ceSFan Gong u8 cmdq_type; 147*db03a1ceSFan Gong int err; 148*db03a1ceSFan Gong 149*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { 150*db03a1ceSFan Gong err = hinic3_set_cmdq_ctxt(hwdev, cmdq_type); 151*db03a1ceSFan Gong if (err) 152*db03a1ceSFan Gong return err; 153*db03a1ceSFan Gong } 154*db03a1ceSFan Gong 155*db03a1ceSFan Gong cmdqs->status |= HINIC3_CMDQ_ENABLE; 156*db03a1ceSFan Gong cmdqs->disable_flag = 0; 157*db03a1ceSFan Gong 158*db03a1ceSFan Gong return 0; 159*db03a1ceSFan Gong } 160*db03a1ceSFan Gong 161*db03a1ceSFan Gong static int create_cmdq_wq(struct hinic3_hwdev *hwdev, 162*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs) 163*db03a1ceSFan Gong { 164*db03a1ceSFan Gong u8 cmdq_type; 165*db03a1ceSFan Gong int err; 166*db03a1ceSFan Gong 167*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { 168*db03a1ceSFan Gong err = hinic3_wq_create(hwdev, &cmdqs->cmdq[cmdq_type].wq, 169*db03a1ceSFan Gong CMDQ_DEPTH, CMDQ_WQEBB_SIZE); 170*db03a1ceSFan Gong if (err) { 171*db03a1ceSFan Gong dev_err(hwdev->dev, "Failed to create cmdq wq\n"); 172*db03a1ceSFan Gong goto err_destroy_wq; 173*db03a1ceSFan Gong } 174*db03a1ceSFan Gong } 175*db03a1ceSFan Gong 176*db03a1ceSFan Gong /* 1-level Chip Logical Address (CLA) must put all 177*db03a1ceSFan Gong * cmdq's wq page addr in one wq block 178*db03a1ceSFan Gong */ 179*db03a1ceSFan Gong if (!hinic3_wq_is_0_level_cla(&cmdqs->cmdq[HINIC3_CMDQ_SYNC].wq)) { 180*db03a1ceSFan Gong if (cmdqs->cmdq[HINIC3_CMDQ_SYNC].wq.qpages.num_pages > 181*db03a1ceSFan Gong CMDQ_WQ_CLA_SIZE / sizeof(u64)) { 182*db03a1ceSFan Gong err = -EINVAL; 183*db03a1ceSFan Gong dev_err(hwdev->dev, 184*db03a1ceSFan Gong "Cmdq number of wq pages exceeds limit: %lu\n", 185*db03a1ceSFan Gong CMDQ_WQ_CLA_SIZE / sizeof(u64)); 186*db03a1ceSFan Gong goto err_destroy_wq; 187*db03a1ceSFan Gong } 188*db03a1ceSFan Gong 189*db03a1ceSFan Gong cmdqs->wq_block_vaddr = 190*db03a1ceSFan Gong dma_alloc_coherent(hwdev->dev, HINIC3_MIN_PAGE_SIZE, 191*db03a1ceSFan Gong &cmdqs->wq_block_paddr, GFP_KERNEL); 192*db03a1ceSFan Gong if (!cmdqs->wq_block_vaddr) { 193*db03a1ceSFan Gong err = -ENOMEM; 194*db03a1ceSFan Gong goto err_destroy_wq; 195*db03a1ceSFan Gong } 196*db03a1ceSFan Gong 197*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) 198*db03a1ceSFan Gong memcpy((u8 *)cmdqs->wq_block_vaddr + 199*db03a1ceSFan Gong CMDQ_WQ_CLA_SIZE * cmdq_type, 200*db03a1ceSFan Gong cmdqs->cmdq[cmdq_type].wq.wq_block_vaddr, 201*db03a1ceSFan Gong cmdqs->cmdq[cmdq_type].wq.qpages.num_pages * 202*db03a1ceSFan Gong sizeof(__be64)); 203*db03a1ceSFan Gong } 204*db03a1ceSFan Gong 205*db03a1ceSFan Gong return 0; 206*db03a1ceSFan Gong 207*db03a1ceSFan Gong err_destroy_wq: 208*db03a1ceSFan Gong while (cmdq_type > 0) { 209*db03a1ceSFan Gong cmdq_type--; 210*db03a1ceSFan Gong hinic3_wq_destroy(hwdev, &cmdqs->cmdq[cmdq_type].wq); 211*db03a1ceSFan Gong } 212*db03a1ceSFan Gong 213*db03a1ceSFan Gong return err; 214*db03a1ceSFan Gong } 215*db03a1ceSFan Gong 216*db03a1ceSFan Gong static void destroy_cmdq_wq(struct hinic3_hwdev *hwdev, 217*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs) 218*db03a1ceSFan Gong { 219*db03a1ceSFan Gong u8 cmdq_type; 220*db03a1ceSFan Gong 221*db03a1ceSFan Gong if (cmdqs->wq_block_vaddr) 222*db03a1ceSFan Gong dma_free_coherent(hwdev->dev, HINIC3_MIN_PAGE_SIZE, 223*db03a1ceSFan Gong cmdqs->wq_block_vaddr, cmdqs->wq_block_paddr); 224*db03a1ceSFan Gong 225*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) 226*db03a1ceSFan Gong hinic3_wq_destroy(hwdev, &cmdqs->cmdq[cmdq_type].wq); 227*db03a1ceSFan Gong } 228*db03a1ceSFan Gong 229*db03a1ceSFan Gong static int init_cmdqs(struct hinic3_hwdev *hwdev) 230*db03a1ceSFan Gong { 231*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs; 232*db03a1ceSFan Gong 233*db03a1ceSFan Gong cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL); 234*db03a1ceSFan Gong if (!cmdqs) 235*db03a1ceSFan Gong return -ENOMEM; 236*db03a1ceSFan Gong 237*db03a1ceSFan Gong hwdev->cmdqs = cmdqs; 238*db03a1ceSFan Gong cmdqs->hwdev = hwdev; 239*db03a1ceSFan Gong cmdqs->cmdq_num = hwdev->max_cmdq; 240*db03a1ceSFan Gong 241*db03a1ceSFan Gong cmdqs->cmd_buf_pool = dma_pool_create("hinic3_cmdq", hwdev->dev, 242*db03a1ceSFan Gong CMDQ_BUF_SIZE, CMDQ_BUF_SIZE, 0); 243*db03a1ceSFan Gong if (!cmdqs->cmd_buf_pool) { 244*db03a1ceSFan Gong dev_err(hwdev->dev, "Failed to create cmdq buffer pool\n"); 245*db03a1ceSFan Gong kfree(cmdqs); 246*db03a1ceSFan Gong return -ENOMEM; 247*db03a1ceSFan Gong } 248*db03a1ceSFan Gong 249*db03a1ceSFan Gong return 0; 250*db03a1ceSFan Gong } 251*db03a1ceSFan Gong 252*db03a1ceSFan Gong static void cmdq_flush_sync_cmd(struct hinic3_cmdq_cmd_info *cmd_info) 253*db03a1ceSFan Gong { 254*db03a1ceSFan Gong if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP) 255*db03a1ceSFan Gong return; 256*db03a1ceSFan Gong 257*db03a1ceSFan Gong cmd_info->cmd_type = HINIC3_CMD_TYPE_FORCE_STOP; 258*db03a1ceSFan Gong 259*db03a1ceSFan Gong if (cmd_info->cmpt_code && 260*db03a1ceSFan Gong *cmd_info->cmpt_code == CMDQ_SEND_CMPT_CODE) 261*db03a1ceSFan Gong *cmd_info->cmpt_code = CMDQ_FORCE_STOP_CMPT_CODE; 262*db03a1ceSFan Gong 263*db03a1ceSFan Gong if (cmd_info->done) { 264*db03a1ceSFan Gong complete(cmd_info->done); 265*db03a1ceSFan Gong cmd_info->done = NULL; 266*db03a1ceSFan Gong cmd_info->cmpt_code = NULL; 267*db03a1ceSFan Gong cmd_info->direct_resp = NULL; 268*db03a1ceSFan Gong cmd_info->errcode = NULL; 269*db03a1ceSFan Gong } 270*db03a1ceSFan Gong } 271*db03a1ceSFan Gong 272*db03a1ceSFan Gong static void hinic3_cmdq_flush_cmd(struct hinic3_cmdq *cmdq) 273*db03a1ceSFan Gong { 274*db03a1ceSFan Gong struct hinic3_cmdq_cmd_info *cmd_info; 275*db03a1ceSFan Gong u16 ci; 276*db03a1ceSFan Gong 277*db03a1ceSFan Gong spin_lock_bh(&cmdq->cmdq_lock); 278*db03a1ceSFan Gong while (cmdq_read_wqe(&cmdq->wq, &ci)) { 279*db03a1ceSFan Gong hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS); 280*db03a1ceSFan Gong cmd_info = &cmdq->cmd_infos[ci]; 281*db03a1ceSFan Gong if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP) 282*db03a1ceSFan Gong cmdq_flush_sync_cmd(cmd_info); 283*db03a1ceSFan Gong } 284*db03a1ceSFan Gong spin_unlock_bh(&cmdq->cmdq_lock); 285*db03a1ceSFan Gong } 286*db03a1ceSFan Gong 287*db03a1ceSFan Gong void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev) 288*db03a1ceSFan Gong { 289*db03a1ceSFan Gong struct hinic3_cmdq *cmdq; 290*db03a1ceSFan Gong u16 wqe_cnt, wqe_idx, i; 291*db03a1ceSFan Gong struct hinic3_wq *wq; 292*db03a1ceSFan Gong 293*db03a1ceSFan Gong cmdq = &hwdev->cmdqs->cmdq[HINIC3_CMDQ_SYNC]; 294*db03a1ceSFan Gong spin_lock_bh(&cmdq->cmdq_lock); 295*db03a1ceSFan Gong wq = &cmdq->wq; 296*db03a1ceSFan Gong wqe_cnt = hinic3_wq_get_used(wq); 297*db03a1ceSFan Gong for (i = 0; i < wqe_cnt; i++) { 298*db03a1ceSFan Gong wqe_idx = (wq->cons_idx + i) & wq->idx_mask; 299*db03a1ceSFan Gong cmdq_flush_sync_cmd(cmdq->cmd_infos + wqe_idx); 300*db03a1ceSFan Gong } 301*db03a1ceSFan Gong spin_unlock_bh(&cmdq->cmdq_lock); 302*db03a1ceSFan Gong } 303*db03a1ceSFan Gong 304*db03a1ceSFan Gong static void hinic3_cmdq_reset_all_cmd_buf(struct hinic3_cmdq *cmdq) 305*db03a1ceSFan Gong { 306*db03a1ceSFan Gong u16 i; 307*db03a1ceSFan Gong 308*db03a1ceSFan Gong for (i = 0; i < cmdq->wq.q_depth; i++) 309*db03a1ceSFan Gong cmdq_clear_cmd_buf(&cmdq->cmd_infos[i], cmdq->hwdev); 310*db03a1ceSFan Gong } 311*db03a1ceSFan Gong 312*db03a1ceSFan Gong int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev) 313*db03a1ceSFan Gong { 314*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs = hwdev->cmdqs; 315*db03a1ceSFan Gong u8 cmdq_type; 316*db03a1ceSFan Gong 317*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { 318*db03a1ceSFan Gong hinic3_cmdq_flush_cmd(&cmdqs->cmdq[cmdq_type]); 319*db03a1ceSFan Gong hinic3_cmdq_reset_all_cmd_buf(&cmdqs->cmdq[cmdq_type]); 320*db03a1ceSFan Gong cmdqs->cmdq[cmdq_type].wrapped = 1; 321*db03a1ceSFan Gong hinic3_wq_reset(&cmdqs->cmdq[cmdq_type].wq); 322*db03a1ceSFan Gong } 323*db03a1ceSFan Gong 324*db03a1ceSFan Gong return hinic3_set_cmdq_ctxts(hwdev); 325*db03a1ceSFan Gong } 326*db03a1ceSFan Gong 327*db03a1ceSFan Gong int hinic3_cmdqs_init(struct hinic3_hwdev *hwdev) 328*db03a1ceSFan Gong { 329*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs; 330*db03a1ceSFan Gong void __iomem *db_base; 331*db03a1ceSFan Gong u8 cmdq_type; 332*db03a1ceSFan Gong int err; 333*db03a1ceSFan Gong 334*db03a1ceSFan Gong err = init_cmdqs(hwdev); 335*db03a1ceSFan Gong if (err) 336*db03a1ceSFan Gong goto err_out; 337*db03a1ceSFan Gong 338*db03a1ceSFan Gong cmdqs = hwdev->cmdqs; 339*db03a1ceSFan Gong err = create_cmdq_wq(hwdev, cmdqs); 340*db03a1ceSFan Gong if (err) 341*db03a1ceSFan Gong goto err_free_cmdqs; 342*db03a1ceSFan Gong 343*db03a1ceSFan Gong err = hinic3_alloc_db_addr(hwdev, &db_base, NULL); 344*db03a1ceSFan Gong if (err) { 345*db03a1ceSFan Gong dev_err(hwdev->dev, "Failed to allocate doorbell address\n"); 346*db03a1ceSFan Gong goto err_destroy_cmdq_wq; 347*db03a1ceSFan Gong } 348*db03a1ceSFan Gong cmdqs->cmdqs_db_base = db_base; 349*db03a1ceSFan Gong 350*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { 351*db03a1ceSFan Gong err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev, cmdq_type); 352*db03a1ceSFan Gong if (err) { 353*db03a1ceSFan Gong dev_err(hwdev->dev, 354*db03a1ceSFan Gong "Failed to initialize cmdq type : %d\n", 355*db03a1ceSFan Gong cmdq_type); 356*db03a1ceSFan Gong goto err_free_cmd_infos; 357*db03a1ceSFan Gong } 358*db03a1ceSFan Gong } 359*db03a1ceSFan Gong 360*db03a1ceSFan Gong err = hinic3_set_cmdq_ctxts(hwdev); 361*db03a1ceSFan Gong if (err) 362*db03a1ceSFan Gong goto err_free_cmd_infos; 363*db03a1ceSFan Gong 364*db03a1ceSFan Gong return 0; 365*db03a1ceSFan Gong 366*db03a1ceSFan Gong err_free_cmd_infos: 367*db03a1ceSFan Gong while (cmdq_type > 0) { 368*db03a1ceSFan Gong cmdq_type--; 369*db03a1ceSFan Gong kfree(cmdqs->cmdq[cmdq_type].cmd_infos); 370*db03a1ceSFan Gong } 371*db03a1ceSFan Gong 372*db03a1ceSFan Gong hinic3_free_db_addr(hwdev, cmdqs->cmdqs_db_base); 373*db03a1ceSFan Gong 374*db03a1ceSFan Gong err_destroy_cmdq_wq: 375*db03a1ceSFan Gong destroy_cmdq_wq(hwdev, cmdqs); 376*db03a1ceSFan Gong 377*db03a1ceSFan Gong err_free_cmdqs: 378*db03a1ceSFan Gong dma_pool_destroy(cmdqs->cmd_buf_pool); 379*db03a1ceSFan Gong kfree(cmdqs); 380*db03a1ceSFan Gong 381*db03a1ceSFan Gong err_out: 382*db03a1ceSFan Gong return err; 383*db03a1ceSFan Gong } 384*db03a1ceSFan Gong 385*db03a1ceSFan Gong void hinic3_cmdqs_free(struct hinic3_hwdev *hwdev) 386*db03a1ceSFan Gong { 387*db03a1ceSFan Gong struct hinic3_cmdqs *cmdqs = hwdev->cmdqs; 388*db03a1ceSFan Gong u8 cmdq_type; 389*db03a1ceSFan Gong 390*db03a1ceSFan Gong cmdqs->status &= ~HINIC3_CMDQ_ENABLE; 391*db03a1ceSFan Gong 392*db03a1ceSFan Gong for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { 393*db03a1ceSFan Gong hinic3_cmdq_flush_cmd(&cmdqs->cmdq[cmdq_type]); 394*db03a1ceSFan Gong hinic3_cmdq_reset_all_cmd_buf(&cmdqs->cmdq[cmdq_type]); 395*db03a1ceSFan Gong kfree(cmdqs->cmdq[cmdq_type].cmd_infos); 396*db03a1ceSFan Gong } 397*db03a1ceSFan Gong 398*db03a1ceSFan Gong hinic3_free_db_addr(hwdev, cmdqs->cmdqs_db_base); 399*db03a1ceSFan Gong destroy_cmdq_wq(hwdev, cmdqs); 400*db03a1ceSFan Gong dma_pool_destroy(cmdqs->cmd_buf_pool); 401*db03a1ceSFan Gong kfree(cmdqs); 402*db03a1ceSFan Gong } 403*db03a1ceSFan Gong 404*db03a1ceSFan Gong bool hinic3_cmdq_idle(struct hinic3_cmdq *cmdq) 405*db03a1ceSFan Gong { 406*db03a1ceSFan Gong return hinic3_wq_get_used(&cmdq->wq) == 0; 407*db03a1ceSFan Gong } 408