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