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