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