Multicast join now works.
[people/xl0/gpxe.git] / src / include / gpxe / infiniband.h
1 #ifndef _GPXE_INFINIBAND_H
2 #define _GPXE_INFINIBAND_H
3
4 /** @file
5  *
6  * Infiniband protocol
7  *
8  */
9
10 #include <stdint.h>
11 #include <gpxe/netdevice.h>
12
13 /** An Infiniband Global Identifier */
14 struct ib_gid {
15         uint8_t bytes[16];
16 };
17
18 /** An Infiniband Global Route Header */
19 struct ib_global_route_header {
20         /** IP version, traffic class, and flow label
21          *
22          *  4 bits : Version of the GRH
23          *  8 bits : Traffic class
24          * 20 bits : Flow label
25          */
26         uint32_t ipver_tclass_flowlabel;
27         /** Payload length */
28         uint16_t paylen;
29         /** Next header */
30         uint8_t nxthdr;
31         /** Hop limit */
32         uint8_t hoplmt;
33         /** Source GID */
34         struct ib_gid sgid;
35         /** Destiniation GID */
36         struct ib_gid dgid;
37 } __attribute__ (( packed ));
38
39 /** Infiniband MAC address length */
40 #define IB_ALEN 20
41
42 /** An Infiniband MAC address */
43 struct ib_mac {
44         /** Queue pair number
45          *
46          * MSB must be zero; QPNs are only 24-bit.
47          */
48         uint32_t qpn;
49         /** Port GID */
50         struct ib_gid gid;
51 } __attribute__ (( packed ));
52
53 /** Infiniband link-layer header length */
54 #define IB_HLEN 4
55
56 /** An Infiniband link-layer header */
57 struct ibhdr {
58         /** Network-layer protocol */
59         uint16_t proto;
60         /** Reserved, must be zero */
61         uint16_t reserved;
62 } __attribute__ (( packed ));
63
64
65
66 struct ib_device;
67 struct ib_queue_pair;
68 struct ib_completion_queue;
69
70 /** An Infiniband Work Queue */
71 struct ib_work_queue {
72         /** Containing queue pair */
73         struct ib_queue_pair *qp;
74         /** "Is a send queue" flag */
75         int is_send;
76         /** Associated completion queue */
77         struct ib_completion_queue *cq;
78         /** List of work queues on this completion queue */
79         struct list_head list;
80         /** Number of work queue entries */
81         unsigned int num_wqes;
82         /** Next work queue entry index
83          *
84          * This is the index of the next entry to be filled (i.e. the
85          * first empty entry).  This value is not bounded by num_wqes;
86          * users must logical-AND with (num_wqes-1) to generate an
87          * array index.
88          */
89         unsigned long next_idx;
90         /** I/O buffers assigned to work queue */
91         struct io_buffer **iobufs;
92         /** Device private data */
93         void *dev_priv;
94 };
95
96 /** An Infiniband Queue Pair */
97 struct ib_queue_pair {
98         /** Queue Pair Number */
99         unsigned long qpn;
100         /** Queue key */
101         unsigned long qkey;
102         /** Send queue */
103         struct ib_work_queue send;
104         /** Receive queue */
105         struct ib_work_queue recv;
106         /** Device private data */
107         void *dev_priv;
108         /** Queue owner private data */
109         void *owner_priv;
110 };
111
112 /** An Infiniband Completion Queue */
113 struct ib_completion_queue {
114         /** Completion queue number */
115         unsigned long cqn;
116         /** Number of completion queue entries */
117         unsigned int num_cqes;
118         /** Next completion queue entry index
119          *
120          * This is the index of the next entry to be filled (i.e. the
121          * first empty entry).  This value is not bounded by num_wqes;
122          * users must logical-AND with (num_wqes-1) to generate an
123          * array index.
124          */
125         unsigned long next_idx;
126         /** List of work queues completing to this queue */
127         struct list_head work_queues;
128         /** Device private data */
129         void *dev_priv;
130 };
131
132 /** An Infiniband completion */
133 struct ib_completion {
134         /** Syndrome
135          *
136          * If non-zero, then the completion is in error.
137          */
138         unsigned int syndrome;
139         /** Length */
140         size_t len;
141 };
142
143 /** An Infiniband completion handler
144  *
145  * @v ibdev             Infiniband device
146  * @v qp                Queue pair
147  * @v completion        Completion
148  * @v iobuf             I/O buffer
149  */
150 typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
151                                     struct ib_queue_pair *qp,
152                                     struct ib_completion *completion,
153                                     struct io_buffer *iobuf );
154
155 /** An Infiniband Address Vector */
156 struct ib_address_vector {
157         /** Destination Queue Pair */
158         unsigned int dest_qp;
159         /** Queue key */
160         unsigned int qkey;
161         /** Destination Local ID */
162         unsigned int dlid;
163         /** Rate */
164         unsigned int rate;
165         /** Service level */
166         unsigned int sl;
167         /** GID is present */
168         unsigned int gid_present;
169         /** GID */
170         struct ib_gid gid;
171 };
172
173 /**
174  * Infiniband device operations
175  *
176  * These represent a subset of the Infiniband Verbs.
177  */
178 struct ib_device_operations {
179         /** Create completion queue
180          *
181          * @v ibdev             Infiniband device
182          * @v cq                Completion queue
183          * @ret rc              Return status code
184          */
185         int ( * create_cq ) ( struct ib_device *ibdev,
186                               struct ib_completion_queue *cq );
187         /** Destroy completion queue
188          *
189          * @v ibdev             Infiniband device
190          * @v cq                Completion queue
191          */
192         void ( * destroy_cq ) ( struct ib_device *ibdev,
193                                 struct ib_completion_queue *cq );
194         /** Create queue pair
195          *
196          * @v ibdev             Infiniband device
197          * @v qp                Queue pair
198          * @ret rc              Return status code
199          */
200         int ( * create_qp ) ( struct ib_device *ibdev,
201                               struct ib_queue_pair *qp );
202         /** Destroy queue pair
203          *
204          * @v ibdev             Infiniband device
205          * @v qp                Queue pair
206          */
207         void ( * destroy_qp ) ( struct ib_device *ibdev,
208                                 struct ib_queue_pair *qp );
209         /** Post send work queue entry
210          *
211          * @v ibdev             Infiniband device
212          * @v qp                Queue pair
213          * @v av                Address vector
214          * @v iobuf             I/O buffer
215          * @ret rc              Return status code
216          *
217          * If this method returns success, the I/O buffer remains
218          * owned by the queue pair.  If this method returns failure,
219          * the I/O buffer is immediately released; the failure is
220          * interpreted as "failure to enqueue buffer".
221          */
222         int ( * post_send ) ( struct ib_device *ibdev,
223                               struct ib_queue_pair *qp,
224                               struct ib_address_vector *av,
225                               struct io_buffer *iobuf );
226         /**
227          * Post receive work queue entry
228          *
229          * @v ibdev             Infiniband device
230          * @v qp                Queue pair
231          * @v iobuf             I/O buffer
232          * @ret rc              Return status code
233          *
234          * If this method returns success, the I/O buffer remains
235          * owned by the queue pair.  If this method returns failure,
236          * the I/O buffer is immediately released; the failure is
237          * interpreted as "failure to enqueue buffer".
238          */
239         int ( * post_recv ) ( struct ib_device *ibdev,
240                               struct ib_queue_pair *qp,
241                               struct io_buffer *iobuf );
242         /** Poll completion queue
243          *
244          * @v ibdev             Infiniband device
245          * @v cq                Completion queue
246          * @v complete_send     Send completion handler
247          * @v complete_recv     Receive completion handler
248          *
249          * The completion handler takes ownership of the I/O buffer.
250          */
251         void ( * poll_cq ) ( struct ib_device *ibdev,
252                              struct ib_completion_queue *cq,
253                              ib_completer_t complete_send,
254                              ib_completer_t complete_recv );
255         /**
256          * Attach to multicast group
257          *
258          * @v ibdev             Infiniband device
259          * @v qp                Queue pair
260          * @v gid               Multicast GID
261          * @ret rc              Return status code
262          */
263         int ( * mcast_attach ) ( struct ib_device *ibdev,
264                                  struct ib_queue_pair *qp,
265                                  struct ib_gid *gid );
266         /**
267          * Detach from multicast group
268          *
269          * @v ibdev             Infiniband device
270          * @v qp                Queue pair
271          * @v gid               Multicast GID
272          */
273         void ( * mcast_detach ) ( struct ib_device *ibdev,
274                                   struct ib_queue_pair *qp,
275                                   struct ib_gid *gid );
276 };
277
278 /** An Infiniband device */
279 struct ib_device {      
280         /** Infiniband operations */
281         struct ib_device_operations *op;
282         /** Device private data */
283         void *dev_priv;
284 };
285
286 extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
287                                                    unsigned int num_cqes );
288 extern void ib_destroy_cq ( struct ib_device *ibdev,
289                             struct ib_completion_queue *cq );
290 extern struct ib_queue_pair *
291 ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes,
292                struct ib_completion_queue *send_cq, unsigned int num_recv_wqes,
293                struct ib_completion_queue *recv_cq, unsigned long qkey );
294 extern void ib_destroy_qp ( struct ib_device *ibdev,
295                             struct ib_queue_pair *qp );
296 extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
297                                            unsigned long qpn, int is_send );
298
299 /**
300  * Attach to multicast group
301  *
302  * @v ibdev             Infiniband device
303  * @v qp                Queue pair
304  * @v gid               Multicast GID
305  * @ret rc              Return status code
306  */
307 static inline __attribute__ (( always_inline )) int
308 ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
309                   struct ib_gid *gid ) {
310         return ibdev->op->mcast_attach ( ibdev, qp, gid );
311 }
312
313 /**
314  * Detach from multicast group
315  *
316  * @v ibdev             Infiniband device
317  * @v qp                Queue pair
318  * @v gid               Multicast GID
319  */
320 static inline __attribute__ (( always_inline )) void
321 ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
322                   struct ib_gid *gid ) {
323         ibdev->op->mcast_detach ( ibdev, qp, gid );
324 }
325
326
327 extern struct ll_protocol infiniband_protocol;
328
329 extern const char * ib_ntoa ( const void *ll_addr );
330
331 /**
332  * Allocate Infiniband device
333  *
334  * @v priv_size         Size of driver private data
335  * @ret netdev          Network device, or NULL
336  */
337 static inline struct net_device * alloc_ibdev ( size_t priv_size ) {
338         struct net_device *netdev;
339
340         netdev = alloc_netdev ( priv_size );
341         if ( netdev ) {
342                 netdev->ll_protocol = &infiniband_protocol;
343         }
344         return netdev;
345 }
346
347 #endif /* _GPXE_INFINIBAND_H */