2 * Huawei HiNIC PCI Express Linux driver
3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
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.
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
16 #ifndef HINIC_HW_EQS_H
17 #define HINIC_HW_EQS_H
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>
26 #include "hinic_hw_if.h"
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
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
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)
42 #define HINIC_AEQ_CTRL_0_CLEAR(val, member) \
43 ((val) & (~(HINIC_AEQ_CTRL_0_##member##_MASK \
44 << HINIC_AEQ_CTRL_0_##member##_SHIFT)))
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
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
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)
58 #define HINIC_AEQ_CTRL_1_CLEAR(val, member) \
59 ((val) & (~(HINIC_AEQ_CTRL_1_##member##_MASK \
60 << HINIC_AEQ_CTRL_1_##member##_SHIFT)))
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
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
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)
78 #define HINIC_CEQ_CTRL_0_CLEAR(val, member) \
79 ((val) & (~(HINIC_CEQ_CTRL_0_##member##_MASK \
80 << HINIC_CEQ_CTRL_0_##member##_SHIFT)))
82 #define HINIC_CEQ_CTRL_1_LEN_SHIFT 0
83 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_SHIFT 28
85 #define HINIC_CEQ_CTRL_1_LEN_MASK 0x1FFFFF
86 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_MASK 0xF
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)
92 #define HINIC_CEQ_CTRL_1_CLEAR(val, member) \
93 ((val) & (~(HINIC_CEQ_CTRL_1_##member##_MASK \
94 << HINIC_CEQ_CTRL_1_##member##_SHIFT)))
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
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
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)
110 #define HINIC_EQ_ELEM_DESC_GET(val, member) \
111 (((val) >> HINIC_EQ_ELEM_DESC_##member##_SHIFT) & \
112 HINIC_EQ_ELEM_DESC_##member##_MASK)
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
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
124 #define HINIC_EQ_CI_SET(val, member) \
125 (((u32)(val) & HINIC_EQ_CI_##member##_MASK) << \
126 HINIC_EQ_CI_##member##_SHIFT)
128 #define HINIC_EQ_CI_CLEAR(val, member) \
129 ((val) & (~(HINIC_EQ_CI_##member##_MASK \
130 << HINIC_EQ_CI_##member##_SHIFT)))
132 #define HINIC_MAX_AEQS 4
133 #define HINIC_MAX_CEQS 32
135 #define HINIC_AEQE_SIZE 64
136 #define HINIC_CEQE_SIZE 4
138 #define HINIC_AEQE_DESC_SIZE 4
139 #define HINIC_AEQE_DATA_SIZE \
140 (HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE)
142 #define HINIC_DEFAULT_AEQ_LEN 64
143 #define HINIC_DEFAULT_CEQ_LEN 1024
145 #define HINIC_EQ_PAGE_SIZE SZ_4K
147 #define HINIC_CEQ_ID_CMDQ 0
154 enum hinic_aeq_type {
155 HINIC_MSG_FROM_MGMT_CPU = 2,
157 HINIC_MAX_AEQ_EVENTS,
160 enum hinic_ceq_type {
163 HINIC_MAX_CEQ_EVENTS,
166 enum hinic_eqe_state {
167 HINIC_EQE_ENABLED = BIT(0),
168 HINIC_EQE_RUNNING = BIT(1),
171 struct hinic_aeq_elem {
172 u8 data[HINIC_AEQE_DATA_SIZE];
176 struct hinic_eq_work {
177 struct work_struct work;
182 struct hinic_hwif *hwif;
184 enum hinic_eq_type type;
196 struct msix_entry msix_entry;
198 dma_addr_t *dma_addr;
201 struct hinic_eq_work aeq_work;
203 struct tasklet_struct ceq_tasklet;
206 struct hinic_hw_event_cb {
207 void (*hwe_handler)(void *handle, void *data, u8 size);
209 unsigned long hwe_state;
213 struct hinic_hwif *hwif;
215 struct hinic_eq aeq[HINIC_MAX_AEQS];
218 struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS];
220 struct workqueue_struct *workq;
223 struct hinic_ceq_cb {
224 void (*handler)(void *handle, u32 ceqe_data);
226 enum hinic_eqe_state ceqe_state;
230 struct hinic_hwif *hwif;
232 struct hinic_eq ceq[HINIC_MAX_CEQS];
235 struct hinic_ceq_cb ceq_cb[HINIC_MAX_CEQ_EVENTS];
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,
243 void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs,
244 enum hinic_aeq_type event);
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));
250 void hinic_ceq_unregister_cb(struct hinic_ceqs *ceqs,
251 enum hinic_ceq_type event);
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);
257 void hinic_aeqs_free(struct hinic_aeqs *aeqs);
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);
263 void hinic_ceqs_free(struct hinic_ceqs *ceqs);