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