Direct polling of TX completion queue now works.
[people/pcmattman/gpxe.git] / src / net / infiniband.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <byteswap.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <gpxe/if_arp.h>
26 #include <gpxe/netdevice.h>
27 #include <gpxe/iobuf.h>
28 #include <gpxe/infiniband.h>
29
30 /** @file
31  *
32  * Infiniband protocol
33  *
34  */
35
36 /**
37  * Find queue pair from a list
38  *
39  * @v list              List of queue pairs
40  * @v qpn               Queue pair number
41  * @ret qp              Queue pair, or NULL if not found
42  */
43 struct ib_queue_pair * ib_find_qp ( struct list_head *list,
44                                     unsigned long qpn ) {
45         struct ib_queue_pair *qp;
46
47         list_for_each_entry ( qp, list, list ) {
48                 if ( qp->qpn == qpn )
49                         return qp;
50         }
51         return NULL;
52 }
53
54
55
56 /** Infiniband broadcast MAC address */
57 static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
58
59 /**
60  * Transmit Infiniband packet
61  *
62  * @v iobuf             I/O buffer
63  * @v netdev            Network device
64  * @v net_protocol      Network-layer protocol
65  * @v ll_dest           Link-layer destination address
66  *
67  * Prepends the Infiniband link-layer header and transmits the packet.
68  */
69 static int ib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
70                    struct net_protocol *net_protocol, const void *ll_dest ) {
71         struct ibhdr *ibhdr = iob_push ( iobuf, sizeof ( *ibhdr ) );
72
73         /* Build Infiniband header */
74         ibhdr->proto = net_protocol->net_proto;
75         ibhdr->reserved = 0;
76
77         ( void ) ll_dest;
78
79         /* Hand off to network device */
80         return netdev_tx ( netdev, iobuf );
81 }
82
83 /**
84  * Process received Infiniband packet
85  *
86  * @v iobuf     I/O buffer
87  * @v netdev    Network device
88  *
89  * Strips off the Infiniband link-layer header and passes up to the
90  * network-layer protocol.
91  */
92 static int ib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
93         struct ibhdr *ibhdr = iobuf->data;
94
95         /* Sanity check */
96         if ( iob_len ( iobuf ) < sizeof ( *ibhdr ) ) {
97                 DBG ( "Infiniband packet too short (%d bytes)\n",
98                       iob_len ( iobuf ) );
99                 free_iob ( iobuf );
100                 return -EINVAL;
101         }
102
103         /* Strip off Infiniband header */
104         iob_pull ( iobuf, sizeof ( *ibhdr ) );
105
106         /* Hand off to network-layer protocol */
107         return net_rx ( iobuf, netdev, ibhdr->proto, NULL );
108 }
109
110 /**
111  * Transcribe Infiniband address
112  *
113  * @v ll_addr   Link-layer address
114  * @ret string  Link-layer address in human-readable format
115  */
116 const char * ib_ntoa ( const void *ll_addr ) {
117         static char buf[61];
118         const uint8_t *ib_addr = ll_addr;
119         unsigned int i;
120         char *p = buf;
121
122         for ( i = 0 ; i < IB_ALEN ; i++ ) {
123                 p += sprintf ( p, ":%02x", ib_addr[i] );
124         }
125         return ( buf + 1 );
126 }
127
128 /** Infiniband protocol */
129 struct ll_protocol infiniband_protocol __ll_protocol = {
130         .name           = "Infiniband",
131         .ll_proto       = htons ( ARPHRD_INFINIBAND ),
132         .ll_addr_len    = IB_ALEN,
133         .ll_header_len  = IB_HLEN,
134         .ll_broadcast   = ib_broadcast,
135         .tx             = ib_tx,
136         .rx             = ib_rx,
137         .ntoa           = ib_ntoa,
138 };