create_cq() implemented (but not tested).
[people/xl0/gpxe.git] / src / drivers / net / mlx_ipoib / arbel.h
1 #ifndef _ARBEL_H
2 #define _ARBEL_H
3
4 /** @file
5  *
6  * Mellanox Arbel Infiniband HCA driver
7  *
8  */
9
10 /*
11  * Hardware constants
12  *
13  */
14
15 /* UAR context table (UCE) resource types */
16 #define ARBEL_UAR_RES_NONE              0x00
17 #define ARBEL_UAR_RES_CQ_CI             0x01
18 #define ARBEL_UAR_RES_CQ_ARM            0x02
19 #define ARBEL_UAR_RES_SQ                0x03
20 #define ARBEL_UAR_RES_RQ                0x04
21 #define ARBEL_UAR_RES_GROUP_SEP         0x07
22
23 /* Work queue entry and completion queue entry opcodes */
24 #define ARBEL_OPCODE_SEND               0x0a
25 #define ARBEL_OPCODE_RECV_ERROR         0xfe
26 #define ARBEL_OPCODE_SEND_ERROR         0xff
27
28 /* HCA command register opcodes */
29 #define ARBEL_HCR_QUERY_DEV_LIM         0x0003
30 #define ARBEL_HCR_SW2HW_CQ              0x0016
31
32 /*
33  * Wrapper structures for hardware datatypes
34  *
35  */
36
37 struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_context );
38 struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
39 struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
40 struct MLX_DECLARE_STRUCT ( arbelprm_cq_arm_db_record );
41 struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
42 struct MLX_DECLARE_STRUCT ( arbelprm_hca_command_register );
43 struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
44 struct MLX_DECLARE_STRUCT ( arbelprm_query_dev_lim );
45 struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
46 struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
47 struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
48 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
49 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
50 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
51 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
52
53 /*
54  * Composite hardware datatypes
55  *
56  */
57
58 #define ARBEL_MAX_GATHER 1
59
60 struct arbelprm_ud_send_wqe {
61         struct arbelprm_wqe_segment_next next;
62         struct arbelprm_wqe_segment_ctrl_send ctrl;
63         struct arbelprm_wqe_segment_ud ud;
64         struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
65 } __attribute__ (( packed ));
66
67 #define ARBEL_MAX_SCATTER 1
68
69 struct arbelprm_recv_wqe {
70         /* The autogenerated header is inconsistent between send and
71          * receive WQEs.  The "ctrl" structure for receive WQEs is
72          * defined to include the "next" structure.  Since the "ctrl"
73          * part of the "ctrl" structure contains only "reserved, must
74          * be zero" bits, we ignore its definition and provide
75          * something more usable.
76          */
77         struct arbelprm_recv_wqe_segment_next next;
78         uint32_t ctrl[2]; /* All "reserved, must be zero" */
79         struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_SCATTER];
80 } __attribute__ (( packed ));
81
82 union arbelprm_completion_entry {
83         struct arbelprm_completion_queue_entry normal;
84         struct arbelprm_completion_with_error error;
85 } __attribute__ (( packed ));
86
87 union arbelprm_doorbell_record {
88         struct arbelprm_cq_arm_db_record cq_arm;
89         struct arbelprm_cq_ci_db_record cq_ci;
90         struct arbelprm_qp_db_record qp;
91 } __attribute__ (( packed ));
92
93 union arbelprm_doorbell_register {
94         struct arbelprm_send_doorbell send;
95         uint32_t dword[2];
96 } __attribute__ (( packed ));
97
98 /*
99  * gPXE-specific definitions
100  *
101  */
102
103 /** Arbel device limits */
104 struct arbel_dev_limits {
105         /** Number of reserver UARs */
106         unsigned long reserved_uars;
107         /** Number of reserved CQs */
108         unsigned long reserved_cqs;
109 };
110
111 /** Alignment of Arbel send work queue entries */
112 #define ARBEL_SEND_WQE_ALIGN 128
113
114 /** An Arbel send work queue entry */
115 union arbel_send_wqe {
116         struct arbelprm_ud_send_wqe ud;
117         uint8_t force_align[ARBEL_SEND_WQE_ALIGN];
118 } __attribute__ (( packed ));
119
120 /** An Arbel send work queue */
121 struct arbel_send_work_queue {
122         /** Doorbell record number */
123         unsigned int doorbell_idx;
124         /** Work queue entries */
125         union arbel_send_wqe *wqe;
126 };
127
128 /** Alignment of Arbel receive work queue entries */
129 #define ARBEL_RECV_WQE_ALIGN 64
130
131 /** An Arbel receive work queue entry */
132 union arbel_recv_wqe {
133         struct arbelprm_recv_wqe recv;
134         uint8_t force_align[ARBEL_RECV_WQE_ALIGN];
135 } __attribute__ (( packed ));
136
137 /** An Arbel receive work queue */
138 struct arbel_recv_work_queue {
139         /** Doorbell record number */
140         unsigned int doorbell_idx;
141         /** Work queue entries */
142         union arbel_recv_wqe *wqe;
143 };
144
145 /** An Arbel queue pair */
146 struct arbel_queue_pair {
147         /** Infiniband queue pair */
148         struct ib_queue_pair qp;
149         /** Send work queue */
150         struct arbel_send_work_queue send;
151         /** Receive work queue */
152         struct arbel_recv_work_queue recv;
153 };
154
155 /** Maximum number of allocatable completion queues
156  *
157  * This is a policy decision, not a device limit.
158  */
159 #define ARBEL_MAX_CQS           8
160
161 /** An Arbel completion queue */
162 struct arbel_completion_queue {
163         /** Infiniband completion queue */
164         struct ib_completion_queue cq;
165         /** Doorbell record number */
166         unsigned int doorbell_idx;
167         /** Completion queue entries */
168         union arbelprm_completion_entry *cqe;
169 };
170
171 /** An Arbel resource bitmask */
172 typedef uint32_t arbel_bitmask_t;
173
174 /** Size of an Arbel resource bitmask */
175 #define ARBEL_BITMASK_SIZE(max_entries)                                      \
176         ( ( (max_entries) + ( 8 * sizeof ( arbel_bitmask_t ) ) - 1 ) /       \
177           ( 8 * sizeof ( arbel_bitmask_t ) ) )
178
179 /** An Arbel device */
180 struct arbel {
181         /** Configuration registers */
182         void *config;
183         /** Command input mailbox */
184         void *mailbox_in;
185         /** Command output mailbox */
186         void *mailbox_out;
187
188         /** User Access Region */
189         void *uar;
190         /** Doorbell records */
191         union arbelprm_doorbell_record *db_rec;
192         /** Reserved LKey
193          *
194          * Used to get unrestricted memory access.
195          */
196         unsigned long reserved_lkey;
197         /** Event queue number */
198         unsigned long eqn;
199
200         /** Completion queue in-use bitmask */
201         arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ];
202         
203         /** Device limits */
204         struct arbel_dev_limits limits;
205 };
206
207 /** Global protection domain */
208 #define ARBEL_GLOBAL_PD                 0x123456
209
210 /*
211  * HCA commands
212  *
213  */
214
215 #define ARBEL_HCR_BASE                  0x80680
216 #define ARBEL_HCR_REG(x)                ( ARBEL_HCR_BASE + 4 * (x) )
217 #define ARBEL_HCR_MAX_WAIT_MS           2000
218
219 /* HCA command is split into
220  *
221  * bits  11:0   Opcode
222  * bit     12   Input uses mailbox
223  * bit     13   Output uses mailbox
224  * bits 22:14   Input parameter length (in dwords)
225  * bits 31:23   Output parameter length (in dwords)
226  *
227  * Encoding the information in this way allows us to cut out several
228  * parameters to the arbel_command() call.
229  */
230 #define ARBEL_HCR_IN_MBOX               0x00001000UL
231 #define ARBEL_HCR_OUT_MBOX              0x00002000UL
232 #define ARBEL_HCR_OPCODE( _command )    ( (_command) & 0xfff )
233 #define ARBEL_HCR_IN_LEN( _command )    ( ( (_command) >> 12 ) & 0x7fc )
234 #define ARBEL_HCR_OUT_LEN( _command )   ( ( (_command) >> 21 ) & 0x7fc )
235
236 /** Build HCR command from component parts */
237 #define ARBEL_HCR_CMD( _opcode, _in_mbox, _in_len, _out_mbox, _out_len )     \
238         ( (_opcode) |                                                        \
239           ( (_in_mbox) ? ARBEL_HCR_IN_MBOX : 0 ) |                           \
240           ( ( (_in_len) / 4 ) << 14 ) |                                      \
241           ( (_out_mbox) ? ARBEL_HCR_OUT_MBOX : 0 ) |                         \
242           ( ( (_out_len) / 4 ) << 23 ) )
243
244 #define ARBEL_HCR_IN_CMD( _opcode, _in_mbox, _in_len )                       \
245         ARBEL_HCR_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
246
247 #define ARBEL_HCR_OUT_CMD( _opcode, _out_mbox, _out_len )                    \
248         ARBEL_HCR_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
249
250 /*
251  * Doorbell record allocation
252  *
253  * The doorbell record map looks like:
254  *
255  *    ARBEL_MAX_CQS * Arm completion queue doorbell
256  *    ARBEL_MAX_QPS * Send work request doorbell
257  *    Group separator
258  *    ...(empty space)...
259  *    ARBEL_MAX_QPS * Receive work request doorbell
260  *    ARBEL_MAX_CQS * Completion queue consumer counter update doorbell
261  */
262
263 #define ARBEL_MAX_DOORBELL_RECORDS 512
264 #define ARBEL_GROUP_SEPARATOR_DOORBELL ( ARBEL_MAX_CQS + ARBEL_MAX_QPS )
265
266 /**
267  * Get arm completion queue doorbell index
268  *
269  * @v cqn_offset        Completion queue number offset
270  * @ret doorbell_idx    Doorbell index
271  */
272 static inline unsigned int
273 arbel_cq_arm_doorbell_idx ( unsigned int cqn_offset ) {
274         return cqn_offset;
275 }
276
277 /**
278  * Get send work request doorbell index
279  *
280  * @v qpn_offset        Queue pair number offset
281  * @ret doorbell_idx    Doorbell index
282  */
283 static inline unsigned int
284 arbel_send_doorbell_idx ( unsigned int qpn_offset ) {
285         return ( ARBEL_MAX_CQS + qpn_offset );
286 }
287
288 /**
289  * Get receive work request doorbell index
290  *
291  * @v qpn_offset        Queue pair number offset
292  * @ret doorbell_idx    Doorbell index
293  */
294 static inline unsigned int
295 arbel_recv_doorbell_idx ( unsigned int qpn_offset ) {
296         return ( ARBEL_MAX_DOORBELL_RECORDS - ARBEL_MAX_CQS - qpn_offset - 1 );
297 }
298
299 /**
300  * Get commpletion queue consumer counter doorbell index
301  *
302  * @v cqn_offset        Completion queue number offset
303  * @ret doorbell_idx    Doorbell index
304  */
305 static inline unsigned int
306 arbel_cq_ci_doorbell_idx ( unsigned int cqn_offset ) {
307         return ( ARBEL_MAX_DOORBELL_RECORDS - cqn_offset - 1 );
308 }
309
310 #endif /* _ARBEL_H */