[infiniband] Centralise SMA and GMA queue constants
[people/peper/gpxe.git] / src / drivers / net / ipoib.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <byteswap.h>
26 #include <errno.h>
27 #include <gpxe/if_arp.h>
28 #include <gpxe/iobuf.h>
29 #include <gpxe/netdevice.h>
30 #include <gpxe/infiniband.h>
31 #include <gpxe/ib_qset.h>
32 #include <gpxe/ipoib.h>
33
34 /** @file
35  *
36  * IP over Infiniband
37  */
38
39 /** Number of IPoIB data send work queue entries */
40 #define IPOIB_DATA_NUM_SEND_WQES 2
41
42 /** Number of IPoIB data receive work queue entries */
43 #define IPOIB_DATA_NUM_RECV_WQES 4
44
45 /** Number of IPoIB data completion entries */
46 #define IPOIB_DATA_NUM_CQES 8
47
48 /** Number of IPoIB metadata send work queue entries */
49 #define IPOIB_META_NUM_SEND_WQES 2
50
51 /** Number of IPoIB metadata receive work queue entries */
52 #define IPOIB_META_NUM_RECV_WQES 2
53
54 /** Number of IPoIB metadata completion entries */
55 #define IPOIB_META_NUM_CQES 8
56
57 /** An IPoIB device */
58 struct ipoib_device {
59         /** Network device */
60         struct net_device *netdev;
61         /** Underlying Infiniband device */
62         struct ib_device *ibdev;
63         /** Data queue set */
64         struct ib_queue_set data;
65         /** Data queue set */
66         struct ib_queue_set meta;
67         /** Broadcast GID */
68         struct ib_gid broadcast_gid;
69         /** Broadcast LID */
70         unsigned int broadcast_lid;
71         /** Data queue key */
72         unsigned long data_qkey;
73         /** Attached to multicast group
74          *
75          * This flag indicates whether or not we have attached our
76          * data queue pair to the broadcast multicast GID.
77          */
78         int broadcast_attached;
79 };
80
81 /** TID half used to identify get path record replies */
82 #define IPOIB_TID_GET_PATH_REC 0x11111111UL
83
84 /** TID half used to identify multicast member record replies */
85 #define IPOIB_TID_MC_MEMBER_REC 0x22222222UL
86
87 /** IPoIB metadata TID */
88 static uint32_t ipoib_meta_tid = 0;
89
90 /** Broadcast QPN used in IPoIB MAC addresses
91  *
92  * This is a guaranteed invalid real QPN
93  */
94 #define IPOIB_BROADCAST_QPN 0xffffffffUL
95
96 /** Broadcast IPoIB address */
97 static struct ipoib_mac ipoib_broadcast = {
98         .qpn = ntohl ( IPOIB_BROADCAST_QPN ),
99         .gid.u.bytes =  { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
100                           0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
101 };
102
103 /****************************************************************************
104  *
105  * IPoIB peer cache
106  *
107  ****************************************************************************
108  */
109
110 /**
111  * IPoIB peer address
112  *
113  * This serves a similar role to the ARP cache for Ethernet.  (ARP
114  * *is* used on IPoIB; we have two caches to maintain.)
115  */
116 struct ipoib_peer {
117         /** Key */
118         uint8_t key;
119         /** MAC address */
120         struct ipoib_mac mac;
121         /** LID */
122         unsigned int lid;
123         /** Service level */
124         unsigned int sl;
125         /** Rate */
126         unsigned int rate;
127 };
128
129 /** Number of IPoIB peer cache entries
130  *
131  * Must be a power of two.
132  */
133 #define IPOIB_NUM_CACHED_PEERS 4
134
135 /** IPoIB peer address cache */
136 static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS];
137
138 /** Oldest IPoIB peer cache entry index */
139 static unsigned int ipoib_peer_cache_idx = 1;
140
141 /**
142  * Look up cached peer by key
143  *
144  * @v key               Peer cache key
145  * @ret peer            Peer cache entry, or NULL
146  */
147 static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) {
148         struct ipoib_peer *peer;
149         unsigned int i;
150
151         for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
152                 peer = &ipoib_peer_cache[i];
153                 if ( peer->key == key )
154                         return peer;
155         }
156
157         if ( key != 0 ) {
158                 DBG ( "IPoIB warning: peer cache lost track of key %x while "
159                       "still in use\n", key );
160         }
161         return NULL;
162 }
163
164 /**
165  * Look up cached peer by GID
166  *
167  * @v gid               Peer GID
168  * @ret peer            Peer cache entry, or NULL
169  */
170 static struct ipoib_peer *
171 ipoib_lookup_peer_by_gid ( const struct ib_gid *gid ) {
172         struct ipoib_peer *peer;
173         unsigned int i;
174
175         for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
176                 peer = &ipoib_peer_cache[i];
177                 if ( memcmp ( &peer->mac.gid, gid,
178                               sizeof ( peer->mac.gid) ) == 0 ) {
179                         return peer;
180                 }
181         }
182
183         return NULL;
184 }
185
186 /**
187  * Store GID and QPN in peer cache
188  *
189  * @v gid               Peer GID
190  * @v qpn               Peer QPN
191  * @ret peer            Peer cache entry
192  */
193 static struct ipoib_peer *
194 ipoib_cache_peer ( const struct ib_gid *gid, unsigned long qpn ) {
195         struct ipoib_peer *peer;
196         unsigned int key;
197
198         /* Look for existing cache entry */
199         peer = ipoib_lookup_peer_by_gid ( gid );
200         if ( peer ) {
201                 assert ( peer->mac.qpn = ntohl ( qpn ) );
202                 return peer;
203         }
204
205         /* No entry found: create a new one */
206         key = ipoib_peer_cache_idx++;
207         peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ];
208         if ( peer->key )
209                 DBG ( "IPoIB peer %x evicted from cache\n", peer->key );
210
211         memset ( peer, 0, sizeof ( *peer ) );
212         peer->key = key;
213         peer->mac.qpn = htonl ( qpn );
214         memcpy ( &peer->mac.gid, gid, sizeof ( peer->mac.gid ) );
215         DBG ( "IPoIB peer %x has GID %08x:%08x:%08x:%08x and QPN %lx\n",
216               peer->key, htonl ( gid->u.dwords[0] ),
217               htonl ( gid->u.dwords[1] ), htonl ( gid->u.dwords[2] ),
218               htonl ( gid->u.dwords[3] ), qpn );
219         return peer;
220 }
221
222 /****************************************************************************
223  *
224  * IPoIB link layer
225  *
226  ****************************************************************************
227  */
228
229 /**
230  * Add IPoIB link-layer header
231  *
232  * @v netdev            Network device
233  * @v iobuf             I/O buffer
234  * @v ll_dest           Link-layer destination address
235  * @v ll_source         Source link-layer address
236  * @v net_proto         Network-layer protocol, in network-byte order
237  * @ret rc              Return status code
238  */
239 static int ipoib_push ( struct net_device *netdev __unused,
240                         struct io_buffer *iobuf, const void *ll_dest,
241                         const void *ll_source __unused, uint16_t net_proto ) {
242         struct ipoib_hdr *ipoib_hdr =
243                 iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
244         const struct ipoib_mac *dest_mac = ll_dest;
245         const struct ipoib_mac *src_mac = ll_source;
246         struct ipoib_peer *dest;
247         struct ipoib_peer *src;
248
249         /* Add link-layer addresses to cache */
250         dest = ipoib_cache_peer ( &dest_mac->gid, ntohl ( dest_mac->qpn ) );
251         src = ipoib_cache_peer ( &src_mac->gid, ntohl ( src_mac->qpn ) );
252
253         /* Build IPoIB header */
254         ipoib_hdr->proto = net_proto;
255         ipoib_hdr->u.peer.dest = dest->key;
256         ipoib_hdr->u.peer.src = src->key;
257
258         return 0;
259 }
260
261 /**
262  * Remove IPoIB link-layer header
263  *
264  * @v netdev            Network device
265  * @v iobuf             I/O buffer
266  * @ret ll_dest         Link-layer destination address
267  * @ret ll_source       Source link-layer address
268  * @ret net_proto       Network-layer protocol, in network-byte order
269  * @ret rc              Return status code
270  */
271 static int ipoib_pull ( struct net_device *netdev __unused,
272                         struct io_buffer *iobuf, const void **ll_dest,
273                         const void **ll_source, uint16_t *net_proto ) {
274         struct ipoib_hdr *ipoib_hdr = iobuf->data;
275         struct ipoib_peer *dest;
276         struct ipoib_peer *source;
277
278         /* Sanity check */
279         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
280                 DBG ( "IPoIB packet too short for link-layer header\n" );
281                 DBG_HD ( iobuf->data, iob_len ( iobuf ) );
282                 return -EINVAL;
283         }
284
285         /* Strip off IPoIB header */
286         iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
287
288         /* Identify source and destination addresses, and clear
289          * reserved word in IPoIB header
290          */
291         dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
292         source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src );
293         ipoib_hdr->u.reserved = 0;
294
295         /* Fill in required fields */
296         *ll_dest = ( dest ? &dest->mac : &ipoib_broadcast );
297         *ll_source = ( source ? &source->mac : &ipoib_broadcast );
298         *net_proto = ipoib_hdr->proto;
299
300         return 0;
301 }
302
303 /**
304  * Transcribe IPoIB address
305  *
306  * @v ll_addr   Link-layer address
307  * @ret string  Link-layer address in human-readable format
308  */
309 const char * ipoib_ntoa ( const void *ll_addr ) {
310         static char buf[45];
311         const struct ipoib_mac *mac = ll_addr;
312
313         snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x",
314                    htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
315                    htonl ( mac->gid.u.dwords[1] ),
316                    htonl ( mac->gid.u.dwords[2] ),
317                    htonl ( mac->gid.u.dwords[3] ) );
318         return buf;
319 }
320
321 /**
322  * Hash multicast address
323  *
324  * @v af                Address family
325  * @v net_addr          Network-layer address
326  * @v ll_addr           Link-layer address to fill in
327  * @ret rc              Return status code
328  */
329 static int ipoib_mc_hash ( unsigned int af __unused,
330                            const void *net_addr __unused,
331                            void *ll_addr __unused ) {
332
333         return -ENOTSUP;
334 }
335
336 /** IPoIB protocol */
337 struct ll_protocol ipoib_protocol __ll_protocol = {
338         .name           = "IPoIB",
339         .ll_proto       = htons ( ARPHRD_INFINIBAND ),
340         .ll_addr_len    = IPOIB_ALEN,
341         .ll_header_len  = IPOIB_HLEN,
342         .push           = ipoib_push,
343         .pull           = ipoib_pull,
344         .ntoa           = ipoib_ntoa,
345         .mc_hash        = ipoib_mc_hash,
346 };
347
348 /****************************************************************************
349  *
350  * IPoIB network device
351  *
352  ****************************************************************************
353  */
354
355 /**
356  * Transmit path record request
357  *
358  * @v ipoib             IPoIB device
359  * @v gid               Destination GID
360  * @ret rc              Return status code
361  */
362 static int ipoib_get_path_record ( struct ipoib_device *ipoib,
363                                    struct ib_gid *gid ) {
364         struct ib_device *ibdev = ipoib->ibdev;
365         struct io_buffer *iobuf;
366         struct ib_mad_sa *sa;
367         struct ib_address_vector av;
368         int rc;
369
370         /* Allocate I/O buffer */
371         iobuf = alloc_iob ( sizeof ( *sa ) );
372         if ( ! iobuf )
373                 return -ENOMEM;
374         iob_put ( iobuf, sizeof ( *sa ) );
375         sa = iobuf->data;
376         memset ( sa, 0, sizeof ( *sa ) );
377
378         /* Construct path record request */
379         sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
380         sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
381         sa->mad_hdr.class_version = 2;
382         sa->mad_hdr.method = IB_MGMT_METHOD_GET;
383         sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
384         sa->mad_hdr.tid[0] = IPOIB_TID_GET_PATH_REC;
385         sa->mad_hdr.tid[1] = ipoib_meta_tid++;
386         sa->sa_hdr.comp_mask[1] =
387                 htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
388         memcpy ( &sa->sa_data.path_record.dgid, gid,
389                  sizeof ( sa->sa_data.path_record.dgid ) );
390         memcpy ( &sa->sa_data.path_record.sgid, &ibdev->gid,
391                  sizeof ( sa->sa_data.path_record.sgid ) );
392
393         /* Construct address vector */
394         memset ( &av, 0, sizeof ( av ) );
395         av.lid = ibdev->sm_lid;
396         av.sl = ibdev->sm_sl;
397         av.qpn = IB_QPN_GMA;
398         av.qkey = IB_QKEY_GMA;
399
400         /* Post send request */
401         if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
402                                    iobuf ) ) != 0 ) {
403                 DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n",
404                        ipoib, strerror ( rc ) );
405                 free_iob ( iobuf );
406                 return rc;
407         }
408
409         return 0;
410 }
411
412 /**
413  * Transmit multicast group membership request
414  *
415  * @v ipoib             IPoIB device
416  * @v gid               Multicast GID
417  * @v join              Join (rather than leave) group
418  * @ret rc              Return status code
419  */
420 static int ipoib_mc_member_record ( struct ipoib_device *ipoib,
421                                     struct ib_gid *gid, int join ) {
422         struct ib_device *ibdev = ipoib->ibdev;
423         struct io_buffer *iobuf;
424         struct ib_mad_sa *sa;
425         struct ib_address_vector av;
426         int rc;
427
428         /* Allocate I/O buffer */
429         iobuf = alloc_iob ( sizeof ( *sa ) );
430         if ( ! iobuf )
431                 return -ENOMEM;
432         iob_put ( iobuf, sizeof ( *sa ) );
433         sa = iobuf->data;
434         memset ( sa, 0, sizeof ( *sa ) );
435
436         /* Construct path record request */
437         sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
438         sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
439         sa->mad_hdr.class_version = 2;
440         sa->mad_hdr.method =
441                 ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
442         sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
443         sa->mad_hdr.tid[0] = IPOIB_TID_MC_MEMBER_REC;
444         sa->mad_hdr.tid[1] = ipoib_meta_tid++;
445         sa->sa_hdr.comp_mask[1] =
446                 htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
447                         IB_SA_MCMEMBER_REC_JOIN_STATE );
448         sa->sa_data.mc_member_record.scope__join_state = 1;
449         memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
450                  sizeof ( sa->sa_data.mc_member_record.mgid ) );
451         memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
452                  sizeof ( sa->sa_data.mc_member_record.port_gid ) );
453
454         /* Construct address vector */
455         memset ( &av, 0, sizeof ( av ) );
456         av.lid = ibdev->sm_lid;
457         av.sl = ibdev->sm_sl;
458         av.qpn = IB_QPN_GMA;
459         av.qkey = IB_QKEY_GMA;
460
461         /* Post send request */
462         if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
463                                    iobuf ) ) != 0 ) {
464                 DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n",
465                        ipoib, strerror ( rc ) );
466                 free_iob ( iobuf );
467                 return rc;
468         }
469
470         return 0;
471 }
472
473 /**
474  * Transmit packet via IPoIB network device
475  *
476  * @v netdev            Network device
477  * @v iobuf             I/O buffer
478  * @ret rc              Return status code
479  */
480 static int ipoib_transmit ( struct net_device *netdev,
481                             struct io_buffer *iobuf ) {
482         struct ipoib_device *ipoib = netdev->priv;
483         struct ib_device *ibdev = ipoib->ibdev;
484         struct ipoib_hdr *ipoib_hdr;
485         struct ipoib_peer *dest;
486         struct ib_address_vector av;
487         struct ib_gid *gid;
488
489         /* Sanity check */
490         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
491                 DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
492                 return -EINVAL;
493         }
494         ipoib_hdr = iobuf->data;
495
496         /* Attempting transmission while link is down will put the
497          * queue pair into an error state, so don't try it.
498          */
499         if ( ! ib_link_ok ( ibdev ) )
500                 return -ENETUNREACH;
501
502         /* Identify destination address */
503         dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
504         if ( ! dest )
505                 return -ENXIO;
506         ipoib_hdr->u.reserved = 0;
507
508         /* Construct address vector */
509         memset ( &av, 0, sizeof ( av ) );
510         av.qkey = ipoib->data_qkey;
511         av.gid_present = 1;
512         if ( dest->mac.qpn == htonl ( IPOIB_BROADCAST_QPN ) ) {
513                 /* Broadcast */
514                 av.qpn = IB_QPN_BROADCAST;
515                 av.lid = ipoib->broadcast_lid;
516                 gid = &ipoib->broadcast_gid;
517         } else {
518                 /* Unicast */
519                 if ( ! dest->lid ) {
520                         /* No LID yet - get path record to fetch LID */
521                         ipoib_get_path_record ( ipoib, &dest->mac.gid );
522                         return -ENOENT;
523                 }
524                 av.qpn = ntohl ( dest->mac.qpn );
525                 av.lid = dest->lid;
526                 av.rate = dest->rate;
527                 av.sl = dest->sl;
528                 gid = &dest->mac.gid;
529         }
530         memcpy ( &av.gid, gid, sizeof ( av.gid ) );
531
532         return ib_post_send ( ibdev, ipoib->data.qp, &av, iobuf );
533 }
534
535 /**
536  * Handle IPoIB data send completion
537  *
538  * @v ibdev             Infiniband device
539  * @v qp                Queue pair
540  * @v iobuf             I/O buffer
541  * @v rc                Completion status code
542  */
543 static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
544                                        struct ib_queue_pair *qp,
545                                        struct io_buffer *iobuf, int rc ) {
546         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
547
548         netdev_tx_complete_err ( ipoib->netdev, iobuf, rc );
549 }
550
551 /**
552  * Handle IPoIB data receive completion
553  *
554  * @v ibdev             Infiniband device
555  * @v qp                Queue pair
556  * @v av                Address vector, or NULL
557  * @v iobuf             I/O buffer
558  * @v rc                Completion status code
559  */
560 static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
561                                        struct ib_queue_pair *qp,
562                                        struct ib_address_vector *av,
563                                        struct io_buffer *iobuf, int rc ) {
564         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
565         struct net_device *netdev = ipoib->netdev;
566         struct ipoib_hdr *ipoib_hdr;
567         struct ipoib_peer *src;
568
569         if ( rc != 0 ) {
570                 netdev_rx_err ( netdev, iobuf, rc );
571                 return;
572         }
573
574         /* Sanity check */
575         if ( iob_len ( iobuf ) < sizeof ( struct ipoib_hdr ) ) {
576                 DBGC ( ipoib, "IPoIB %p received data packet too short to "
577                        "contain IPoIB header\n", ipoib );
578                 DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
579                 netdev_rx_err ( netdev, iobuf, -EIO );
580                 return;
581         }
582         ipoib_hdr = iobuf->data;
583
584         /* Parse source address */
585         if ( av->gid_present ) {
586                 src = ipoib_cache_peer ( &av->gid, av->qpn );
587                 ipoib_hdr->u.peer.src = src->key;
588         }
589
590         /* Hand off to network layer */
591         netdev_rx ( netdev, iobuf );
592 }
593
594 /** IPoIB data completion operations */
595 static struct ib_completion_queue_operations ipoib_data_cq_op = {
596         .complete_send = ipoib_data_complete_send,
597         .complete_recv = ipoib_data_complete_recv,
598 };
599
600 /**
601  * Handle IPoIB metadata send completion
602  *
603  * @v ibdev             Infiniband device
604  * @v qp                Queue pair
605  * @v iobuf             I/O buffer
606  * @v rc                Completion status code
607  */
608 static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
609                                        struct ib_queue_pair *qp,
610                                        struct io_buffer *iobuf, int rc ) {
611         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
612
613         if ( rc != 0 ) {
614                 DBGC ( ipoib, "IPoIB %p metadata TX completion error: %s\n",
615                        ipoib, strerror ( rc ) );
616         }
617         free_iob ( iobuf );
618 }
619
620 /**
621  * Handle received IPoIB path record
622  *
623  * @v ipoib             IPoIB device
624  * @v path_record       Path record
625  */
626 static void ipoib_recv_path_record ( struct ipoib_device *ipoib,
627                                      struct ib_path_record *path_record ) {
628         struct ipoib_peer *peer;
629
630         /* Locate peer cache entry */
631         peer = ipoib_lookup_peer_by_gid ( &path_record->dgid );
632         if ( ! peer ) {
633                 DBGC ( ipoib, "IPoIB %p received unsolicited path record\n",
634                        ipoib );
635                 return;
636         }
637
638         /* Update path cache entry */
639         peer->lid = ntohs ( path_record->dlid );
640         peer->sl = ( path_record->reserved__sl & 0x0f );
641         peer->rate = ( path_record->rate_selector__rate & 0x3f );
642
643         DBG ( "IPoIB peer %x has dlid %x sl %x rate %x\n",
644               peer->key, peer->lid, peer->sl, peer->rate );
645 }
646
647 /**
648  * Handle received IPoIB multicast membership record
649  *
650  * @v ipoib             IPoIB device
651  * @v mc_member_record  Multicast membership record
652  */
653 static void ipoib_recv_mc_member_record ( struct ipoib_device *ipoib,
654                                struct ib_mc_member_record *mc_member_record ) {
655         int joined;
656         int rc;
657
658         /* Record parameters */
659         joined = ( mc_member_record->scope__join_state & 0x0f );
660         ipoib->data_qkey = ntohl ( mc_member_record->qkey );
661         ipoib->broadcast_lid = ntohs ( mc_member_record->mlid );
662         DBGC ( ipoib, "IPoIB %p %s broadcast group: qkey %lx mlid %x\n",
663                ipoib, ( joined ? "joined" : "left" ), ipoib->data_qkey,
664                ipoib->broadcast_lid );
665
666         /* Update data queue pair qkey */
667         if ( ( rc = ib_modify_qp ( ipoib->ibdev, ipoib->data.qp,
668                                    IB_MODIFY_QKEY, ipoib->data_qkey ) ) != 0 ){
669                 DBGC ( ipoib, "IPoIB %p could not update data qkey: %s\n",
670                        ipoib, strerror ( rc ) );
671                 return;
672         }
673 }
674
675 /**
676  * Handle IPoIB metadata receive completion
677  *
678  * @v ibdev             Infiniband device
679  * @v qp                Queue pair
680  * @v av                Address vector, or NULL
681  * @v iobuf             I/O buffer
682  * @v rc                Completion status code
683  */
684 static void
685 ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
686                            struct ib_queue_pair *qp,
687                            struct ib_address_vector *av __unused,
688                            struct io_buffer *iobuf, int rc ) {
689         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
690         struct ib_mad_sa *sa;
691
692         if ( rc != 0 ) {
693                 DBGC ( ipoib, "IPoIB %p metadata RX completion error: %s\n",
694                        ipoib, strerror ( rc ) );
695                 goto done;
696         }
697
698         if ( iob_len ( iobuf ) < sizeof ( *sa ) ) {
699                 DBGC ( ipoib, "IPoIB %p received metadata packet too short "
700                        "to contain reply\n", ipoib );
701                 DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
702                 goto done;
703         }
704         sa = iobuf->data;
705
706         if ( sa->mad_hdr.status != 0 ) {
707                 DBGC ( ipoib, "IPoIB %p metadata RX err status %04x\n",
708                        ipoib, ntohs ( sa->mad_hdr.status ) );
709                 goto done;
710         }
711
712         switch ( sa->mad_hdr.tid[0] ) {
713         case IPOIB_TID_GET_PATH_REC:
714                 ipoib_recv_path_record ( ipoib, &sa->sa_data.path_record );
715                 break;
716         case IPOIB_TID_MC_MEMBER_REC:
717                 ipoib_recv_mc_member_record ( ipoib,
718                                               &sa->sa_data.mc_member_record );
719                 break;
720         default:
721                 DBGC ( ipoib, "IPoIB %p unwanted response:\n",
722                        ipoib );
723                 DBGC_HD ( ipoib, sa, sizeof ( *sa ) );
724                 break;
725         }
726
727  done:
728         free_iob ( iobuf );
729 }
730
731 /** IPoIB metadata completion operations */
732 static struct ib_completion_queue_operations ipoib_meta_cq_op = {
733         .complete_send = ipoib_meta_complete_send,
734         .complete_recv = ipoib_meta_complete_recv,
735 };
736
737 /**
738  * Poll IPoIB network device
739  *
740  * @v netdev            Network device
741  */
742 static void ipoib_poll ( struct net_device *netdev ) {
743         struct ipoib_device *ipoib = netdev->priv;
744         struct ib_device *ibdev = ipoib->ibdev;
745
746         ib_poll_eq ( ibdev );
747 }
748
749 /**
750  * Enable/disable interrupts on IPoIB network device
751  *
752  * @v netdev            Network device
753  * @v enable            Interrupts should be enabled
754  */
755 static void ipoib_irq ( struct net_device *netdev __unused,
756                         int enable __unused ) {
757         /* No implementation */
758 }
759
760 /**
761  * Join IPv4 broadcast multicast group
762  *
763  * @v ipoib             IPoIB device
764  * @ret rc              Return status code
765  */
766 static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
767         int rc;
768
769         /* Sanity check */
770         if ( ! ipoib->data.qp )
771                 return 0;
772
773         /* Attach data queue to broadcast multicast GID */
774         assert ( ipoib->broadcast_attached == 0 );
775         if ( ( rc = ib_mcast_attach ( ipoib->ibdev, ipoib->data.qp,
776                                       &ipoib->broadcast_gid ) ) != 0 ){
777                 DBGC ( ipoib, "IPoIB %p could not attach to broadcast GID: "
778                        "%s\n", ipoib, strerror ( rc ) );
779                 return rc;
780         }
781         ipoib->broadcast_attached = 1;
782
783         /* Initiate broadcast group join */
784         if ( ( rc = ipoib_mc_member_record ( ipoib, &ipoib->broadcast_gid,
785                                              1 ) ) != 0 ) {
786                 DBGC ( ipoib, "IPoIB %p could not send broadcast join: %s\n",
787                        ipoib, strerror ( rc ) );
788                 return rc;
789         }
790
791         /* We will set link up on the network device when we receive
792          * the broadcast join response.
793          */
794
795         return 0;
796 }
797
798 /**
799  * Leave IPv4 broadcast multicast group
800  *
801  * @v ipoib             IPoIB device
802  */
803 static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
804
805         /* Detach data queue from broadcast multicast GID */
806         if ( ipoib->broadcast_attached ) {
807                 assert ( ipoib->data.qp != NULL );
808                 ib_mcast_detach ( ipoib->ibdev, ipoib->data.qp,
809                                   &ipoib->broadcast_gid );
810                 ipoib->broadcast_attached = 0;
811         }
812 }
813
814 /**
815  * Open IPoIB network device
816  *
817  * @v netdev            Network device
818  * @ret rc              Return status code
819  */
820 static int ipoib_open ( struct net_device *netdev ) {
821         struct ipoib_device *ipoib = netdev->priv;
822         struct ib_device *ibdev = ipoib->ibdev;
823         struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
824         int rc;
825
826         /* Open IB device */
827         if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
828                 DBGC ( ipoib, "IPoIB %p could not open device: %s\n",
829                        ipoib, strerror ( rc ) );
830                 goto err_ib_open;
831         }
832
833         /* Allocate metadata queue set */
834         if ( ( rc = ib_create_qset ( ibdev, &ipoib->meta,
835                                      IPOIB_META_NUM_CQES, &ipoib_meta_cq_op,
836                                      IPOIB_META_NUM_SEND_WQES,
837                                      IPOIB_META_NUM_RECV_WQES,
838                                      IB_QKEY_GMA ) ) != 0 ) {
839                 DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
840                        ipoib, strerror ( rc ) );
841                 goto err_create_meta_qset;
842         }
843         ib_qp_set_ownerdata ( ipoib->meta.qp, ipoib );
844
845         /* Allocate data queue set */
846         if ( ( rc = ib_create_qset ( ibdev, &ipoib->data,
847                                      IPOIB_DATA_NUM_CQES, &ipoib_data_cq_op,
848                                      IPOIB_DATA_NUM_SEND_WQES,
849                                      IPOIB_DATA_NUM_RECV_WQES,
850                                      IB_QKEY_GMA ) ) != 0 ) {
851                 DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
852                        ipoib, strerror ( rc ) );
853                 goto err_create_data_qset;
854         }
855         ib_qp_set_ownerdata ( ipoib->data.qp, ipoib );
856
857         /* Update MAC address with data QPN */
858         mac->qpn = htonl ( ipoib->data.qp->qpn );
859
860         /* Fill receive rings */
861         ib_refill_recv ( ibdev, ipoib->meta.qp );
862         ib_refill_recv ( ibdev, ipoib->data.qp );
863
864         /* Join broadcast group */
865         if ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) {
866                 DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
867                        ipoib, strerror ( rc ) );
868                 goto err_join_broadcast;
869         }
870
871         return 0;
872
873  err_join_broadcast:
874         ib_destroy_qset ( ibdev, &ipoib->data );
875  err_create_data_qset:
876         ib_destroy_qset ( ibdev, &ipoib->meta );
877  err_create_meta_qset:
878         ib_close ( ibdev );
879  err_ib_open:
880         return rc;
881 }
882
883 /**
884  * Close IPoIB network device
885  *
886  * @v netdev            Network device
887  */
888 static void ipoib_close ( struct net_device *netdev ) {
889         struct ipoib_device *ipoib = netdev->priv;
890         struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
891
892         /* Leave broadcast group */
893         ipoib_leave_broadcast_group ( ipoib );
894
895         /* Remove data QPN from MAC address */
896         mac->qpn = 0;
897
898         /* Tear down the queues */
899         ib_destroy_qset ( ipoib->ibdev, &ipoib->data );
900         ib_destroy_qset ( ipoib->ibdev, &ipoib->meta );
901
902         /* Close IB device */
903         ib_close ( ipoib->ibdev );
904 }
905
906 /** IPoIB network device operations */
907 static struct net_device_operations ipoib_operations = {
908         .open           = ipoib_open,
909         .close          = ipoib_close,
910         .transmit       = ipoib_transmit,
911         .poll           = ipoib_poll,
912         .irq            = ipoib_irq,
913 };
914
915 /**
916  * Update IPoIB dynamic Infiniband parameters
917  *
918  * @v ipoib             IPoIB device
919  *
920  * The Infiniband port GID and partition key will change at runtime,
921  * when the link is established (or lost).  The MAC address is based
922  * on the port GID, and the broadcast GID is based on the partition
923  * key.  This function recalculates these IPoIB device parameters.
924  */
925 static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
926         struct ib_device *ibdev = ipoib->ibdev;
927         struct net_device *netdev = ipoib->netdev;
928         struct ipoib_mac *mac;
929
930         /* Calculate GID portion of MAC address based on port GID */
931         mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
932         memcpy ( &mac->gid, &ibdev->gid, sizeof ( mac->gid ) );
933
934         /* Calculate broadcast GID based on partition key */
935         memcpy ( &ipoib->broadcast_gid, &ipoib_broadcast.gid,
936                  sizeof ( ipoib->broadcast_gid ) );
937         ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
938
939         /* Set net device link state to reflect Infiniband link state */
940         if ( ib_link_ok ( ibdev ) ) {
941                 netdev_link_up ( netdev );
942         } else {
943                 netdev_link_down ( netdev );
944         }
945 }
946
947 /**
948  * Handle link status change
949  *
950  * @v ibdev             Infiniband device
951  */
952 void ipoib_link_state_changed ( struct ib_device *ibdev ) {
953         struct net_device *netdev = ib_get_ownerdata ( ibdev );
954         struct ipoib_device *ipoib = netdev->priv;
955         int rc;
956
957         /* Leave existing broadcast group */
958         ipoib_leave_broadcast_group ( ipoib );
959
960         /* Update MAC address and broadcast GID based on new port GID
961          * and partition key.
962          */
963         ipoib_set_ib_params ( ipoib );
964
965         /* Join new broadcast group */
966         if ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) {
967                 DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
968                        "%s\n", ipoib, strerror ( rc ) );
969                 return;
970         }
971 }
972
973 /**
974  * Probe IPoIB device
975  *
976  * @v ibdev             Infiniband device
977  * @ret rc              Return status code
978  */
979 int ipoib_probe ( struct ib_device *ibdev ) {
980         struct net_device *netdev;
981         struct ipoib_device *ipoib;
982         int rc;
983
984         /* Allocate network device */
985         netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
986         if ( ! netdev )
987                 return -ENOMEM;
988         netdev_init ( netdev, &ipoib_operations );
989         ipoib = netdev->priv;
990         ib_set_ownerdata ( ibdev, netdev );
991         netdev->dev = ibdev->dev;
992         memset ( ipoib, 0, sizeof ( *ipoib ) );
993         ipoib->netdev = netdev;
994         ipoib->ibdev = ibdev;
995
996         /* Calculate as much of the broadcast GID and the MAC address
997          * as we can.  We won't know either of these in full until we
998          * have link-up.
999          */
1000         ipoib_set_ib_params ( ipoib );
1001
1002         /* Register network device */
1003         if ( ( rc = register_netdev ( netdev ) ) != 0 )
1004                 goto err_register_netdev;
1005
1006         return 0;
1007
1008  err_register_netdev:
1009         netdev_nullify ( netdev );
1010         netdev_put ( netdev );
1011         return rc;
1012 }
1013
1014 /**
1015  * Remove IPoIB device
1016  *
1017  * @v ibdev             Infiniband device
1018  */
1019 void ipoib_remove ( struct ib_device *ibdev ) {
1020         struct net_device *netdev = ib_get_ownerdata ( ibdev );
1021
1022         unregister_netdev ( netdev );
1023         netdev_nullify ( netdev );
1024         netdev_put ( netdev );
1025 }
1026
1027 /**
1028  * Allocate IPoIB device
1029  *
1030  * @v priv_size         Size of driver private data
1031  * @ret netdev          Network device, or NULL
1032  */
1033 struct net_device * alloc_ipoibdev ( size_t priv_size ) {
1034         struct net_device *netdev;
1035
1036         netdev = alloc_netdev ( priv_size );
1037         if ( netdev ) {
1038                 netdev->ll_protocol = &ipoib_protocol;
1039                 netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast;
1040                 netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
1041         }
1042         return netdev;
1043 }