36df342cd91bc0383b001104e8f526e7b467ec8d
[people/sha0/gpxe.git] / src / drivers / net / ipoib.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <byteswap.h>
26 #include <errno.h>
27 #include <gpxe/if_arp.h>
28 #include <gpxe/iobuf.h>
29 #include <gpxe/netdevice.h>
30 #include <gpxe/infiniband.h>
31 #include <gpxe/ib_qset.h>
32 #include <gpxe/ib_pathrec.h>
33 #include <gpxe/ib_mcast.h>
34 #include <gpxe/ipoib.h>
35
36 /** @file
37  *
38  * IP over Infiniband
39  */
40
41 /** Number of IPoIB data send work queue entries */
42 #define IPOIB_DATA_NUM_SEND_WQES 2
43
44 /** Number of IPoIB data receive work queue entries */
45 #define IPOIB_DATA_NUM_RECV_WQES 4
46
47 /** Number of IPoIB data completion entries */
48 #define IPOIB_DATA_NUM_CQES 8
49
50 /** Number of IPoIB metadata send work queue entries */
51 #define IPOIB_META_NUM_SEND_WQES 2
52
53 /** Number of IPoIB metadata receive work queue entries */
54 #define IPOIB_META_NUM_RECV_WQES 2
55
56 /** Number of IPoIB metadata completion entries */
57 #define IPOIB_META_NUM_CQES 8
58
59 /** An IPoIB device */
60 struct ipoib_device {
61         /** Network device */
62         struct net_device *netdev;
63         /** Underlying Infiniband device */
64         struct ib_device *ibdev;
65         /** Data queue set */
66         struct ib_queue_set data;
67         /** Data queue set */
68         struct ib_queue_set meta;
69         /** Broadcast MAC */
70         struct ipoib_mac broadcast;
71         /** Joined to multicast group
72          *
73          * This flag indicates whether or not we have initiated the
74          * join to the IPv4 multicast group.
75          */
76         int broadcast_joined;
77 };
78
79 /** Broadcast IPoIB address */
80 static struct ipoib_mac ipoib_broadcast = {
81         .qpn = htonl ( IB_QPN_BROADCAST ),
82         .gid.u.bytes =  { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
83                           0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
84 };
85
86 /****************************************************************************
87  *
88  * IPoIB peer cache
89  *
90  ****************************************************************************
91  */
92
93 /**
94  * IPoIB peer address
95  *
96  * The IPoIB link-layer header is only four bytes long and so does not
97  * have sufficient room to store IPoIB MAC address(es).  We therefore
98  * maintain a cache of MAC addresses identified by a single-byte key,
99  * and abuse the spare two bytes within the link-layer header to
100  * communicate these MAC addresses between the link-layer code and the
101  * netdevice driver.
102  */
103 struct ipoib_peer {
104         /** Key */
105         uint8_t key;
106         /** MAC address */
107         struct ipoib_mac mac;
108 };
109
110 /** Number of IPoIB peer cache entries
111  *
112  * Must be a power of two.
113  */
114 #define IPOIB_NUM_CACHED_PEERS 4
115
116 /** IPoIB peer address cache */
117 static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS];
118
119 /** Oldest IPoIB peer cache entry index */
120 static unsigned int ipoib_peer_cache_idx = 1;
121
122 /**
123  * Look up cached peer by key
124  *
125  * @v key               Peer cache key
126  * @ret peer            Peer cache entry, or NULL
127  */
128 static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) {
129         struct ipoib_peer *peer;
130         unsigned int i;
131
132         for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
133                 peer = &ipoib_peer_cache[i];
134                 if ( peer->key == key )
135                         return peer;
136         }
137
138         if ( key != 0 ) {
139                 DBG ( "IPoIB warning: peer cache lost track of key %x while "
140                       "still in use\n", key );
141         }
142         return NULL;
143 }
144
145 /**
146  * Store GID and QPN in peer cache
147  *
148  * @v gid               Peer GID
149  * @v qpn               Peer QPN
150  * @ret peer            Peer cache entry
151  */
152 static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) {
153         struct ipoib_peer *peer;
154         unsigned int key;
155         unsigned int i;
156
157         /* Look for existing cache entry */
158         for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
159                 peer = &ipoib_peer_cache[i];
160                 if ( memcmp ( &peer->mac, mac, sizeof ( peer->mac ) ) == 0 )
161                         return peer;
162         }
163
164         /* No entry found: create a new one */
165         key = ipoib_peer_cache_idx++;
166         peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ];
167         if ( peer->key )
168                 DBG ( "IPoIB peer %x evicted from cache\n", peer->key );
169
170         memset ( peer, 0, sizeof ( *peer ) );
171         peer->key = key;
172         memcpy ( &peer->mac, mac, sizeof ( peer->mac ) );
173         DBG ( "IPoIB peer %x has MAC %s\n",
174               peer->key, ipoib_ntoa ( &peer->mac ) );
175         return peer;
176 }
177
178 /****************************************************************************
179  *
180  * IPoIB link layer
181  *
182  ****************************************************************************
183  */
184
185 /**
186  * Add IPoIB link-layer header
187  *
188  * @v netdev            Network device
189  * @v iobuf             I/O buffer
190  * @v ll_dest           Link-layer destination address
191  * @v ll_source         Source link-layer address
192  * @v net_proto         Network-layer protocol, in network-byte order
193  * @ret rc              Return status code
194  */
195 static int ipoib_push ( struct net_device *netdev __unused,
196                         struct io_buffer *iobuf, const void *ll_dest,
197                         const void *ll_source __unused, uint16_t net_proto ) {
198         struct ipoib_hdr *ipoib_hdr =
199                 iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
200         const struct ipoib_mac *dest_mac = ll_dest;
201         const struct ipoib_mac *src_mac = ll_source;
202         struct ipoib_peer *dest;
203         struct ipoib_peer *src;
204
205         /* Add link-layer addresses to cache */
206         dest = ipoib_cache_peer ( dest_mac );
207         src = ipoib_cache_peer ( src_mac );
208
209         /* Build IPoIB header */
210         ipoib_hdr->proto = net_proto;
211         ipoib_hdr->u.peer.dest = dest->key;
212         ipoib_hdr->u.peer.src = src->key;
213
214         return 0;
215 }
216
217 /**
218  * Remove IPoIB link-layer header
219  *
220  * @v netdev            Network device
221  * @v iobuf             I/O buffer
222  * @ret ll_dest         Link-layer destination address
223  * @ret ll_source       Source link-layer address
224  * @ret net_proto       Network-layer protocol, in network-byte order
225  * @ret rc              Return status code
226  */
227 static int ipoib_pull ( struct net_device *netdev,
228                         struct io_buffer *iobuf, const void **ll_dest,
229                         const void **ll_source, uint16_t *net_proto ) {
230         struct ipoib_device *ipoib = netdev->priv;
231         struct ipoib_hdr *ipoib_hdr = iobuf->data;
232         struct ipoib_peer *dest;
233         struct ipoib_peer *source;
234
235         /* Sanity check */
236         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
237                 DBG ( "IPoIB packet too short for link-layer header\n" );
238                 DBG_HD ( iobuf->data, iob_len ( iobuf ) );
239                 return -EINVAL;
240         }
241
242         /* Strip off IPoIB header */
243         iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
244
245         /* Identify source and destination addresses, and clear
246          * reserved word in IPoIB header
247          */
248         dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
249         source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src );
250         ipoib_hdr->u.reserved = 0;
251
252         /* Fill in required fields */
253         *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast );
254         *ll_source = ( source ? &source->mac : &ipoib->broadcast );
255         *net_proto = ipoib_hdr->proto;
256
257         return 0;
258 }
259
260 /**
261  * Transcribe IPoIB address
262  *
263  * @v ll_addr   Link-layer address
264  * @ret string  Link-layer address in human-readable format
265  */
266 const char * ipoib_ntoa ( const void *ll_addr ) {
267         static char buf[45];
268         const struct ipoib_mac *mac = ll_addr;
269
270         snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x",
271                    htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
272                    htonl ( mac->gid.u.dwords[1] ),
273                    htonl ( mac->gid.u.dwords[2] ),
274                    htonl ( mac->gid.u.dwords[3] ) );
275         return buf;
276 }
277
278 /**
279  * Hash multicast address
280  *
281  * @v af                Address family
282  * @v net_addr          Network-layer address
283  * @v ll_addr           Link-layer address to fill in
284  * @ret rc              Return status code
285  */
286 static int ipoib_mc_hash ( unsigned int af __unused,
287                            const void *net_addr __unused,
288                            void *ll_addr __unused ) {
289
290         return -ENOTSUP;
291 }
292
293 /** IPoIB protocol */
294 struct ll_protocol ipoib_protocol __ll_protocol = {
295         .name           = "IPoIB",
296         .ll_proto       = htons ( ARPHRD_INFINIBAND ),
297         .ll_addr_len    = IPOIB_ALEN,
298         .ll_header_len  = IPOIB_HLEN,
299         .push           = ipoib_push,
300         .pull           = ipoib_pull,
301         .ntoa           = ipoib_ntoa,
302         .mc_hash        = ipoib_mc_hash,
303 };
304
305 /**
306  * Allocate IPoIB device
307  *
308  * @v priv_size         Size of driver private data
309  * @ret netdev          Network device, or NULL
310  */
311 struct net_device * alloc_ipoibdev ( size_t priv_size ) {
312         struct net_device *netdev;
313
314         netdev = alloc_netdev ( priv_size );
315         if ( netdev ) {
316                 netdev->ll_protocol = &ipoib_protocol;
317                 netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast;
318                 netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
319         }
320         return netdev;
321 }
322
323 /****************************************************************************
324  *
325  * IPoIB network device
326  *
327  ****************************************************************************
328  */
329
330 /**
331  * Transmit packet via IPoIB network device
332  *
333  * @v netdev            Network device
334  * @v iobuf             I/O buffer
335  * @ret rc              Return status code
336  */
337 static int ipoib_transmit ( struct net_device *netdev,
338                             struct io_buffer *iobuf ) {
339         struct ipoib_device *ipoib = netdev->priv;
340         struct ib_device *ibdev = ipoib->ibdev;
341         struct ipoib_hdr *ipoib_hdr;
342         struct ipoib_peer *dest;
343         struct ib_address_vector av;
344         int rc;
345
346         /* Sanity check */
347         if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
348                 DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
349                 return -EINVAL;
350         }
351         ipoib_hdr = iobuf->data;
352
353         /* Attempting transmission while link is down will put the
354          * queue pair into an error state, so don't try it.
355          */
356         if ( ! ib_link_ok ( ibdev ) )
357                 return -ENETUNREACH;
358
359         /* Identify destination address */
360         dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
361         if ( ! dest )
362                 return -ENXIO;
363         ipoib_hdr->u.reserved = 0;
364
365         /* Construct address vector */
366         memset ( &av, 0, sizeof ( av ) );
367         av.qpn = ntohl ( dest->mac.qpn );
368         av.gid_present = 1;
369         memcpy ( &av.gid, &dest->mac.gid, sizeof ( av.gid ) );
370         if ( ( rc = ib_resolve_path ( ibdev, &av ) ) != 0 ) {
371                 /* Path not resolved yet */
372                 return rc;
373         }
374
375         return ib_post_send ( ibdev, ipoib->data.qp, &av, iobuf );
376 }
377
378 /**
379  * Handle IPoIB data send completion
380  *
381  * @v ibdev             Infiniband device
382  * @v qp                Queue pair
383  * @v iobuf             I/O buffer
384  * @v rc                Completion status code
385  */
386 static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
387                                        struct ib_queue_pair *qp,
388                                        struct io_buffer *iobuf, int rc ) {
389         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
390
391         netdev_tx_complete_err ( ipoib->netdev, iobuf, rc );
392 }
393
394 /**
395  * Handle IPoIB data receive completion
396  *
397  * @v ibdev             Infiniband device
398  * @v qp                Queue pair
399  * @v av                Address vector, or NULL
400  * @v iobuf             I/O buffer
401  * @v rc                Completion status code
402  */
403 static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
404                                        struct ib_queue_pair *qp,
405                                        struct ib_address_vector *av,
406                                        struct io_buffer *iobuf, int rc ) {
407         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
408         struct net_device *netdev = ipoib->netdev;
409         struct ipoib_hdr *ipoib_hdr;
410         struct ipoib_mac ll_src;
411         struct ipoib_peer *src;
412
413         if ( rc != 0 ) {
414                 netdev_rx_err ( netdev, iobuf, rc );
415                 return;
416         }
417
418         /* Sanity check */
419         if ( iob_len ( iobuf ) < sizeof ( struct ipoib_hdr ) ) {
420                 DBGC ( ipoib, "IPoIB %p received data packet too short to "
421                        "contain IPoIB header\n", ipoib );
422                 DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
423                 netdev_rx_err ( netdev, iobuf, -EIO );
424                 return;
425         }
426         ipoib_hdr = iobuf->data;
427
428         /* Parse source address */
429         if ( av->gid_present ) {
430                 ll_src.qpn = htonl ( av->qpn );
431                 memcpy ( &ll_src.gid, &av->gid, sizeof ( ll_src.gid ) );
432                 src = ipoib_cache_peer ( &ll_src );
433                 ipoib_hdr->u.peer.src = src->key;
434         }
435
436         /* Hand off to network layer */
437         netdev_rx ( netdev, iobuf );
438 }
439
440 /** IPoIB data completion operations */
441 static struct ib_completion_queue_operations ipoib_data_cq_op = {
442         .complete_send = ipoib_data_complete_send,
443         .complete_recv = ipoib_data_complete_recv,
444 };
445
446 /**
447  * Handle IPoIB metadata send completion
448  *
449  * @v ibdev             Infiniband device
450  * @v qp                Queue pair
451  * @v iobuf             I/O buffer
452  * @v rc                Completion status code
453  */
454 static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
455                                        struct ib_queue_pair *qp,
456                                        struct io_buffer *iobuf, int rc ) {
457         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
458
459         if ( rc != 0 ) {
460                 DBGC ( ipoib, "IPoIB %p metadata TX completion error: %s\n",
461                        ipoib, strerror ( rc ) );
462         }
463         free_iob ( iobuf );
464 }
465
466 /**
467  * Handle IPoIB metadata receive completion
468  *
469  * @v ibdev             Infiniband device
470  * @v qp                Queue pair
471  * @v av                Address vector, or NULL
472  * @v iobuf             I/O buffer
473  * @v rc                Completion status code
474  */
475 static void
476 ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
477                            struct ib_queue_pair *qp,
478                            struct ib_address_vector *av __unused,
479                            struct io_buffer *iobuf, int rc ) {
480         struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
481         struct ib_mad_sa *sa;
482
483         if ( rc != 0 ) {
484                 DBGC ( ipoib, "IPoIB %p metadata RX completion error: %s\n",
485                        ipoib, strerror ( rc ) );
486                 goto done;
487         }
488
489         if ( iob_len ( iobuf ) < sizeof ( *sa ) ) {
490                 DBGC ( ipoib, "IPoIB %p received metadata packet too short "
491                        "to contain reply\n", ipoib );
492                 DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
493                 goto done;
494         }
495         sa = iobuf->data;
496
497         if ( sa->mad_hdr.status != 0 ) {
498                 DBGC ( ipoib, "IPoIB %p metadata RX err status %04x\n",
499                        ipoib, ntohs ( sa->mad_hdr.status ) );
500                 goto done;
501         }
502
503         switch ( sa->mad_hdr.tid[0] ) {
504         default:
505                 DBGC ( ipoib, "IPoIB %p unwanted response:\n",
506                        ipoib );
507                 DBGC_HD ( ipoib, sa, sizeof ( *sa ) );
508                 break;
509         }
510
511  done:
512         free_iob ( iobuf );
513 }
514
515 /** IPoIB metadata completion operations */
516 static struct ib_completion_queue_operations ipoib_meta_cq_op = {
517         .complete_send = ipoib_meta_complete_send,
518         .complete_recv = ipoib_meta_complete_recv,
519 };
520
521 /**
522  * Poll IPoIB network device
523  *
524  * @v netdev            Network device
525  */
526 static void ipoib_poll ( struct net_device *netdev ) {
527         struct ipoib_device *ipoib = netdev->priv;
528         struct ib_device *ibdev = ipoib->ibdev;
529
530         ib_poll_eq ( ibdev );
531 }
532
533 /**
534  * Enable/disable interrupts on IPoIB network device
535  *
536  * @v netdev            Network device
537  * @v enable            Interrupts should be enabled
538  */
539 static void ipoib_irq ( struct net_device *netdev __unused,
540                         int enable __unused ) {
541         /* No implementation */
542 }
543
544 /**
545  * Join IPv4 broadcast multicast group
546  *
547  * @v ipoib             IPoIB device
548  * @ret rc              Return status code
549  */
550 static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
551         int rc;
552
553         if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->data.qp,
554                                     &ipoib->broadcast.gid ) ) != 0 ) {
555                 DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
556                        ipoib, strerror ( rc ) );
557                 return rc;
558         }
559         ipoib->broadcast_joined = 1;
560
561         return 0;
562 }
563
564 /**
565  * Leave IPv4 broadcast multicast group
566  *
567  * @v ipoib             IPoIB device
568  */
569 static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
570
571         /* Detach data queue from broadcast multicast GID */
572         if ( ipoib->broadcast_joined ) {
573                 ib_mcast_leave ( ipoib->ibdev, ipoib->data.qp,
574                                  &ipoib->broadcast.gid );
575                 ipoib->broadcast_joined = 0;
576         }
577 }
578
579 /**
580  * Open IPoIB network device
581  *
582  * @v netdev            Network device
583  * @ret rc              Return status code
584  */
585 static int ipoib_open ( struct net_device *netdev ) {
586         struct ipoib_device *ipoib = netdev->priv;
587         struct ib_device *ibdev = ipoib->ibdev;
588         struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
589         int rc;
590
591         /* Open IB device */
592         if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
593                 DBGC ( ipoib, "IPoIB %p could not open device: %s\n",
594                        ipoib, strerror ( rc ) );
595                 goto err_ib_open;
596         }
597
598         /* Allocate metadata queue set */
599         if ( ( rc = ib_create_qset ( ibdev, &ipoib->meta,
600                                      IPOIB_META_NUM_CQES, &ipoib_meta_cq_op,
601                                      IPOIB_META_NUM_SEND_WQES,
602                                      IPOIB_META_NUM_RECV_WQES,
603                                      IB_QKEY_GMA ) ) != 0 ) {
604                 DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
605                        ipoib, strerror ( rc ) );
606                 goto err_create_meta_qset;
607         }
608         ib_qp_set_ownerdata ( ipoib->meta.qp, ipoib );
609
610         /* Allocate data queue set */
611         if ( ( rc = ib_create_qset ( ibdev, &ipoib->data,
612                                      IPOIB_DATA_NUM_CQES, &ipoib_data_cq_op,
613                                      IPOIB_DATA_NUM_SEND_WQES,
614                                      IPOIB_DATA_NUM_RECV_WQES,
615                                      IB_QKEY_GMA ) ) != 0 ) {
616                 DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
617                        ipoib, strerror ( rc ) );
618                 goto err_create_data_qset;
619         }
620         ib_qp_set_ownerdata ( ipoib->data.qp, ipoib );
621
622         /* Update MAC address with data QPN */
623         mac->qpn = htonl ( ipoib->data.qp->qpn );
624
625         /* Fill receive rings */
626         ib_refill_recv ( ibdev, ipoib->meta.qp );
627         ib_refill_recv ( ibdev, ipoib->data.qp );
628
629         /* Join broadcast group */
630         if ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) {
631                 DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
632                        ipoib, strerror ( rc ) );
633                 goto err_join_broadcast;
634         }
635
636         return 0;
637
638  err_join_broadcast:
639         ib_destroy_qset ( ibdev, &ipoib->data );
640  err_create_data_qset:
641         ib_destroy_qset ( ibdev, &ipoib->meta );
642  err_create_meta_qset:
643         ib_close ( ibdev );
644  err_ib_open:
645         return rc;
646 }
647
648 /**
649  * Close IPoIB network device
650  *
651  * @v netdev            Network device
652  */
653 static void ipoib_close ( struct net_device *netdev ) {
654         struct ipoib_device *ipoib = netdev->priv;
655         struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
656
657         /* Leave broadcast group */
658         ipoib_leave_broadcast_group ( ipoib );
659
660         /* Remove data QPN from MAC address */
661         mac->qpn = 0;
662
663         /* Tear down the queues */
664         ib_destroy_qset ( ipoib->ibdev, &ipoib->data );
665         ib_destroy_qset ( ipoib->ibdev, &ipoib->meta );
666
667         /* Close IB device */
668         ib_close ( ipoib->ibdev );
669 }
670
671 /** IPoIB network device operations */
672 static struct net_device_operations ipoib_operations = {
673         .open           = ipoib_open,
674         .close          = ipoib_close,
675         .transmit       = ipoib_transmit,
676         .poll           = ipoib_poll,
677         .irq            = ipoib_irq,
678 };
679
680 /**
681  * Update IPoIB dynamic Infiniband parameters
682  *
683  * @v ipoib             IPoIB device
684  *
685  * The Infiniband port GID and partition key will change at runtime,
686  * when the link is established (or lost).  The MAC address is based
687  * on the port GID, and the broadcast GID is based on the partition
688  * key.  This function recalculates these IPoIB device parameters.
689  */
690 static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
691         struct ib_device *ibdev = ipoib->ibdev;
692         struct net_device *netdev = ipoib->netdev;
693         struct ipoib_mac *mac;
694
695         /* Calculate GID portion of MAC address based on port GID */
696         mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
697         memcpy ( &mac->gid, &ibdev->gid, sizeof ( mac->gid ) );
698
699         /* Calculate broadcast GID based on partition key */
700         memcpy ( &ipoib->broadcast, &ipoib_broadcast,
701                  sizeof ( ipoib->broadcast ) );
702         ipoib->broadcast.gid.u.words[2] = htons ( ibdev->pkey );
703
704         /* Set net device link state to reflect Infiniband link state */
705         if ( ib_link_ok ( ibdev ) ) {
706                 netdev_link_up ( netdev );
707         } else {
708                 netdev_link_down ( netdev );
709         }
710 }
711
712 /**
713  * Handle link status change
714  *
715  * @v ibdev             Infiniband device
716  */
717 void ipoib_link_state_changed ( struct ib_device *ibdev ) {
718         struct net_device *netdev = ib_get_ownerdata ( ibdev );
719         struct ipoib_device *ipoib = netdev->priv;
720         int rc;
721
722         /* Leave existing broadcast group */
723         ipoib_leave_broadcast_group ( ipoib );
724
725         /* Update MAC address and broadcast GID based on new port GID
726          * and partition key.
727          */
728         ipoib_set_ib_params ( ipoib );
729
730         /* Join new broadcast group */
731         if ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) {
732                 DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
733                        "%s\n", ipoib, strerror ( rc ) );
734                 return;
735         }
736 }
737
738 /**
739  * Probe IPoIB device
740  *
741  * @v ibdev             Infiniband device
742  * @ret rc              Return status code
743  */
744 int ipoib_probe ( struct ib_device *ibdev ) {
745         struct net_device *netdev;
746         struct ipoib_device *ipoib;
747         int rc;
748
749         /* Allocate network device */
750         netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
751         if ( ! netdev )
752                 return -ENOMEM;
753         netdev_init ( netdev, &ipoib_operations );
754         ipoib = netdev->priv;
755         ib_set_ownerdata ( ibdev, netdev );
756         netdev->dev = ibdev->dev;
757         netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast );
758         memset ( ipoib, 0, sizeof ( *ipoib ) );
759         ipoib->netdev = netdev;
760         ipoib->ibdev = ibdev;
761
762         /* Calculate as much of the broadcast GID and the MAC address
763          * as we can.  We won't know either of these in full until we
764          * have link-up.
765          */
766         ipoib_set_ib_params ( ipoib );
767
768         /* Register network device */
769         if ( ( rc = register_netdev ( netdev ) ) != 0 )
770                 goto err_register_netdev;
771
772         return 0;
773
774  err_register_netdev:
775         netdev_nullify ( netdev );
776         netdev_put ( netdev );
777         return rc;
778 }
779
780 /**
781  * Remove IPoIB device
782  *
783  * @v ibdev             Infiniband device
784  */
785 void ipoib_remove ( struct ib_device *ibdev ) {
786         struct net_device *netdev = ib_get_ownerdata ( ibdev );
787
788         unregister_netdev ( netdev );
789         netdev_nullify ( netdev );
790         netdev_put ( netdev );
791 }