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