Broadcast GID is now calculated by IPoIB layer.
[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         /** Broadcast GID */
88         struct ib_gid broadcast_gid;
89 };
90
91 /**
92  * IPoIB path cache entry
93  *
94  * This serves a similar role to the ARP cache for Ethernet.  (ARP
95  * *is* used on IPoIB; we have two caches to maintain.)
96  */
97 struct ipoib_cached_path {
98         /** Destination GID */
99         struct ib_gid gid;
100         /** Destination LID */
101         unsigned int dlid;
102         /** Service level */
103         unsigned int sl;
104         /** Rate */
105         unsigned int rate;
106 };
107
108 /** Number of IPoIB path cache entries */
109 #define IPOIB_NUM_CACHED_PATHS 2
110
111 /** IPoIB path cache */
112 static struct ipoib_cached_path ipoib_path_cache[IPOIB_NUM_CACHED_PATHS];
113
114 /** Oldest IPoIB path cache entry index */
115 static unsigned int ipoib_path_cache_idx = 0;
116
117 /** IPoIB metadata TID */
118 static uint32_t ipoib_meta_tid = 0;
119
120 /** IPv4 broadcast GID */
121 static const struct ib_gid ipv4_broadcast_gid = {
122         { { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
123             0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff } }
124 };
125
126 /****************************************************************************
127  *
128  * IPoIB link layer
129  *
130  ****************************************************************************
131  */
132
133 /** Broadcast QPN used in IPoIB MAC addresses
134  *
135  * This is a guaranteed invalid real QPN
136  */
137 #define IPOIB_BROADCAST_QPN 0xffffffffUL
138
139 /** Broadcast IPoIB address */
140 static struct ipoib_mac ipoib_broadcast = {
141         .qpn = ntohl ( IPOIB_BROADCAST_QPN ),
142 };
143
144 /**
145  * Transmit IPoIB packet
146  *
147  * @v iobuf             I/O buffer
148  * @v netdev            Network device
149  * @v net_protocol      Network-layer protocol
150  * @v ll_dest           Link-layer destination address
151  *
152  * Prepends the IPoIB link-layer header and transmits the packet.
153  */
154 static int ipoib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
155                       struct net_protocol *net_protocol,
156                       const void *ll_dest ) {
157         struct ipoib_hdr *ipoib_hdr =
158                 iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
159
160         /* Build IPoIB header */
161         memcpy ( &ipoib_hdr->pseudo.peer, ll_dest,
162                  sizeof ( ipoib_hdr->pseudo.peer ) );
163         ipoib_hdr->real.proto = net_protocol->net_proto;
164         ipoib_hdr->real.reserved = 0;
165
166         /* Hand off to network device */
167         return netdev_tx ( netdev, iobuf );
168 }
169
170 /**
171  * Process received IPoIB packet
172  *
173  * @v iobuf     I/O buffer
174  * @v netdev    Network device
175  *
176  * Strips off the IPoIB link-layer header and passes up to the
177  * network-layer protocol.
178  */
179 static int ipoib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
180         struct ipoib_hdr *ipoib_hdr = iobuf->data;
181
182         /* Sanity check */
183         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
184                 DBG ( "IPoIB packet too short (%d bytes)\n",
185                       iob_len ( iobuf ) );
186                 free_iob ( iobuf );
187                 return -EINVAL;
188         }
189
190         /* Strip off IPoIB header */
191         iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
192
193         /* Hand off to network-layer protocol */
194         return net_rx ( iobuf, netdev, ipoib_hdr->real.proto,
195                         &ipoib_hdr->pseudo.peer );
196 }
197
198 /**
199  * Transcribe IPoIB address
200  *
201  * @v ll_addr   Link-layer address
202  * @ret string  Link-layer address in human-readable format
203  */
204 const char * ipoib_ntoa ( const void *ll_addr ) {
205         static char buf[45];
206         const struct ipoib_mac *mac = ll_addr;
207
208         snprintf ( buf, sizeof ( buf ), "%08lx:%08lx:%08lx:%08lx:%08lx",
209                    htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
210                    htonl ( mac->gid.u.dwords[1] ),
211                    htonl ( mac->gid.u.dwords[2] ),
212                    htonl ( mac->gid.u.dwords[3] ) );
213         return buf;
214 }
215
216 /** IPoIB protocol */
217 struct ll_protocol ipoib_protocol __ll_protocol = {
218         .name           = "IPoIB",
219         .ll_proto       = htons ( ARPHRD_INFINIBAND ),
220         .ll_addr_len    = IPOIB_ALEN,
221         .ll_header_len  = IPOIB_HLEN,
222         .ll_broadcast   = ( uint8_t * ) &ipoib_broadcast,
223         .tx             = ipoib_tx,
224         .rx             = ipoib_rx,
225         .ntoa           = ipoib_ntoa,
226 };
227
228 /****************************************************************************
229  *
230  * IPoIB network device
231  *
232  ****************************************************************************
233  */
234
235 /**
236  * Destroy queue set
237  *
238  * @v ipoib             IPoIB device
239  * @v qset              Queue set
240  */
241 static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
242                                  struct ipoib_queue_set *qset ) {
243         struct ib_device *ibdev = ipoib->ibdev;
244
245         if ( qset->qp )
246                 ib_destroy_qp ( ibdev, qset->qp );
247         if ( qset->cq )
248                 ib_destroy_cq ( ibdev, qset->cq );
249         memset ( qset, 0, sizeof ( *qset ) );
250 }
251
252 /**
253  * Create queue set
254  *
255  * @v ipoib             IPoIB device
256  * @v qset              Queue set
257  * @ret rc              Return status code
258  */
259 static int ipoib_create_qset ( struct ipoib_device *ipoib,
260                                struct ipoib_queue_set *qset,
261                                unsigned int num_cqes,
262                                unsigned int num_send_wqes,
263                                unsigned int num_recv_wqes,
264                                unsigned long qkey ) {
265         struct ib_device *ibdev = ipoib->ibdev;
266         int rc;
267
268         /* Store queue parameters */
269         qset->recv_max_fill = num_recv_wqes;
270
271         /* Allocate completion queue */
272         qset->cq = ib_create_cq ( ibdev, num_cqes );
273         if ( ! qset->cq ) {
274                 DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
275                        ipoib );
276                 rc = -ENOMEM;
277                 goto err;
278         }
279
280         /* Allocate queue pair */
281         qset->qp = ib_create_qp ( ibdev, num_send_wqes, qset->cq,
282                                   num_recv_wqes, qset->cq, qkey );
283         if ( ! qset->qp ) {
284                 DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
285                        ipoib );
286                 rc = -ENOMEM;
287                 goto err;
288         }
289         qset->qp->owner_priv = ipoib->netdev;
290
291         return 0;
292
293  err:
294         ipoib_destroy_qset ( ipoib, qset );
295         return rc;
296 }
297
298 /**
299  * Find path cache entry by GID
300  *
301  * @v gid               GID
302  * @ret entry           Path cache entry, or NULL
303  */
304 static struct ipoib_cached_path *
305 ipoib_find_cached_path ( struct ib_gid *gid ) {
306         struct ipoib_cached_path *path;
307         unsigned int i;
308
309         for ( i = 0 ; i < IPOIB_NUM_CACHED_PATHS ; i++ ) {
310                 path = &ipoib_path_cache[i];
311                 if ( memcmp ( &path->gid, gid, sizeof ( *gid ) ) == 0 )
312                         return path;
313         }
314         DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx cache miss\n",
315               htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
316               htonl ( gid->u.dwords[2] ), htonl ( gid->u.dwords[3] ) );
317         return NULL;
318 }
319
320 /**
321  * Transmit path record request
322  *
323  * @v ipoib             IPoIB device
324  * @v gid               Destination GID
325  * @ret rc              Return status code
326  */
327 static int ipoib_get_path_record ( struct ipoib_device *ipoib,
328                                    struct ib_gid *gid ) {
329         struct ib_device *ibdev = ipoib->ibdev;
330         struct io_buffer *iobuf;
331         struct ib_mad_path_record *path_record;
332         struct ib_address_vector av;
333         int rc;
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 = ipoib_meta_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 multicast group membership request
376  *
377  * @v ipoib             IPoIB device
378  * @v gid               Multicast GID
379  * @v join              Join (rather than leave) group
380  * @ret rc              Return status code
381  */
382 static int ipoib_mc_member_record ( struct ipoib_device *ipoib,
383                                     struct ib_gid *gid, int join ) {
384         struct ib_device *ibdev = ipoib->ibdev;
385         struct io_buffer *iobuf;
386         struct ib_mad_mc_member_record *mc_member_record;
387         struct ib_address_vector av;
388         int rc;
389
390         /* Allocate I/O buffer */
391         iobuf = alloc_iob ( sizeof ( *mc_member_record ) );
392         if ( ! iobuf )
393                 return -ENOMEM;
394         iob_put ( iobuf, sizeof ( *mc_member_record ) );
395         mc_member_record = iobuf->data;
396         memset ( mc_member_record, 0, sizeof ( *mc_member_record ) );
397
398         /* Construct path record request */
399         mc_member_record->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
400         mc_member_record->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
401         mc_member_record->mad_hdr.class_version = 2;
402         mc_member_record->mad_hdr.method = 
403                 ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
404         mc_member_record->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
405         mc_member_record->mad_hdr.tid = ipoib_meta_tid++;
406         mc_member_record->sa_hdr.comp_mask[1] =
407                 htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
408                         IB_SA_MCMEMBER_REC_JOIN_STATE );
409         mc_member_record->scope__join_state = 1;
410         memcpy ( &mc_member_record->mgid, gid,
411                  sizeof ( mc_member_record->mgid ) );
412         memcpy ( &mc_member_record->port_gid, &ibdev->port_gid,
413                  sizeof ( mc_member_record->port_gid ) );
414
415         /* Construct address vector */
416         memset ( &av, 0, sizeof ( av ) );
417         av.dlid = ibdev->sm_lid;
418         av.dest_qp = IB_SA_QPN;
419         av.qkey = IB_GLOBAL_QKEY;
420
421         /* Post send request */
422         if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
423                                    iobuf ) ) != 0 ) {
424                 DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n",
425                        ipoib, strerror ( rc ) );
426                 free_iob ( iobuf );
427                 return rc;
428         }
429
430         return 0;
431 }
432
433 /**
434  * Transmit packet via IPoIB network device
435  *
436  * @v netdev            Network device
437  * @v iobuf             I/O buffer
438  * @ret rc              Return status code
439  */
440 static int ipoib_transmit ( struct net_device *netdev,
441                             struct io_buffer *iobuf ) {
442         struct ipoib_device *ipoib = netdev->priv;
443         struct ib_device *ibdev = ipoib->ibdev;
444         struct ipoib_pseudo_hdr *ipoib_pshdr = iobuf->data;
445         struct ib_address_vector av;
446         struct ipoib_cached_path *path;
447         int rc;
448
449         if ( iob_len ( iobuf ) < sizeof ( *ipoib_pshdr ) ) {
450                 DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
451                 return -EINVAL;
452         }
453
454         /* Construct address vector */
455         memset ( &av, 0, sizeof ( av ) );
456         if ( ipoib_pshdr->peer.qpn == htonl ( IPOIB_BROADCAST_QPN ) ) {
457                 /* Broadcast address */
458                 memcpy ( &av, &hack_ipoib_bcast_av, sizeof ( av ) );
459         } else {
460                 /* Unicast - look in path cache */
461                 path = ipoib_find_cached_path ( &ipoib_pshdr->peer.gid );
462                 if ( ! path ) {
463                         /* No path entry - get path record */
464                         rc = ipoib_get_path_record ( ipoib,
465                                                      &ipoib_pshdr->peer.gid );
466                         free_iob ( iobuf );
467                         return rc;
468                 }
469                 av.dest_qp = ntohl ( ipoib_pshdr->peer.qpn );
470                 av.qkey = IB_GLOBAL_QKEY;
471                 av.dlid = path->dlid;
472                 av.rate = path->rate;
473                 av.sl = path->sl;
474                 av.gid_present = 1;
475                 memcpy ( &av.gid, &ipoib_pshdr->peer.gid, sizeof ( av.gid ) );
476         }
477
478         iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
479         return ib_post_send ( ibdev, ipoib->data.qp, &av, iobuf );
480 }
481
482 /**
483  * Handle IPoIB data send completion
484  *
485  * @v ibdev             Infiniband device
486  * @v qp                Queue pair
487  * @v completion        Completion
488  * @v iobuf             I/O buffer
489  */
490 static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
491                                        struct ib_queue_pair *qp,
492                                        struct ib_completion *completion,
493                                        struct io_buffer *iobuf ) {
494         struct net_device *netdev = qp->owner_priv;
495
496         netdev_tx_complete_err ( netdev, iobuf,
497                                  ( completion->syndrome ? -EIO : 0 ) );
498 }
499
500 /**
501  * Handle IPoIB data receive completion
502  *
503  * @v ibdev             Infiniband device
504  * @v qp                Queue pair
505  * @v completion        Completion
506  * @v iobuf             I/O buffer
507  */
508 static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
509                                        struct ib_queue_pair *qp,
510                                        struct ib_completion *completion,
511                                        struct io_buffer *iobuf ) {
512         struct net_device *netdev = qp->owner_priv;
513         struct ipoib_device *ipoib = netdev->priv;
514         struct ipoib_pseudo_hdr *ipoib_pshdr;
515
516         if ( completion->syndrome ) {
517                 netdev_rx_err ( netdev, iobuf, -EIO );
518         } else {
519                 iob_put ( iobuf, completion->len );
520                 iob_pull ( iobuf, ( sizeof ( struct ib_global_route_header ) -
521                                     sizeof ( *ipoib_pshdr ) ) );
522                 /* FIXME: fill in a MAC address for the sake of AoE! */
523                 netdev_rx ( netdev, iobuf );
524         }
525
526         ipoib->data.recv_fill--;
527 }
528
529 /**
530  * Handle IPoIB metadata send completion
531  *
532  * @v ibdev             Infiniband device
533  * @v qp                Queue pair
534  * @v completion        Completion
535  * @v iobuf             I/O buffer
536  */
537 static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
538                                        struct ib_queue_pair *qp,
539                                        struct ib_completion *completion,
540                                        struct io_buffer *iobuf ) {
541         struct net_device *netdev = qp->owner_priv;
542         struct ipoib_device *ipoib = netdev->priv;
543
544         if ( completion->syndrome ) {
545                 DBGC ( ipoib, "IPoIB %p metadata TX completion error %x\n",
546                        ipoib, completion->syndrome );
547         }
548         free_iob ( iobuf );
549 }
550
551 /**
552  * Handle IPoIB metadata receive completion
553  *
554  * @v ibdev             Infiniband device
555  * @v qp                Queue pair
556  * @v completion        Completion
557  * @v iobuf             I/O buffer
558  */
559 static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
560                                        struct ib_queue_pair *qp,
561                                        struct ib_completion *completion,
562                                        struct io_buffer *iobuf ) {
563         struct net_device *netdev = qp->owner_priv;
564         struct ipoib_device *ipoib = netdev->priv;
565         struct ib_mad_path_record *path_record;
566         struct ipoib_cached_path *path;
567
568         if ( completion->syndrome ) {
569                 DBGC ( ipoib, "IPoIB %p metadata RX completion error %x\n",
570                        ipoib, completion->syndrome );
571         } else {
572                 /* Update path cache */
573                 iob_put ( iobuf, completion->len );
574                 iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
575                 path_record = iobuf->data;
576                 path = &ipoib_path_cache[ipoib_path_cache_idx];
577                 memcpy ( &path->gid, &path_record->dgid,
578                          sizeof ( path->gid ) );
579                 path->dlid = ntohs ( path_record->dlid );
580                 path->sl = ( path_record->reserved__sl & 0x0f );
581                 path->rate = ( path_record->rate_selector__rate & 0x3f );
582                 DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx dlid %x sl %x rate %x\n",
583                       htonl ( path->gid.u.dwords[0] ),
584                       htonl ( path->gid.u.dwords[1] ),
585                       htonl ( path->gid.u.dwords[2] ),
586                       htonl ( path->gid.u.dwords[3] ),
587                       path->dlid, path->sl, path->rate );
588
589                 /* Update path cache index */
590                 ipoib_path_cache_idx++;
591                 if ( ipoib_path_cache_idx == IPOIB_NUM_CACHED_PATHS )
592                         ipoib_path_cache_idx = 0;
593         }
594
595         ipoib->meta.recv_fill--;
596         free_iob ( iobuf );
597 }
598
599 /**
600  * Refill IPoIB receive ring
601  *
602  * @v ipoib             IPoIB device
603  */
604 static void ipoib_refill_recv ( struct ipoib_device *ipoib,
605                                 struct ipoib_queue_set *qset ) {
606         struct ib_device *ibdev = ipoib->ibdev;
607         struct io_buffer *iobuf;
608         int rc;
609
610         while ( qset->recv_fill < qset->recv_max_fill ) {
611                 iobuf = alloc_iob ( IPOIB_MTU );
612                 if ( ! iobuf )
613                         break;
614                 if ( ( rc = ib_post_recv ( ibdev, qset->qp, iobuf ) ) != 0 ) {
615                         free_iob ( iobuf );
616                         break;
617                 }
618                 qset->recv_fill++;
619         }
620 }
621
622 /**
623  * Poll IPoIB network device
624  *
625  * @v netdev            Network device
626  */
627 static void ipoib_poll ( struct net_device *netdev ) {
628         struct ipoib_device *ipoib = netdev->priv;
629         struct ib_device *ibdev = ipoib->ibdev;
630
631         ib_poll_cq ( ibdev, ipoib->data.cq, ipoib_data_complete_send,
632                      ipoib_data_complete_recv );
633         ib_poll_cq ( ibdev, ipoib->meta.cq, ipoib_meta_complete_send,
634                      ipoib_meta_complete_recv );
635         ipoib_refill_recv ( ipoib, &ipoib->meta );
636         ipoib_refill_recv ( ipoib, &ipoib->data );
637 }
638
639 /**
640  * Enable/disable interrupts on IPoIB network device
641  *
642  * @v netdev            Network device
643  * @v enable            Interrupts should be enabled
644  */
645 static void ipoib_irq ( struct net_device *netdev __unused,
646                         int enable __unused ) {
647         /* No implementation */
648 }
649
650 /**
651  * Open IPoIB network device
652  *
653  * @v netdev            Network device
654  * @ret rc              Return status code
655  */
656 static int ipoib_open ( struct net_device *netdev ) {
657         struct ipoib_device *ipoib = netdev->priv;
658         struct ib_device *ibdev = ipoib->ibdev;
659         int rc;
660
661         /* Attach to broadcast multicast GID */
662         if ( ( rc = ib_mcast_attach ( ibdev, ipoib->data.qp,
663                                       &ipoib->broadcast_gid ) ) != 0 ) {
664                 DBG ( "Could not attach to broadcast GID: %s\n",
665                       strerror ( rc ) );
666                 return rc;
667         }
668
669         /* Fill receive rings */
670         ipoib_refill_recv ( ipoib, &ipoib->meta );
671         ipoib_refill_recv ( ipoib, &ipoib->data );
672
673         return 0;
674 }
675
676 /**
677  * Close IPoIB network device
678  *
679  * @v netdev            Network device
680  */
681 static void ipoib_close ( struct net_device *netdev ) {
682         struct ipoib_device *ipoib = netdev->priv;
683         struct ib_device *ibdev = ipoib->ibdev;
684
685         /* Detach from broadcast multicast GID */
686         ib_mcast_detach ( ibdev, ipoib->data.qp, &ipoib_broadcast.gid );
687
688         /* FIXME: should probably flush the receive ring */
689 }
690
691 /** IPoIB network device operations */
692 static struct net_device_operations ipoib_operations = {
693         .open           = ipoib_open,
694         .close          = ipoib_close,
695         .transmit       = ipoib_transmit,
696         .poll           = ipoib_poll,
697         .irq            = ipoib_irq,
698 };
699
700 /**
701  * Join IPoIB broadcast group
702  *
703  * @v ipoib             IPoIB device
704  * @ret rc              Return status code
705  */
706 int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
707         int rc;
708
709         /* Send join request */
710         if ( ( rc = ipoib_mc_member_record ( ipoib, &ipoib->broadcast_gid,
711                                              1 ) ) != 0 ) {
712                 DBGC ( ipoib, "IPoIB %p could not send broadcast join: %s\n",
713                        ipoib, strerror ( rc ) );
714                 return rc;
715         }
716
717
718         return 0;
719 }
720
721 /**
722  * Probe IPoIB device
723  *
724  * @v ibdev             Infiniband device
725  * @ret rc              Return status code
726  */
727 int ipoib_probe ( struct ib_device *ibdev ) {
728         struct net_device *netdev;
729         struct ipoib_device *ipoib;
730         struct ipoib_mac *mac;
731         int rc;
732
733         /* Allocate network device */
734         netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
735         if ( ! netdev )
736                 return -ENOMEM;
737         netdev_init ( netdev, &ipoib_operations );
738         ipoib = netdev->priv;
739         ib_set_ownerdata ( ibdev, netdev );
740         netdev->dev = ibdev->dev;
741         memset ( ipoib, 0, sizeof ( *ipoib ) );
742         ipoib->netdev = netdev;
743         ipoib->ibdev = ibdev;
744
745         /* Calculate broadcast GID */
746         memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
747                  sizeof ( ipoib->broadcast_gid ) );
748         ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
749
750         /* Allocate metadata queue set */
751         if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
752                                         IPOIB_META_NUM_CQES,
753                                         IPOIB_META_NUM_SEND_WQES,
754                                         IPOIB_META_NUM_RECV_WQES,
755                                         IB_GLOBAL_QKEY ) ) != 0 ) {
756                 DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
757                        ipoib, strerror ( rc ) );
758                 goto err_create_meta_qset;
759         }
760
761
762
763         /* Allocate data queue set */
764         if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
765                                         IPOIB_DATA_NUM_CQES,
766                                         IPOIB_DATA_NUM_SEND_WQES,
767                                         IPOIB_DATA_NUM_RECV_WQES,
768                                         hack_ipoib_qkey ) ) != 0 ) {
769                 DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
770                        ipoib, strerror ( rc ) );
771                 goto err_create_data_qset;
772         }
773
774         /* Construct MAC address */
775         mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
776         mac->qpn = htonl ( ipoib->data.qp->qpn );
777         memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
778
779         /* Register network device */
780         if ( ( rc = register_netdev ( netdev ) ) != 0 )
781                 goto err_register_netdev;
782
783         return 0;
784
785  err_register_netdev:
786         ipoib_destroy_qset ( ipoib, &ipoib->data );
787  err_create_data_qset:
788         ipoib_destroy_qset ( ipoib, &ipoib->meta );
789  err_create_meta_qset:
790         netdev_nullify ( netdev );
791         netdev_put ( netdev );
792         return rc;
793 }
794
795 /**
796  * Remove IPoIB device
797  *
798  * @v ibdev             Infiniband device
799  */
800 void ipoib_remove ( struct ib_device *ibdev ) {
801         struct net_device *netdev = ib_get_ownerdata ( ibdev );
802         struct ipoib_device *ipoib = netdev->priv;
803
804         unregister_netdev ( netdev );
805         ipoib_destroy_qset ( ipoib, &ipoib->data );
806         ipoib_destroy_qset ( ipoib, &ipoib->meta );
807         netdev_nullify ( netdev );
808         netdev_put ( netdev );
809 }