f3b821c4719e5548b2befe492ba15bab37c53cad
[people/pcmattman/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 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <byteswap.h>
23 #include <errno.h>
24 #include <gpxe/if_arp.h>
25 #include <gpxe/iobuf.h>
26 #include <gpxe/netdevice.h>
27 #include <gpxe/infiniband.h>
28 #include <gpxe/ipoib.h>
29
30 /** @file
31  *
32  * IP over Infiniband
33  */
34
35
36
37
38
39 extern unsigned long hack_ipoib_qkey;
40 extern struct ib_address_vector hack_ipoib_bcast_av;
41
42
43
44 /** IPoIB MTU */
45 #define IPOIB_MTU 2048
46
47 /** Number of IPoIB data send work queue entries */
48 #define IPOIB_DATA_NUM_SEND_WQES 4
49
50 /** Number of IPoIB data receive work queue entries */
51 #define IPOIB_DATA_NUM_RECV_WQES 4
52
53 /** Number of IPoIB data completion entries */
54 #define IPOIB_DATA_NUM_CQES 8
55
56 /** Number of IPoIB metadata send work queue entries */
57 #define IPOIB_META_NUM_SEND_WQES 4
58
59 /** Number of IPoIB metadata receive work queue entries */
60 #define IPOIB_META_NUM_RECV_WQES 4
61
62 /** Number of IPoIB metadata completion entries */
63 #define IPOIB_META_NUM_CQES 8
64
65 /** An IPoIB queue set */
66 struct ipoib_queue_set {
67         /** Completion queue */
68         struct ib_completion_queue *cq;
69         /** Queue pair */
70         struct ib_queue_pair *qp;
71         /** Receive work queue fill level */
72         unsigned int recv_fill;
73         /** Receive work queue maximum fill level */
74         unsigned int recv_max_fill;
75 };
76
77 /** An IPoIB device */
78 struct ipoib_device {
79         /** Network device */
80         struct net_device *netdev;
81         /** Underlying Infiniband device */
82         struct ib_device *ibdev;
83         /** Data queue set */
84         struct ipoib_queue_set data;
85         /** Data queue set */
86         struct ipoib_queue_set meta;
87 };
88
89 /**
90  * IPoIB path cache entry
91  *
92  * This serves a similar role to the ARP cache for Ethernet.  (ARP
93  * *is* used on IPoIB; we have two caches to maintain.)
94  */
95 struct ipoib_cached_path {
96         /** Destination GID */
97         struct ib_gid gid;
98         /** Destination LID */
99         unsigned int dlid;
100         /** Service level */
101         unsigned int sl;
102         /** Rate */
103         unsigned int rate;
104 };
105
106 /** Number of IPoIB path cache entries */
107 #define IPOIB_NUM_CACHED_PATHS 2
108
109 /** IPoIB path cache */
110 static struct ipoib_cached_path ipoib_path_cache[IPOIB_NUM_CACHED_PATHS];
111
112 /** Oldest IPoIB path cache entry index */
113 static unsigned int ipoib_path_cache_idx = 0;
114
115 /****************************************************************************
116  *
117  * IPoIB link layer
118  *
119  ****************************************************************************
120  */
121
122 /** Broadcast QPN used in IPoIB MAC addresses
123  *
124  * This is a guaranteed invalid real QPN
125  */
126 #define IPOIB_BROADCAST_QPN 0xffffffffUL
127
128 /** Broadcast IPoIB address */
129 static struct ipoib_mac ipoib_broadcast = {
130         .qpn = ntohl ( IPOIB_BROADCAST_QPN ),
131 };
132
133 /**
134  * Transmit IPoIB packet
135  *
136  * @v iobuf             I/O buffer
137  * @v netdev            Network device
138  * @v net_protocol      Network-layer protocol
139  * @v ll_dest           Link-layer destination address
140  *
141  * Prepends the IPoIB link-layer header and transmits the packet.
142  */
143 static int ipoib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
144                       struct net_protocol *net_protocol,
145                       const void *ll_dest ) {
146         struct ipoib_hdr *ipoib_hdr =
147                 iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
148
149         /* Build IPoIB header */
150         memcpy ( &ipoib_hdr->pseudo.peer, ll_dest,
151                  sizeof ( ipoib_hdr->pseudo.peer ) );
152         ipoib_hdr->real.proto = net_protocol->net_proto;
153         ipoib_hdr->real.reserved = 0;
154
155         /* Hand off to network device */
156         return netdev_tx ( netdev, iobuf );
157 }
158
159 /**
160  * Process received IPoIB packet
161  *
162  * @v iobuf     I/O buffer
163  * @v netdev    Network device
164  *
165  * Strips off the IPoIB link-layer header and passes up to the
166  * network-layer protocol.
167  */
168 static int ipoib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
169         struct ipoib_hdr *ipoib_hdr = iobuf->data;
170
171         /* Sanity check */
172         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
173                 DBG ( "IPoIB packet too short (%d bytes)\n",
174                       iob_len ( iobuf ) );
175                 free_iob ( iobuf );
176                 return -EINVAL;
177         }
178
179         /* Strip off IPoIB header */
180         iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
181
182         /* Hand off to network-layer protocol */
183         return net_rx ( iobuf, netdev, ipoib_hdr->real.proto,
184                         &ipoib_hdr->pseudo.peer );
185 }
186
187 /**
188  * Transcribe IPoIB address
189  *
190  * @v ll_addr   Link-layer address
191  * @ret string  Link-layer address in human-readable format
192  */
193 const char * ipoib_ntoa ( const void *ll_addr ) {
194         static char buf[45];
195         const struct ipoib_mac *mac = ll_addr;
196
197         snprintf ( buf, sizeof ( buf ), "%08lx:%08lx:%08lx:%08lx:%08lx",
198                    htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
199                    htonl ( mac->gid.u.dwords[1] ),
200                    htonl ( mac->gid.u.dwords[2] ),
201                    htonl ( mac->gid.u.dwords[3] ) );
202         return buf;
203 }
204
205 /** IPoIB protocol */
206 struct ll_protocol ipoib_protocol __ll_protocol = {
207         .name           = "IPoIB",
208         .ll_proto       = htons ( ARPHRD_INFINIBAND ),
209         .ll_addr_len    = IPOIB_ALEN,
210         .ll_header_len  = IPOIB_HLEN,
211         .ll_broadcast   = ( uint8_t * ) &ipoib_broadcast,
212         .tx             = ipoib_tx,
213         .rx             = ipoib_rx,
214         .ntoa           = ipoib_ntoa,
215 };
216
217 /****************************************************************************
218  *
219  * IPoIB network device
220  *
221  ****************************************************************************
222  */
223
224 /**
225  * Destroy queue set
226  *
227  * @v ipoib             IPoIB device
228  * @v qset              Queue set
229  */
230 static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
231                                  struct ipoib_queue_set *qset ) {
232         struct ib_device *ibdev = ipoib->ibdev;
233
234         if ( qset->qp )
235                 ib_destroy_qp ( ibdev, qset->qp );
236         if ( qset->cq )
237                 ib_destroy_cq ( ibdev, qset->cq );
238         memset ( qset, 0, sizeof ( *qset ) );
239 }
240
241 /**
242  * Create queue set
243  *
244  * @v ipoib             IPoIB device
245  * @v qset              Queue set
246  * @ret rc              Return status code
247  */
248 static int ipoib_create_qset ( struct ipoib_device *ipoib,
249                                struct ipoib_queue_set *qset,
250                                unsigned int num_cqes,
251                                unsigned int num_send_wqes,
252                                unsigned int num_recv_wqes,
253                                unsigned long qkey ) {
254         struct ib_device *ibdev = ipoib->ibdev;
255         int rc;
256
257         /* Store queue parameters */
258         qset->recv_max_fill = num_recv_wqes;
259
260         /* Allocate completion queue */
261         qset->cq = ib_create_cq ( ibdev, num_cqes );
262         if ( ! qset->cq ) {
263                 DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
264                        ipoib );
265                 rc = -ENOMEM;
266                 goto err;
267         }
268
269         /* Allocate queue pair */
270         qset->qp = ib_create_qp ( ibdev, num_send_wqes, qset->cq,
271                                   num_recv_wqes, qset->cq, qkey );
272         if ( ! qset->qp ) {
273                 DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
274                        ipoib );
275                 rc = -ENOMEM;
276                 goto err;
277         }
278         qset->qp->owner_priv = ipoib->netdev;
279
280         return 0;
281
282  err:
283         ipoib_destroy_qset ( ipoib, qset );
284         return rc;
285 }
286
287 /**
288  * Find path cache entry by GID
289  *
290  * @v gid               GID
291  * @ret entry           Path cache entry, or NULL
292  */
293 static struct ipoib_cached_path *
294 ipoib_find_cached_path ( struct ib_gid *gid ) {
295         struct ipoib_cached_path *path;
296         unsigned int i;
297
298         for ( i = 0 ; i < IPOIB_NUM_CACHED_PATHS ; i++ ) {
299                 path = &ipoib_path_cache[i];
300                 if ( memcmp ( &path->gid, gid, sizeof ( *gid ) ) == 0 )
301                         return path;
302         }
303         DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx cache miss\n",
304               htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
305               htonl ( gid->u.dwords[2] ), htonl ( gid->u.dwords[3] ) );
306         return NULL;
307 }
308
309 /**
310  * Transmit path record request
311  *
312  * @v ipoib             IPoIB device
313  * @v gid               Destination GID
314  * @ret rc              Return status code
315  */
316 static int ipoib_get_path_record ( struct ipoib_device *ipoib,
317                                    struct ib_gid *gid ) {
318         struct ib_device *ibdev = ipoib->ibdev;
319         struct io_buffer *iobuf;
320         struct ib_mad_path_record *path_record;
321         struct ib_address_vector av;
322         static uint32_t tid = 0;
323         int rc;
324
325         int get_path_record(struct ib_gid *dgid, uint16_t *dlid_p,
326                             uint8_t *sl_p, uint8_t *rate_p);
327         uint16_t tmp_dlid;
328         uint8_t tmp_sl;
329         uint8_t tmp_rate;
330         get_path_record ( gid, &tmp_dlid, &tmp_sl, &tmp_rate );
331         DBG ( "get_path_record() gives dlid = %04x, sl = %02x, rate = %02x\n",
332               tmp_dlid, tmp_sl, tmp_rate );
333
334
335         /* Allocate I/O buffer */
336         iobuf = alloc_iob ( sizeof ( *path_record ) );
337         if ( ! iobuf )
338                 return -ENOMEM;
339         iob_put ( iobuf, sizeof ( *path_record ) );
340         path_record = iobuf->data;
341         memset ( path_record, 0, sizeof ( *path_record ) );
342
343         /* Construct path record request */
344         path_record->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
345         path_record->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
346         path_record->mad_hdr.class_version = 2;
347         path_record->mad_hdr.method = IB_MGMT_METHOD_GET;
348         path_record->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
349         path_record->mad_hdr.tid = tid++;
350         path_record->sa_hdr.comp_mask[1] =
351                 htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
352         memcpy ( &path_record->dgid, gid, sizeof ( path_record->dgid ) );
353         memcpy ( &path_record->sgid, &ibdev->port_gid,
354                  sizeof ( path_record->sgid ) );
355
356         /* Construct address vector */
357         memset ( &av, 0, sizeof ( av ) );
358         av.dlid = ibdev->sm_lid;
359         av.dest_qp = IB_SA_QPN;
360         av.qkey = IB_GLOBAL_QKEY;
361
362         /* Post send request */
363         if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
364                                    iobuf ) ) != 0 ) {
365                 DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n",
366                        ipoib, strerror ( rc ) );
367                 free_iob ( iobuf );
368                 return rc;
369         }
370
371         return 0;
372 }
373
374 /**
375  * Transmit packet via IPoIB network device
376  *
377  * @v netdev            Network device
378  * @v iobuf             I/O buffer
379  * @ret rc              Return status code
380  */
381 static int ipoib_transmit ( struct net_device *netdev,
382                             struct io_buffer *iobuf ) {
383         struct ipoib_device *ipoib = netdev->priv;
384         struct ib_device *ibdev = ipoib->ibdev;
385         struct ipoib_pseudo_hdr *ipoib_pshdr = iobuf->data;
386         struct ib_address_vector av;
387         struct ipoib_cached_path *path;
388         int rc;
389
390         if ( iob_len ( iobuf ) < sizeof ( *ipoib_pshdr ) ) {
391                 DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
392                 return -EINVAL;
393         }
394
395         /* Construct address vector */
396         memset ( &av, 0, sizeof ( av ) );
397         if ( ipoib_pshdr->peer.qpn == htonl ( IPOIB_BROADCAST_QPN ) ) {
398                 /* Broadcast address */
399                 memcpy ( &av, &hack_ipoib_bcast_av, sizeof ( av ) );
400         } else {
401                 /* Unicast - look in path cache */
402                 path = ipoib_find_cached_path ( &ipoib_pshdr->peer.gid );
403                 if ( ! path ) {
404                         /* No path entry - get path record */
405                         rc = ipoib_get_path_record ( ipoib,
406                                                      &ipoib_pshdr->peer.gid );
407                         free_iob ( iobuf );
408                         return rc;
409                 }
410                 av.dest_qp = ntohl ( ipoib_pshdr->peer.qpn );
411                 av.qkey = IB_GLOBAL_QKEY;
412                 av.dlid = path->dlid;
413                 av.rate = path->rate;
414                 av.sl = path->sl;
415                 av.gid_present = 1;
416                 memcpy ( &av.gid, &ipoib_pshdr->peer.gid, sizeof ( av.gid ) );
417         }
418
419         iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
420         return ib_post_send ( ibdev, ipoib->data.qp, &av, iobuf );
421 }
422
423 /**
424  * Handle IPoIB data send completion
425  *
426  * @v ibdev             Infiniband device
427  * @v qp                Queue pair
428  * @v completion        Completion
429  * @v iobuf             I/O buffer
430  */
431 static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
432                                        struct ib_queue_pair *qp,
433                                        struct ib_completion *completion,
434                                        struct io_buffer *iobuf ) {
435         struct net_device *netdev = qp->owner_priv;
436
437         netdev_tx_complete_err ( netdev, iobuf,
438                                  ( completion->syndrome ? -EIO : 0 ) );
439 }
440
441 /**
442  * Handle IPoIB data receive completion
443  *
444  * @v ibdev             Infiniband device
445  * @v qp                Queue pair
446  * @v completion        Completion
447  * @v iobuf             I/O buffer
448  */
449 static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
450                                        struct ib_queue_pair *qp,
451                                        struct ib_completion *completion,
452                                        struct io_buffer *iobuf ) {
453         struct net_device *netdev = qp->owner_priv;
454         struct ipoib_device *ipoib = netdev->priv;
455         struct ipoib_pseudo_hdr *ipoib_pshdr;
456
457         if ( completion->syndrome ) {
458                 netdev_rx_err ( netdev, iobuf, -EIO );
459         } else {
460                 iob_put ( iobuf, completion->len );
461                 iob_pull ( iobuf, ( sizeof ( struct ib_global_route_header ) -
462                                     sizeof ( *ipoib_pshdr ) ) );
463                 /* FIXME: fill in a MAC address for the sake of AoE! */
464                 netdev_rx ( netdev, iobuf );
465         }
466
467         ipoib->data.recv_fill--;
468 }
469
470 /**
471  * Handle IPoIB metadata send completion
472  *
473  * @v ibdev             Infiniband device
474  * @v qp                Queue pair
475  * @v completion        Completion
476  * @v iobuf             I/O buffer
477  */
478 static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
479                                        struct ib_queue_pair *qp,
480                                        struct ib_completion *completion,
481                                        struct io_buffer *iobuf ) {
482         struct net_device *netdev = qp->owner_priv;
483         struct ipoib_device *ipoib = netdev->priv;
484
485         if ( completion->syndrome ) {
486                 DBGC ( ipoib, "IPoIB %p metadata TX completion error %x\n",
487                        ipoib, completion->syndrome );
488         }
489         free_iob ( iobuf );
490 }
491
492 /**
493  * Handle IPoIB metadata receive completion
494  *
495  * @v ibdev             Infiniband device
496  * @v qp                Queue pair
497  * @v completion        Completion
498  * @v iobuf             I/O buffer
499  */
500 static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
501                                        struct ib_queue_pair *qp,
502                                        struct ib_completion *completion,
503                                        struct io_buffer *iobuf ) {
504         struct net_device *netdev = qp->owner_priv;
505         struct ipoib_device *ipoib = netdev->priv;
506         struct ib_mad_path_record *path_record;
507         struct ipoib_cached_path *path;
508
509         if ( completion->syndrome ) {
510                 DBGC ( ipoib, "IPoIB %p metadata RX completion error %x\n",
511                        ipoib, completion->syndrome );
512         } else {
513                 /* Update path cache */
514                 iob_put ( iobuf, completion->len );
515                 iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
516
517                 DBG ( "Metadata RX:\n" );
518                 DBG_HD ( iobuf->data, iob_len ( iobuf ) );
519
520                 path_record = iobuf->data;
521                 path = &ipoib_path_cache[ipoib_path_cache_idx];
522                 memcpy ( &path->gid, &path_record->dgid,
523                          sizeof ( path->gid ) );
524                 path->dlid = ntohs ( path_record->dlid );
525                 path->sl = ( path_record->reserved__sl & 0x0f );
526                 path->rate = ( path_record->rate_selector__rate & 0x3f );
527                 DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx dlid %x sl %x rate %x\n",
528                       htonl ( path->gid.u.dwords[0] ),
529                       htonl ( path->gid.u.dwords[1] ),
530                       htonl ( path->gid.u.dwords[2] ),
531                       htonl ( path->gid.u.dwords[3] ),
532                       path->dlid, path->sl, path->rate );
533
534                 /* Update path cache index */
535                 ipoib_path_cache_idx++;
536                 if ( ipoib_path_cache_idx == IPOIB_NUM_CACHED_PATHS )
537                         ipoib_path_cache_idx = 0;
538         }
539
540         ipoib->meta.recv_fill--;
541         free_iob ( iobuf );
542 }
543
544 /**
545  * Refill IPoIB receive ring
546  *
547  * @v ipoib             IPoIB device
548  */
549 static void ipoib_refill_recv ( struct ipoib_device *ipoib,
550                                 struct ipoib_queue_set *qset ) {
551         struct ib_device *ibdev = ipoib->ibdev;
552         struct io_buffer *iobuf;
553         int rc;
554
555         while ( qset->recv_fill < qset->recv_max_fill ) {
556                 iobuf = alloc_iob ( IPOIB_MTU );
557                 if ( ! iobuf )
558                         break;
559                 if ( ( rc = ib_post_recv ( ibdev, qset->qp, iobuf ) ) != 0 ) {
560                         free_iob ( iobuf );
561                         break;
562                 }
563                 qset->recv_fill++;
564         }
565 }
566
567 /**
568  * Poll IPoIB network device
569  *
570  * @v netdev            Network device
571  */
572 static void ipoib_poll ( struct net_device *netdev ) {
573         struct ipoib_device *ipoib = netdev->priv;
574         struct ib_device *ibdev = ipoib->ibdev;
575
576         ib_poll_cq ( ibdev, ipoib->data.cq, ipoib_data_complete_send,
577                      ipoib_data_complete_recv );
578         ib_poll_cq ( ibdev, ipoib->meta.cq, ipoib_meta_complete_send,
579                      ipoib_meta_complete_recv );
580         ipoib_refill_recv ( ipoib, &ipoib->meta );
581         ipoib_refill_recv ( ipoib, &ipoib->data );
582 }
583
584 /**
585  * Enable/disable interrupts on IPoIB network device
586  *
587  * @v netdev            Network device
588  * @v enable            Interrupts should be enabled
589  */
590 static void ipoib_irq ( struct net_device *netdev __unused,
591                         int enable __unused ) {
592         /* No implementation */
593 }
594
595 /**
596  * Open IPoIB network device
597  *
598  * @v netdev            Network device
599  * @ret rc              Return status code
600  */
601 static int ipoib_open ( struct net_device *netdev ) {
602         struct ipoib_device *ipoib = netdev->priv;
603         struct ib_device *ibdev = ipoib->ibdev;
604         int rc;
605
606         /* Attach to broadcast multicast GID */
607         if ( ( rc = ib_mcast_attach ( ibdev, ipoib->data.qp,
608                                       &ibdev->broadcast_gid ) ) != 0 ) {
609                 DBG ( "Could not attach to broadcast GID: %s\n",
610                       strerror ( rc ) );
611                 return rc;
612         }
613
614         /* Fill receive rings */
615         ipoib_refill_recv ( ipoib, &ipoib->meta );
616         ipoib_refill_recv ( ipoib, &ipoib->data );
617
618         return 0;
619 }
620
621 /**
622  * Close IPoIB network device
623  *
624  * @v netdev            Network device
625  */
626 static void ipoib_close ( struct net_device *netdev ) {
627         struct ipoib_device *ipoib = netdev->priv;
628         struct ib_device *ibdev = ipoib->ibdev;
629
630         /* Detach from broadcast multicast GID */
631         ib_mcast_detach ( ibdev, ipoib->data.qp, &ipoib_broadcast.gid );
632
633         /* FIXME: should probably flush the receive ring */
634 }
635
636 /** IPoIB network device operations */
637 static struct net_device_operations ipoib_operations = {
638         .open           = ipoib_open,
639         .close          = ipoib_close,
640         .transmit       = ipoib_transmit,
641         .poll           = ipoib_poll,
642         .irq            = ipoib_irq,
643 };
644
645 /**
646  * Probe IPoIB device
647  *
648  * @v ibdev             Infiniband device
649  * @ret rc              Return status code
650  */
651 int ipoib_probe ( struct ib_device *ibdev ) {
652         struct net_device *netdev;
653         struct ipoib_device *ipoib;
654         struct ipoib_mac *mac;
655         int rc;
656
657         /* Allocate network device */
658         netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
659         if ( ! netdev )
660                 return -ENOMEM;
661         netdev_init ( netdev, &ipoib_operations );
662         ipoib = netdev->priv;
663         ib_set_ownerdata ( ibdev, netdev );
664         netdev->dev = ibdev->dev;
665         memset ( ipoib, 0, sizeof ( *ipoib ) );
666         ipoib->netdev = netdev;
667         ipoib->ibdev = ibdev;
668
669         /* Allocate metadata queue set */
670         if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
671                                         IPOIB_META_NUM_CQES,
672                                         IPOIB_META_NUM_SEND_WQES,
673                                         IPOIB_META_NUM_RECV_WQES,
674                                         IB_GLOBAL_QKEY ) ) != 0 ) {
675                 DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
676                        ipoib, strerror ( rc ) );
677                 goto err_create_meta_qset;
678         }
679
680         /* Allocate data queue set */
681         if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
682                                         IPOIB_DATA_NUM_CQES,
683                                         IPOIB_DATA_NUM_SEND_WQES,
684                                         IPOIB_DATA_NUM_RECV_WQES,
685                                         hack_ipoib_qkey ) ) != 0 ) {
686                 DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
687                        ipoib, strerror ( rc ) );
688                 goto err_create_data_qset;
689         }
690
691         /* Construct MAC address */
692         mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
693         mac->qpn = htonl ( ipoib->data.qp->qpn );
694         memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
695
696         /* Register network device */
697         if ( ( rc = register_netdev ( netdev ) ) != 0 )
698                 goto err_register_netdev;
699
700         return 0;
701
702  err_register_netdev:
703         ipoib_destroy_qset ( ipoib, &ipoib->data );
704  err_create_data_qset:
705         ipoib_destroy_qset ( ipoib, &ipoib->meta );
706  err_create_meta_qset:
707         netdev_nullify ( netdev );
708         netdev_put ( netdev );
709         return rc;
710 }
711
712 /**
713  * Remove IPoIB device
714  *
715  * @v ibdev             Infiniband device
716  */
717 void ipoib_remove ( struct ib_device *ibdev ) {
718         struct net_device *netdev = ib_get_ownerdata ( ibdev );
719
720         unregister_netdev ( netdev );
721         netdev_nullify ( netdev );
722         netdev_put ( netdev );
723 }