354dc579c24d51f067f3cafed190639fe1f6e42c
[people/mdeck/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/device.h>
12
13 /** Subnet administrator QPN */
14 #define IB_SA_QPN 1
15
16 /** Broadcast QPN */
17 #define IB_BROADCAST_QPN 0xffffffUL
18
19 /** Subnet administrator queue key */
20 #define IB_GLOBAL_QKEY 0x80010000UL
21
22 /** An Infiniband Global Identifier */
23 struct ib_gid {
24         union {
25                 uint8_t bytes[16];
26                 uint16_t words[8];
27                 uint32_t dwords[4];
28         } u;
29 };
30
31 /** An Infiniband Global Route Header */
32 struct ib_global_route_header {
33         /** IP version, traffic class, and flow label
34          *
35          *  4 bits : Version of the GRH
36          *  8 bits : Traffic class
37          * 20 bits : Flow label
38          */
39         uint32_t ipver_tclass_flowlabel;
40         /** Payload length */
41         uint16_t paylen;
42         /** Next header */
43         uint8_t nxthdr;
44         /** Hop limit */
45         uint8_t hoplmt;
46         /** Source GID */
47         struct ib_gid sgid;
48         /** Destiniation GID */
49         struct ib_gid dgid;
50 } __attribute__ (( packed ));
51
52 struct ib_device;
53 struct ib_queue_pair;
54 struct ib_completion_queue;
55
56 /** An Infiniband Work Queue */
57 struct ib_work_queue {
58         /** Containing queue pair */
59         struct ib_queue_pair *qp;
60         /** "Is a send queue" flag */
61         int is_send;
62         /** Associated completion queue */
63         struct ib_completion_queue *cq;
64         /** List of work queues on this completion queue */
65         struct list_head list;
66         /** Number of work queue entries */
67         unsigned int num_wqes;
68         /** Next work queue entry index
69          *
70          * This is the index of the next entry to be filled (i.e. the
71          * first empty entry).  This value is not bounded by num_wqes;
72          * users must logical-AND with (num_wqes-1) to generate an
73          * array index.
74          */
75         unsigned long next_idx;
76         /** I/O buffers assigned to work queue */
77         struct io_buffer **iobufs;
78         /** Driver private data */
79         void *drv_priv;
80 };
81
82 /** An Infiniband Queue Pair */
83 struct ib_queue_pair {
84         /** Queue Pair Number */
85         unsigned long qpn;
86         /** Queue key */
87         unsigned long qkey;
88         /** Send queue */
89         struct ib_work_queue send;
90         /** Receive queue */
91         struct ib_work_queue recv;
92         /** Driver private data */
93         void *drv_priv;
94         /** Queue owner private data */
95         void *owner_priv;
96 };
97
98 /** An Infiniband Completion Queue */
99 struct ib_completion_queue {
100         /** Completion queue number */
101         unsigned long cqn;
102         /** Number of completion queue entries */
103         unsigned int num_cqes;
104         /** Next completion queue entry index
105          *
106          * This is the index of the next entry to be filled (i.e. the
107          * first empty entry).  This value is not bounded by num_wqes;
108          * users must logical-AND with (num_wqes-1) to generate an
109          * array index.
110          */
111         unsigned long next_idx;
112         /** List of work queues completing to this queue */
113         struct list_head work_queues;
114         /** Driver private data */
115         void *drv_priv;
116 };
117
118 /** An Infiniband completion */
119 struct ib_completion {
120         /** Syndrome
121          *
122          * If non-zero, then the completion is in error.
123          */
124         unsigned int syndrome;
125         /** Length */
126         size_t len;
127 };
128
129 /** An Infiniband completion handler
130  *
131  * @v ibdev             Infiniband device
132  * @v qp                Queue pair
133  * @v completion        Completion
134  * @v iobuf             I/O buffer
135  */
136 typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
137                                     struct ib_queue_pair *qp,
138                                     struct ib_completion *completion,
139                                     struct io_buffer *iobuf );
140
141 /** An Infiniband Address Vector */
142 struct ib_address_vector {
143         /** Destination Queue Pair */
144         unsigned int dest_qp;
145         /** Queue key */
146         unsigned long qkey;
147         /** Destination Local ID */
148         unsigned int dlid;
149         /** Rate */
150         unsigned int rate;
151         /** Service level */
152         unsigned int sl;
153         /** GID is present */
154         unsigned int gid_present;
155         /** GID */
156         struct ib_gid gid;
157 };
158
159 struct ib_mad_hdr;
160
161 /**
162  * Infiniband device operations
163  *
164  * These represent a subset of the Infiniband Verbs.
165  */
166 struct ib_device_operations {
167         /** Create completion queue
168          *
169          * @v ibdev             Infiniband device
170          * @v cq                Completion queue
171          * @ret rc              Return status code
172          */
173         int ( * create_cq ) ( struct ib_device *ibdev,
174                               struct ib_completion_queue *cq );
175         /** Destroy completion queue
176          *
177          * @v ibdev             Infiniband device
178          * @v cq                Completion queue
179          */
180         void ( * destroy_cq ) ( struct ib_device *ibdev,
181                                 struct ib_completion_queue *cq );
182         /** Create queue pair
183          *
184          * @v ibdev             Infiniband device
185          * @v qp                Queue pair
186          * @ret rc              Return status code
187          */
188         int ( * create_qp ) ( struct ib_device *ibdev,
189                               struct ib_queue_pair *qp );
190         /** Destroy queue pair
191          *
192          * @v ibdev             Infiniband device
193          * @v qp                Queue pair
194          */
195         void ( * destroy_qp ) ( struct ib_device *ibdev,
196                                 struct ib_queue_pair *qp );
197         /** Post send work queue entry
198          *
199          * @v ibdev             Infiniband device
200          * @v qp                Queue pair
201          * @v av                Address vector
202          * @v iobuf             I/O buffer
203          * @ret rc              Return status code
204          *
205          * If this method returns success, the I/O buffer remains
206          * owned by the queue pair.  If this method returns failure,
207          * the I/O buffer is immediately released; the failure is
208          * interpreted as "failure to enqueue buffer".
209          */
210         int ( * post_send ) ( struct ib_device *ibdev,
211                               struct ib_queue_pair *qp,
212                               struct ib_address_vector *av,
213                               struct io_buffer *iobuf );
214         /** Post receive work queue entry
215          *
216          * @v ibdev             Infiniband device
217          * @v qp                Queue pair
218          * @v iobuf             I/O buffer
219          * @ret rc              Return status code
220          *
221          * If this method returns success, the I/O buffer remains
222          * owned by the queue pair.  If this method returns failure,
223          * the I/O buffer is immediately released; the failure is
224          * interpreted as "failure to enqueue buffer".
225          */
226         int ( * post_recv ) ( struct ib_device *ibdev,
227                               struct ib_queue_pair *qp,
228                               struct io_buffer *iobuf );
229         /** Poll completion queue
230          *
231          * @v ibdev             Infiniband device
232          * @v cq                Completion queue
233          * @v complete_send     Send completion handler
234          * @v complete_recv     Receive completion handler
235          *
236          * The completion handler takes ownership of the I/O buffer.
237          */
238         void ( * poll_cq ) ( struct ib_device *ibdev,
239                              struct ib_completion_queue *cq,
240                              ib_completer_t complete_send,
241                              ib_completer_t complete_recv );
242         /**
243          * Open port
244          *
245          * @v ibdev             Infiniband device
246          * @ret rc              Return status code
247          */
248         int ( * open ) ( struct ib_device *ibdev );
249         /**
250          * Close port
251          *
252          * @v ibdev             Infiniband device
253          */
254         void ( * close ) ( struct ib_device *ibdev );
255         /** Attach to multicast group
256          *
257          * @v ibdev             Infiniband device
258          * @v qp                Queue pair
259          * @v gid               Multicast GID
260          * @ret rc              Return status code
261          */
262         int ( * mcast_attach ) ( struct ib_device *ibdev,
263                                  struct ib_queue_pair *qp,
264                                  struct ib_gid *gid );
265         /** Detach from multicast group
266          *
267          * @v ibdev             Infiniband device
268          * @v qp                Queue pair
269          * @v gid               Multicast GID
270          */
271         void ( * mcast_detach ) ( struct ib_device *ibdev,
272                                   struct ib_queue_pair *qp,
273                                   struct ib_gid *gid );
274         /**
275          * Issue management datagram
276          *
277          * @v ibdev             Infiniband device
278          * @v mad               Management datagram
279          * @v len               Length of management datagram
280          * @ret rc              Return status code
281          */
282         int ( * mad ) ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
283                         size_t len );
284 };
285
286 /** An Infiniband device */
287 struct ib_device {
288         /** Underlying device */
289         struct device *dev;
290         /** Infiniband operations */
291         struct ib_device_operations *op;
292         /** Port number */
293         unsigned int port;
294         /** Port GID */
295         struct ib_gid port_gid;
296         /** Subnet manager LID */
297         unsigned long sm_lid;
298         /** Partition key */
299         unsigned int pkey;
300         /** Driver private data */
301         void *drv_priv;
302         /** Owner private data */
303         void *owner_priv;
304 };
305
306 extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
307                                                    unsigned int num_cqes );
308 extern void ib_destroy_cq ( struct ib_device *ibdev,
309                             struct ib_completion_queue *cq );
310 extern struct ib_queue_pair *
311 ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes,
312                struct ib_completion_queue *send_cq, unsigned int num_recv_wqes,
313                struct ib_completion_queue *recv_cq, unsigned long qkey );
314 extern void ib_destroy_qp ( struct ib_device *ibdev,
315                             struct ib_queue_pair *qp );
316 extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
317                                            unsigned long qpn, int is_send );
318 extern struct ib_device * alloc_ibdev ( size_t priv_size );
319 extern int register_ibdev ( struct ib_device *ibdev );
320 extern void unregister_ibdev ( struct ib_device *ibdev );
321 extern void free_ibdev ( struct ib_device *ibdev );
322
323 /**
324  * Post send work queue entry
325  *
326  * @v ibdev             Infiniband device
327  * @v qp                Queue pair
328  * @v av                Address vector
329  * @v iobuf             I/O buffer
330  * @ret rc              Return status code
331  */
332 static inline __attribute__ (( always_inline )) int
333 ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
334                struct ib_address_vector *av, struct io_buffer *iobuf ) {
335         return ibdev->op->post_send ( ibdev, qp, av, iobuf );
336 }
337
338 /**
339  * Post receive work queue entry
340  *
341  * @v ibdev             Infiniband device
342  * @v qp                Queue pair
343  * @v iobuf             I/O buffer
344  * @ret rc              Return status code
345  */
346 static inline __attribute__ (( always_inline )) int
347 ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
348                struct io_buffer *iobuf ) {
349         return ibdev->op->post_recv ( ibdev, qp, iobuf );
350 }
351
352 /**
353  * Poll completion queue
354  *
355  * @v ibdev             Infiniband device
356  * @v cq                Completion queue
357  * @v complete_send     Send completion handler
358  * @v complete_recv     Receive completion handler
359  */
360 static inline __attribute__ (( always_inline )) void
361 ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq,
362              ib_completer_t complete_send, ib_completer_t complete_recv ) {
363         ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv );
364 }
365
366 /**
367  * Open port
368  *
369  * @v ibdev             Infiniband device
370  * @ret rc              Return status code
371  */
372 static inline __attribute__ (( always_inline )) int
373 ib_open ( struct ib_device *ibdev ) {
374         return ibdev->op->open ( ibdev );
375 }
376
377 /**
378  * Close port
379  *
380  * @v ibdev             Infiniband device
381  */
382 static inline __attribute__ (( always_inline )) void
383 ib_close ( struct ib_device *ibdev ) {
384         ibdev->op->close ( ibdev );
385 }
386
387 /**
388  * Attach to multicast group
389  *
390  * @v ibdev             Infiniband device
391  * @v qp                Queue pair
392  * @v gid               Multicast GID
393  * @ret rc              Return status code
394  */
395 static inline __attribute__ (( always_inline )) int
396 ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
397                   struct ib_gid *gid ) {
398         return ibdev->op->mcast_attach ( ibdev, qp, gid );
399 }
400
401 /**
402  * Detach from multicast group
403  *
404  * @v ibdev             Infiniband device
405  * @v qp                Queue pair
406  * @v gid               Multicast GID
407  */
408 static inline __attribute__ (( always_inline )) void
409 ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
410                   struct ib_gid *gid ) {
411         ibdev->op->mcast_detach ( ibdev, qp, gid );
412 }
413
414 /**
415  * Issue management datagram
416  *
417  * @v ibdev             Infiniband device
418  * @v mad               Management datagram
419  * @v len               Length of management datagram
420  * @ret rc              Return status code
421  */
422 static inline __attribute__ (( always_inline )) int
423 ib_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) {
424         return ibdev->op->mad ( ibdev, mad, len );
425 }
426
427 /**
428  * Set Infiniband work queue driver-private data
429  *
430  * @v wq                Work queue
431  * @v priv              Private data
432  */
433 static inline __attribute__ (( always_inline )) void
434 ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) {
435         wq->drv_priv = priv;
436 }
437
438 /**
439  * Get Infiniband work queue driver-private data
440  *
441  * @v wq                Work queue
442  * @ret priv            Private data
443  */
444 static inline __attribute__ (( always_inline )) void *
445 ib_wq_get_drvdata ( struct ib_work_queue *wq ) {
446         return wq->drv_priv;
447 }
448
449 /**
450  * Set Infiniband queue pair driver-private data
451  *
452  * @v qp                Queue pair
453  * @v priv              Private data
454  */
455 static inline __attribute__ (( always_inline )) void
456 ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) {
457         qp->drv_priv = priv;
458 }
459
460 /**
461  * Get Infiniband queue pair driver-private data
462  *
463  * @v qp                Queue pair
464  * @ret priv            Private data
465  */
466 static inline __attribute__ (( always_inline )) void *
467 ib_qp_get_drvdata ( struct ib_queue_pair *qp ) {
468         return qp->drv_priv;
469 }
470
471 /**
472  * Set Infiniband queue pair owner-private data
473  *
474  * @v qp                Queue pair
475  * @v priv              Private data
476  */
477 static inline __attribute__ (( always_inline )) void
478 ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) {
479         qp->owner_priv = priv;
480 }
481
482 /**
483  * Get Infiniband queue pair owner-private data
484  *
485  * @v qp                Queue pair
486  * @ret priv            Private data
487  */
488 static inline __attribute__ (( always_inline )) void *
489 ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) {
490         return qp->owner_priv;
491 }
492
493 /**
494  * Set Infiniband completion queue driver-private data
495  *
496  * @v cq                Completion queue
497  * @v priv              Private data
498  */
499 static inline __attribute__ (( always_inline )) void
500 ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) {
501         cq->drv_priv = priv;
502 }
503
504 /**
505  * Get Infiniband completion queue driver-private data
506  *
507  * @v cq                Completion queue
508  * @ret priv            Private data
509  */
510 static inline __attribute__ (( always_inline )) void *
511 ib_cq_get_drvdata ( struct ib_completion_queue *cq ) {
512         return cq->drv_priv;
513 }
514
515 /**
516  * Set Infiniband device driver-private data
517  *
518  * @v ibdev             Infiniband device
519  * @v priv              Private data
520  */
521 static inline __attribute__ (( always_inline )) void
522 ib_set_drvdata ( struct ib_device *ibdev, void *priv ) {
523         ibdev->drv_priv = priv;
524 }
525
526 /**
527  * Get Infiniband device driver-private data
528  *
529  * @v ibdev             Infiniband device
530  * @ret priv            Private data
531  */
532 static inline __attribute__ (( always_inline )) void *
533 ib_get_drvdata ( struct ib_device *ibdev ) {
534         return ibdev->drv_priv;
535 }
536
537 /**
538  * Set Infiniband device owner-private data
539  *
540  * @v ibdev             Infiniband device
541  * @v priv              Private data
542  */
543 static inline __attribute__ (( always_inline )) void
544 ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
545         ibdev->owner_priv = priv;
546 }
547
548 /**
549  * Get Infiniband device owner-private data
550  *
551  * @v ibdev             Infiniband device
552  * @ret priv            Private data
553  */
554 static inline __attribute__ (( always_inline )) void *
555 ib_get_ownerdata ( struct ib_device *ibdev ) {
556         return ibdev->owner_priv;
557 }
558
559 /*****************************************************************************
560  *
561  * Management datagrams
562  *
563  * Portions Copyright (c) 2004 Mellanox Technologies Ltd.  All rights
564  * reserved.
565  *
566  */
567
568 /* Management base version */
569 #define IB_MGMT_BASE_VERSION                    1
570
571 /* Management classes */
572 #define IB_MGMT_CLASS_SUBN_LID_ROUTED           0x01
573 #define IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE       0x81
574 #define IB_MGMT_CLASS_SUBN_ADM                  0x03
575 #define IB_MGMT_CLASS_PERF_MGMT                 0x04
576 #define IB_MGMT_CLASS_BM                        0x05
577 #define IB_MGMT_CLASS_DEVICE_MGMT               0x06
578 #define IB_MGMT_CLASS_CM                        0x07
579 #define IB_MGMT_CLASS_SNMP                      0x08
580 #define IB_MGMT_CLASS_VENDOR_RANGE2_START       0x30
581 #define IB_MGMT_CLASS_VENDOR_RANGE2_END         0x4F
582
583 /* Management methods */
584 #define IB_MGMT_METHOD_GET                      0x01
585 #define IB_MGMT_METHOD_SET                      0x02
586 #define IB_MGMT_METHOD_GET_RESP                 0x81
587 #define IB_MGMT_METHOD_SEND                     0x03
588 #define IB_MGMT_METHOD_TRAP                     0x05
589 #define IB_MGMT_METHOD_REPORT                   0x06
590 #define IB_MGMT_METHOD_REPORT_RESP              0x86
591 #define IB_MGMT_METHOD_TRAP_REPRESS             0x07
592 #define IB_MGMT_METHOD_DELETE                   0x15
593 #define IB_MGMT_METHOD_RESP                     0x80
594
595 /* Subnet management attributes */
596 #define IB_SMP_ATTR_NOTICE                      0x0002
597 #define IB_SMP_ATTR_NODE_DESC                   0x0010
598 #define IB_SMP_ATTR_NODE_INFO                   0x0011
599 #define IB_SMP_ATTR_SWITCH_INFO                 0x0012
600 #define IB_SMP_ATTR_GUID_INFO                   0x0014
601 #define IB_SMP_ATTR_PORT_INFO                   0x0015
602 #define IB_SMP_ATTR_PKEY_TABLE                  0x0016
603 #define IB_SMP_ATTR_SL_TO_VL_TABLE              0x0017
604 #define IB_SMP_ATTR_VL_ARB_TABLE                0x0018
605 #define IB_SMP_ATTR_LINEAR_FORWARD_TABLE        0x0019
606 #define IB_SMP_ATTR_RANDOM_FORWARD_TABLE        0x001A
607 #define IB_SMP_ATTR_MCAST_FORWARD_TABLE         0x001B
608 #define IB_SMP_ATTR_SM_INFO                     0x0020
609 #define IB_SMP_ATTR_VENDOR_DIAG                 0x0030
610 #define IB_SMP_ATTR_LED_INFO                    0x0031
611 #define IB_SMP_ATTR_VENDOR_MASK                 0xFF00
612
613 #define IB_SA_ATTR_MC_MEMBER_REC                0x38
614 #define IB_SA_ATTR_PATH_REC                     0x35
615
616 #define IB_SA_MCMEMBER_REC_MGID                 (1<<0)
617 #define IB_SA_MCMEMBER_REC_PORT_GID             (1<<1)
618 #define IB_SA_MCMEMBER_REC_QKEY                 (1<<2)
619 #define IB_SA_MCMEMBER_REC_MLID                 (1<<3)
620 #define IB_SA_MCMEMBER_REC_MTU_SELECTOR         (1<<4)
621 #define IB_SA_MCMEMBER_REC_MTU                  (1<<5)
622 #define IB_SA_MCMEMBER_REC_TRAFFIC_CLASS        (1<<6)
623 #define IB_SA_MCMEMBER_REC_PKEY                 (1<<7)
624 #define IB_SA_MCMEMBER_REC_RATE_SELECTOR        (1<<8)
625 #define IB_SA_MCMEMBER_REC_RATE                 (1<<9)
626 #define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR    (1<<10)
627 #define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME     (1<<11)
628 #define IB_SA_MCMEMBER_REC_SL                   (1<<12)
629 #define IB_SA_MCMEMBER_REC_FLOW_LABEL           (1<<13)
630 #define IB_SA_MCMEMBER_REC_HOP_LIMIT            (1<<14)
631 #define IB_SA_MCMEMBER_REC_SCOPE                (1<<15)
632 #define IB_SA_MCMEMBER_REC_JOIN_STATE           (1<<16)
633 #define IB_SA_MCMEMBER_REC_PROXY_JOIN           (1<<17)
634
635 #define IB_SA_PATH_REC_DGID                     (1<<2)
636 #define IB_SA_PATH_REC_SGID                     (1<<3)
637
638 struct ib_mad_hdr {
639         uint8_t base_version;
640         uint8_t mgmt_class;
641         uint8_t class_version;
642         uint8_t method;
643         uint16_t status;
644         uint16_t class_specific;
645         uint32_t tid[2];
646         uint16_t attr_id;
647         uint16_t resv;
648         uint32_t attr_mod;
649 } __attribute__ (( packed ));
650
651 struct ib_sa_hdr {
652         uint32_t sm_key[2];
653         uint16_t reserved;
654         uint16_t attrib_offset;
655         uint32_t comp_mask[2];
656 } __attribute__ (( packed ));
657
658 struct ib_rmpp_hdr {
659         uint32_t raw[3];
660 } __attribute__ (( packed ));
661
662 struct ib_mad_data {
663         struct ib_mad_hdr mad_hdr;
664         uint8_t data[232];
665 } __attribute__ (( packed ));
666
667 struct ib_mad_guid_info {
668         struct ib_mad_hdr mad_hdr;
669         uint32_t mkey[2];
670         uint32_t reserved[8];
671         uint8_t gid_local[8];
672 } __attribute__ (( packed ));
673
674 struct ib_mad_port_info {
675         struct ib_mad_hdr mad_hdr;
676         uint32_t mkey[2];
677         uint32_t reserved[8];
678         uint32_t mkey2[2];
679         uint8_t gid_prefix[8];
680         uint16_t lid;
681         uint16_t mastersm_lid;
682         uint32_t cap_mask;
683         uint16_t diag_code;
684         uint16_t mkey_lease_period;
685         uint8_t local_port_num;
686         uint8_t link_width_enabled;
687         uint8_t link_width_supported;
688         uint8_t link_width_active;
689         uint8_t port_state__link_speed_supported;
690         uint8_t link_down_def_state__port_phys_state;
691         uint8_t lmc__r1__mkey_prot_bits;
692         uint8_t link_speed_enabled__link_speed_active;
693 } __attribute__ (( packed ));
694
695 struct ib_mad_pkey_table {
696         struct ib_mad_hdr mad_hdr;
697         uint32_t mkey[2];
698         uint32_t reserved[8];
699         uint16_t pkey[16][2];
700 } __attribute__ (( packed ));
701
702 struct ib_mad_path_record {
703         struct ib_mad_hdr mad_hdr;
704         struct ib_rmpp_hdr rmpp_hdr;
705         struct ib_sa_hdr sa_hdr;
706         uint32_t reserved0[2];
707         struct ib_gid dgid;
708         struct ib_gid sgid;
709         uint16_t dlid;
710         uint16_t slid;
711         uint32_t hop_limit__flow_label__raw_traffic;
712         uint32_t pkey__numb_path__reversible__tclass;
713         uint8_t reserved1;
714         uint8_t reserved__sl;
715         uint8_t mtu_selector__mtu;
716         uint8_t rate_selector__rate;
717         uint32_t preference__packet_lifetime__packet_lifetime_selector;
718         uint32_t reserved2[35];
719 } __attribute__ (( packed ));
720
721 struct ib_mad_mc_member_record {
722         struct ib_mad_hdr mad_hdr;
723         struct ib_rmpp_hdr rmpp_hdr;
724         struct ib_sa_hdr sa_hdr;
725         struct ib_gid mgid;
726         struct ib_gid port_gid;
727         uint32_t qkey;
728         uint16_t mlid;
729         uint8_t mtu_selector__mtu;
730         uint8_t tclass;
731         uint16_t pkey;
732         uint8_t rate_selector__rate;
733         uint8_t packet_lifetime_selector__packet_lifetime;
734         uint32_t sl__flow_label__hop_limit;
735         uint8_t scope__join_state;
736         uint8_t proxy_join__reserved;
737         uint16_t reserved0;
738         uint32_t reserved1[37];
739 } __attribute__ (( packed ));
740
741 union ib_mad {
742         struct ib_mad_hdr mad_hdr;
743         struct ib_mad_data data;
744         struct ib_mad_guid_info guid_info;
745         struct ib_mad_port_info port_info;
746         struct ib_mad_pkey_table pkey_table;
747         struct ib_mad_path_record path_record;
748         struct ib_mad_mc_member_record mc_member_record;
749 } __attribute__ (( packed ));
750
751 #endif /* _GPXE_INFINIBAND_H */