1 /* 2 * Huawei HiNIC PCI Express Linux driver 3 * Copyright(c) 2017 Huawei Technologies Co., Ltd 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 */ 15 16 #ifndef HINIC_CMDQ_H 17 #define HINIC_CMDQ_H 18 19 #include <linux/types.h> 20 #include <linux/spinlock.h> 21 #include <linux/completion.h> 22 #include <linux/pci.h> 23 24 #include "hinic_hw_if.h" 25 #include "hinic_hw_wq.h" 26 27 #define HINIC_CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0 28 #define HINIC_CMDQ_CTXT_EQ_ID_SHIFT 56 29 #define HINIC_CMDQ_CTXT_CEQ_ARM_SHIFT 61 30 #define HINIC_CMDQ_CTXT_CEQ_EN_SHIFT 62 31 #define HINIC_CMDQ_CTXT_WRAPPED_SHIFT 63 32 33 #define HINIC_CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF 34 #define HINIC_CMDQ_CTXT_EQ_ID_MASK 0x1F 35 #define HINIC_CMDQ_CTXT_CEQ_ARM_MASK 0x1 36 #define HINIC_CMDQ_CTXT_CEQ_EN_MASK 0x1 37 #define HINIC_CMDQ_CTXT_WRAPPED_MASK 0x1 38 39 #define HINIC_CMDQ_CTXT_PAGE_INFO_SET(val, member) \ 40 (((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \ 41 << HINIC_CMDQ_CTXT_##member##_SHIFT) 42 43 #define HINIC_CMDQ_CTXT_PAGE_INFO_CLEAR(val, member) \ 44 ((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \ 45 << HINIC_CMDQ_CTXT_##member##_SHIFT))) 46 47 #define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0 48 #define HINIC_CMDQ_CTXT_CI_SHIFT 52 49 50 #define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF 51 #define HINIC_CMDQ_CTXT_CI_MASK 0xFFF 52 53 #define HINIC_CMDQ_CTXT_BLOCK_INFO_SET(val, member) \ 54 (((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \ 55 << HINIC_CMDQ_CTXT_##member##_SHIFT) 56 57 #define HINIC_CMDQ_CTXT_BLOCK_INFO_CLEAR(val, member) \ 58 ((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \ 59 << HINIC_CMDQ_CTXT_##member##_SHIFT))) 60 61 #define HINIC_SAVED_DATA_ARM_SHIFT 31 62 63 #define HINIC_SAVED_DATA_ARM_MASK 0x1 64 65 #define HINIC_SAVED_DATA_SET(val, member) \ 66 (((u32)(val) & HINIC_SAVED_DATA_##member##_MASK) \ 67 << HINIC_SAVED_DATA_##member##_SHIFT) 68 69 #define HINIC_SAVED_DATA_GET(val, member) \ 70 (((val) >> HINIC_SAVED_DATA_##member##_SHIFT) \ 71 & HINIC_SAVED_DATA_##member##_MASK) 72 73 #define HINIC_SAVED_DATA_CLEAR(val, member) \ 74 ((val) & (~(HINIC_SAVED_DATA_##member##_MASK \ 75 << HINIC_SAVED_DATA_##member##_SHIFT))) 76 77 #define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0 78 #define HINIC_CMDQ_DB_INFO_PATH_SHIFT 23 79 #define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_SHIFT 24 80 #define HINIC_CMDQ_DB_INFO_DB_TYPE_SHIFT 27 81 82 #define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFF 83 #define HINIC_CMDQ_DB_INFO_PATH_MASK 0x1 84 #define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_MASK 0x7 85 #define HINIC_CMDQ_DB_INFO_DB_TYPE_MASK 0x1F 86 87 #define HINIC_CMDQ_DB_INFO_SET(val, member) \ 88 (((u32)(val) & HINIC_CMDQ_DB_INFO_##member##_MASK) \ 89 << HINIC_CMDQ_DB_INFO_##member##_SHIFT) 90 91 #define HINIC_CMDQ_BUF_SIZE 2048 92 93 #define HINIC_CMDQ_BUF_HW_RSVD 8 94 #define HINIC_CMDQ_MAX_DATA_SIZE (HINIC_CMDQ_BUF_SIZE - \ 95 HINIC_CMDQ_BUF_HW_RSVD) 96 97 enum hinic_cmdq_type { 98 HINIC_CMDQ_SYNC, 99 100 HINIC_MAX_CMDQ_TYPES, 101 }; 102 103 enum hinic_set_arm_qtype { 104 HINIC_SET_ARM_CMDQ, 105 }; 106 107 enum hinic_cmd_ack_type { 108 HINIC_CMD_ACK_TYPE_CMDQ, 109 }; 110 111 struct hinic_cmdq_buf { 112 void *buf; 113 dma_addr_t dma_addr; 114 size_t size; 115 }; 116 117 struct hinic_cmdq_arm_bit { 118 u32 q_type; 119 u32 q_id; 120 }; 121 122 struct hinic_cmdq_ctxt_info { 123 u64 curr_wqe_page_pfn; 124 u64 wq_block_pfn; 125 }; 126 127 struct hinic_cmdq_ctxt { 128 u8 status; 129 u8 version; 130 u8 rsvd0[6]; 131 132 u16 func_idx; 133 u8 cmdq_type; 134 u8 rsvd1[1]; 135 136 u8 rsvd2[4]; 137 138 struct hinic_cmdq_ctxt_info ctxt_info; 139 }; 140 141 struct hinic_cmdq { 142 struct hinic_wq *wq; 143 144 enum hinic_cmdq_type cmdq_type; 145 int wrapped; 146 147 /* Lock for keeping the doorbell order */ 148 spinlock_t cmdq_lock; 149 150 struct completion **done; 151 int **errcode; 152 153 /* doorbell area */ 154 void __iomem *db_base; 155 }; 156 157 struct hinic_cmdqs { 158 struct hinic_hwif *hwif; 159 160 struct dma_pool *cmdq_buf_pool; 161 162 struct hinic_wq *saved_wqs; 163 164 struct hinic_cmdq_pages cmdq_pages; 165 166 struct hinic_cmdq cmdq[HINIC_MAX_CMDQ_TYPES]; 167 }; 168 169 int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs, 170 struct hinic_cmdq_buf *cmdq_buf); 171 172 void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, 173 struct hinic_cmdq_buf *cmdq_buf); 174 175 int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs, 176 enum hinic_mod_type mod, u8 cmd, 177 struct hinic_cmdq_buf *buf_in, u64 *out_param); 178 179 int hinic_set_arm_bit(struct hinic_cmdqs *cmdqs, 180 enum hinic_set_arm_qtype q_type, u32 q_id); 181 182 int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, 183 void __iomem **db_area); 184 185 void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs); 186 187 #endif 188