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_CLEAR(val, member)    \
35 			((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
36 			 << HINIC_CMDQ_CTXT_##member##_SHIFT)))
37 
38 #define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT              0
39 #define HINIC_CMDQ_CTXT_CI_SHIFT                        52
40 
41 #define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_MASK               0xFFFFFFFFFFFFF
42 #define HINIC_CMDQ_CTXT_CI_MASK                         0xFFF
43 
44 #define HINIC_CMDQ_CTXT_BLOCK_INFO_SET(val, member)     \
45 			(((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \
46 			 << HINIC_CMDQ_CTXT_##member##_SHIFT)
47 
48 #define HINIC_CMDQ_CTXT_BLOCK_INFO_CLEAR(val, member)   \
49 			((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
50 			 << HINIC_CMDQ_CTXT_##member##_SHIFT)))
51 
52 #define HINIC_SAVED_DATA_ARM_SHIFT                      31
53 
54 #define HINIC_SAVED_DATA_ARM_MASK                       0x1
55 
56 #define HINIC_SAVED_DATA_SET(val, member)               \
57 			(((u32)(val) & HINIC_SAVED_DATA_##member##_MASK) \
58 			 << HINIC_SAVED_DATA_##member##_SHIFT)
59 
60 #define HINIC_SAVED_DATA_GET(val, member)               \
61 			(((val) >> HINIC_SAVED_DATA_##member##_SHIFT) \
62 			 & HINIC_SAVED_DATA_##member##_MASK)
63 
64 #define HINIC_SAVED_DATA_CLEAR(val, member)             \
65 			((val) & (~(HINIC_SAVED_DATA_##member##_MASK \
66 			 << HINIC_SAVED_DATA_##member##_SHIFT)))
67 
68 #define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_SHIFT            0
69 #define HINIC_CMDQ_DB_INFO_PATH_SHIFT                   23
70 #define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_SHIFT              24
71 #define HINIC_CMDQ_DB_INFO_DB_TYPE_SHIFT                27
72 
73 #define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_MASK             0xFF
74 #define HINIC_CMDQ_DB_INFO_PATH_MASK                    0x1
75 #define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_MASK               0x7
76 #define HINIC_CMDQ_DB_INFO_DB_TYPE_MASK                 0x1F
77 
78 #define HINIC_CMDQ_DB_INFO_SET(val, member)             \
79 			(((u32)(val) & HINIC_CMDQ_DB_INFO_##member##_MASK) \
80 			 << HINIC_CMDQ_DB_INFO_##member##_SHIFT)
81 
82 #define HINIC_CMDQ_BUF_SIZE             2048
83 
84 #define HINIC_CMDQ_BUF_HW_RSVD          8
85 #define HINIC_CMDQ_MAX_DATA_SIZE        (HINIC_CMDQ_BUF_SIZE - \
86 					 HINIC_CMDQ_BUF_HW_RSVD)
87 
88 enum hinic_cmdq_type {
89 	HINIC_CMDQ_SYNC,
90 
91 	HINIC_MAX_CMDQ_TYPES,
92 };
93 
94 enum hinic_set_arm_qtype {
95 	HINIC_SET_ARM_CMDQ,
96 };
97 
98 enum hinic_cmd_ack_type {
99 	HINIC_CMD_ACK_TYPE_CMDQ,
100 };
101 
102 struct hinic_cmdq_buf {
103 	void            *buf;
104 	dma_addr_t      dma_addr;
105 	size_t          size;
106 };
107 
108 struct hinic_cmdq_arm_bit {
109 	u32     q_type;
110 	u32     q_id;
111 };
112 
113 struct hinic_cmdq_ctxt_info {
114 	u64     curr_wqe_page_pfn;
115 	u64     wq_block_pfn;
116 };
117 
118 struct hinic_cmdq_ctxt {
119 	u8      status;
120 	u8      version;
121 	u8      rsvd0[6];
122 
123 	u16     func_idx;
124 	u8      cmdq_type;
125 	u8      rsvd1[1];
126 
127 	u8      rsvd2[4];
128 
129 	struct hinic_cmdq_ctxt_info ctxt_info;
130 };
131 
132 struct hinic_cmdq {
133 	struct hinic_wq         *wq;
134 
135 	enum hinic_cmdq_type    cmdq_type;
136 	int                     wrapped;
137 
138 	/* Lock for keeping the doorbell order */
139 	spinlock_t              cmdq_lock;
140 
141 	struct completion       **done;
142 	int                     **errcode;
143 
144 	/* doorbell area */
145 	void __iomem            *db_base;
146 };
147 
148 struct hinic_cmdqs {
149 	struct hinic_hwif       *hwif;
150 
151 	struct dma_pool         *cmdq_buf_pool;
152 
153 	struct hinic_wq         *saved_wqs;
154 
155 	struct hinic_cmdq_pages cmdq_pages;
156 
157 	struct hinic_cmdq       cmdq[HINIC_MAX_CMDQ_TYPES];
158 };
159 
160 int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs,
161 			 struct hinic_cmdq_buf *cmdq_buf);
162 
163 void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs,
164 			 struct hinic_cmdq_buf *cmdq_buf);
165 
166 int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
167 			   enum hinic_mod_type mod, u8 cmd,
168 			   struct hinic_cmdq_buf *buf_in, u64 *out_param);
169 
170 int hinic_set_arm_bit(struct hinic_cmdqs *cmdqs,
171 		      enum hinic_set_arm_qtype q_type, u32 q_id);
172 
173 int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
174 		     void __iomem **db_area);
175 
176 void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs);
177 
178 #endif
179