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_HW_EQS_H 17 #define HINIC_HW_EQS_H 18 19 #include <linux/types.h> 20 #include <linux/workqueue.h> 21 #include <linux/pci.h> 22 #include <linux/sizes.h> 23 #include <linux/bitops.h> 24 #include <linux/interrupt.h> 25 26 #include "hinic_hw_if.h" 27 28 #define HINIC_AEQ_CTRL_0_INT_IDX_SHIFT 0 29 #define HINIC_AEQ_CTRL_0_DMA_ATTR_SHIFT 12 30 #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20 31 #define HINIC_AEQ_CTRL_0_INT_MODE_SHIFT 31 32 33 #define HINIC_AEQ_CTRL_0_INT_IDX_MASK 0x3FF 34 #define HINIC_AEQ_CTRL_0_DMA_ATTR_MASK 0x3F 35 #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3 36 #define HINIC_AEQ_CTRL_0_INT_MODE_MASK 0x1 37 38 #define HINIC_AEQ_CTRL_0_SET(val, member) \ 39 (((u32)(val) & HINIC_AEQ_CTRL_0_##member##_MASK) << \ 40 HINIC_AEQ_CTRL_0_##member##_SHIFT) 41 42 #define HINIC_AEQ_CTRL_0_CLEAR(val, member) \ 43 ((val) & (~(HINIC_AEQ_CTRL_0_##member##_MASK \ 44 << HINIC_AEQ_CTRL_0_##member##_SHIFT))) 45 46 #define HINIC_AEQ_CTRL_1_LEN_SHIFT 0 47 #define HINIC_AEQ_CTRL_1_ELEM_SIZE_SHIFT 24 48 #define HINIC_AEQ_CTRL_1_PAGE_SIZE_SHIFT 28 49 50 #define HINIC_AEQ_CTRL_1_LEN_MASK 0x1FFFFF 51 #define HINIC_AEQ_CTRL_1_ELEM_SIZE_MASK 0x3 52 #define HINIC_AEQ_CTRL_1_PAGE_SIZE_MASK 0xF 53 54 #define HINIC_AEQ_CTRL_1_SET(val, member) \ 55 (((u32)(val) & HINIC_AEQ_CTRL_1_##member##_MASK) << \ 56 HINIC_AEQ_CTRL_1_##member##_SHIFT) 57 58 #define HINIC_AEQ_CTRL_1_CLEAR(val, member) \ 59 ((val) & (~(HINIC_AEQ_CTRL_1_##member##_MASK \ 60 << HINIC_AEQ_CTRL_1_##member##_SHIFT))) 61 62 #define HINIC_CEQ_CTRL_0_INTR_IDX_SHIFT 0 63 #define HINIC_CEQ_CTRL_0_DMA_ATTR_SHIFT 12 64 #define HINIC_CEQ_CTRL_0_KICK_THRESH_SHIFT 20 65 #define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_SHIFT 24 66 #define HINIC_CEQ_CTRL_0_INTR_MODE_SHIFT 31 67 68 #define HINIC_CEQ_CTRL_0_INTR_IDX_MASK 0x3FF 69 #define HINIC_CEQ_CTRL_0_DMA_ATTR_MASK 0x3F 70 #define HINIC_CEQ_CTRL_0_KICK_THRESH_MASK 0xF 71 #define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3 72 #define HINIC_CEQ_CTRL_0_INTR_MODE_MASK 0x1 73 74 #define HINIC_CEQ_CTRL_0_SET(val, member) \ 75 (((u32)(val) & HINIC_CEQ_CTRL_0_##member##_MASK) << \ 76 HINIC_CEQ_CTRL_0_##member##_SHIFT) 77 78 #define HINIC_CEQ_CTRL_0_CLEAR(val, member) \ 79 ((val) & (~(HINIC_CEQ_CTRL_0_##member##_MASK \ 80 << HINIC_CEQ_CTRL_0_##member##_SHIFT))) 81 82 #define HINIC_CEQ_CTRL_1_LEN_SHIFT 0 83 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_SHIFT 28 84 85 #define HINIC_CEQ_CTRL_1_LEN_MASK 0x1FFFFF 86 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_MASK 0xF 87 88 #define HINIC_CEQ_CTRL_1_SET(val, member) \ 89 (((u32)(val) & HINIC_CEQ_CTRL_1_##member##_MASK) << \ 90 HINIC_CEQ_CTRL_1_##member##_SHIFT) 91 92 #define HINIC_CEQ_CTRL_1_CLEAR(val, member) \ 93 ((val) & (~(HINIC_CEQ_CTRL_1_##member##_MASK \ 94 << HINIC_CEQ_CTRL_1_##member##_SHIFT))) 95 96 #define HINIC_EQ_ELEM_DESC_TYPE_SHIFT 0 97 #define HINIC_EQ_ELEM_DESC_SRC_SHIFT 7 98 #define HINIC_EQ_ELEM_DESC_SIZE_SHIFT 8 99 #define HINIC_EQ_ELEM_DESC_WRAPPED_SHIFT 31 100 101 #define HINIC_EQ_ELEM_DESC_TYPE_MASK 0x7F 102 #define HINIC_EQ_ELEM_DESC_SRC_MASK 0x1 103 #define HINIC_EQ_ELEM_DESC_SIZE_MASK 0xFF 104 #define HINIC_EQ_ELEM_DESC_WRAPPED_MASK 0x1 105 106 #define HINIC_EQ_ELEM_DESC_SET(val, member) \ 107 (((u32)(val) & HINIC_EQ_ELEM_DESC_##member##_MASK) << \ 108 HINIC_EQ_ELEM_DESC_##member##_SHIFT) 109 110 #define HINIC_EQ_ELEM_DESC_GET(val, member) \ 111 (((val) >> HINIC_EQ_ELEM_DESC_##member##_SHIFT) & \ 112 HINIC_EQ_ELEM_DESC_##member##_MASK) 113 114 #define HINIC_EQ_CI_IDX_SHIFT 0 115 #define HINIC_EQ_CI_WRAPPED_SHIFT 20 116 #define HINIC_EQ_CI_XOR_CHKSUM_SHIFT 24 117 #define HINIC_EQ_CI_INT_ARMED_SHIFT 31 118 119 #define HINIC_EQ_CI_IDX_MASK 0xFFFFF 120 #define HINIC_EQ_CI_WRAPPED_MASK 0x1 121 #define HINIC_EQ_CI_XOR_CHKSUM_MASK 0xF 122 #define HINIC_EQ_CI_INT_ARMED_MASK 0x1 123 124 #define HINIC_EQ_CI_SET(val, member) \ 125 (((u32)(val) & HINIC_EQ_CI_##member##_MASK) << \ 126 HINIC_EQ_CI_##member##_SHIFT) 127 128 #define HINIC_EQ_CI_CLEAR(val, member) \ 129 ((val) & (~(HINIC_EQ_CI_##member##_MASK \ 130 << HINIC_EQ_CI_##member##_SHIFT))) 131 132 #define HINIC_MAX_AEQS 4 133 #define HINIC_MAX_CEQS 32 134 135 #define HINIC_AEQE_SIZE 64 136 #define HINIC_CEQE_SIZE 4 137 138 #define HINIC_AEQE_DESC_SIZE 4 139 #define HINIC_AEQE_DATA_SIZE \ 140 (HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE) 141 142 #define HINIC_DEFAULT_AEQ_LEN 64 143 #define HINIC_DEFAULT_CEQ_LEN 1024 144 145 #define HINIC_EQ_PAGE_SIZE SZ_4K 146 147 #define HINIC_CEQ_ID_CMDQ 0 148 149 enum hinic_eq_type { 150 HINIC_AEQ, 151 HINIC_CEQ, 152 }; 153 154 enum hinic_aeq_type { 155 HINIC_MSG_FROM_MGMT_CPU = 2, 156 157 HINIC_MAX_AEQ_EVENTS, 158 }; 159 160 enum hinic_ceq_type { 161 HINIC_CEQ_CMDQ = 3, 162 163 HINIC_MAX_CEQ_EVENTS, 164 }; 165 166 enum hinic_eqe_state { 167 HINIC_EQE_ENABLED = BIT(0), 168 HINIC_EQE_RUNNING = BIT(1), 169 }; 170 171 struct hinic_aeq_elem { 172 u8 data[HINIC_AEQE_DATA_SIZE]; 173 u32 desc; 174 }; 175 176 struct hinic_eq_work { 177 struct work_struct work; 178 void *data; 179 }; 180 181 struct hinic_eq { 182 struct hinic_hwif *hwif; 183 184 enum hinic_eq_type type; 185 int q_id; 186 u32 q_len; 187 u32 page_size; 188 189 u32 cons_idx; 190 int wrapped; 191 192 size_t elem_size; 193 int num_pages; 194 int num_elem_in_pg; 195 196 struct msix_entry msix_entry; 197 198 dma_addr_t *dma_addr; 199 void **virt_addr; 200 201 struct hinic_eq_work aeq_work; 202 203 struct tasklet_struct ceq_tasklet; 204 }; 205 206 struct hinic_hw_event_cb { 207 void (*hwe_handler)(void *handle, void *data, u8 size); 208 void *handle; 209 unsigned long hwe_state; 210 }; 211 212 struct hinic_aeqs { 213 struct hinic_hwif *hwif; 214 215 struct hinic_eq aeq[HINIC_MAX_AEQS]; 216 int num_aeqs; 217 218 struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS]; 219 220 struct workqueue_struct *workq; 221 }; 222 223 struct hinic_ceq_cb { 224 void (*handler)(void *handle, u32 ceqe_data); 225 void *handle; 226 enum hinic_eqe_state ceqe_state; 227 }; 228 229 struct hinic_ceqs { 230 struct hinic_hwif *hwif; 231 232 struct hinic_eq ceq[HINIC_MAX_CEQS]; 233 int num_ceqs; 234 235 struct hinic_ceq_cb ceq_cb[HINIC_MAX_CEQ_EVENTS]; 236 }; 237 238 void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs, 239 enum hinic_aeq_type event, void *handle, 240 void (*hwe_handler)(void *handle, void *data, 241 u8 size)); 242 243 void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs, 244 enum hinic_aeq_type event); 245 246 void hinic_ceq_register_cb(struct hinic_ceqs *ceqs, 247 enum hinic_ceq_type event, void *handle, 248 void (*ceq_cb)(void *handle, u32 ceqe_data)); 249 250 void hinic_ceq_unregister_cb(struct hinic_ceqs *ceqs, 251 enum hinic_ceq_type event); 252 253 int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif, 254 int num_aeqs, u32 q_len, u32 page_size, 255 struct msix_entry *msix_entries); 256 257 void hinic_aeqs_free(struct hinic_aeqs *aeqs); 258 259 int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif, 260 int num_ceqs, u32 q_len, u32 page_size, 261 struct msix_entry *msix_entries); 262 263 void hinic_ceqs_free(struct hinic_ceqs *ceqs); 264 265 #endif 266