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 pci_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