2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
26 #include <gpxe/list.h>
27 #include <gpxe/if_arp.h>
28 #include <gpxe/netdevice.h>
29 #include <gpxe/iobuf.h>
30 #include <gpxe/infiniband.h>
39 * Create completion queue
41 * @v ibdev Infiniband device
42 * @v num_cqes Number of completion queue entries
43 * @ret cq New completion queue
45 struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
46 unsigned int num_cqes ) {
47 struct ib_completion_queue *cq;
50 DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
52 /* Allocate and initialise data structure */
53 cq = zalloc ( sizeof ( *cq ) );
56 cq->num_cqes = num_cqes;
57 INIT_LIST_HEAD ( &cq->work_queues );
59 /* Perform device-specific initialisation and get CQN */
60 if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
61 DBGC ( ibdev, "IBDEV %p could not initialise CQ: %s\n",
62 ibdev, strerror ( rc ) );
67 DBGC ( ibdev, "IBDEV %p created completion queue %#lx\n",
73 * Destroy completion queue
75 * @v ibdev Infiniband device
76 * @v cq Completion queue
78 void ib_destroy_cq ( struct ib_device *ibdev,
79 struct ib_completion_queue *cq ) {
80 DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
82 assert ( list_empty ( &cq->work_queues ) );
83 ibdev->op->destroy_cq ( ibdev, cq );
88 * Find work queue belonging to completion queue
90 * @v cq Completion queue
91 * @v qpn Queue pair number
92 * @v is_send Find send work queue (rather than receive)
93 * @ret wq Work queue, or NULL if not found
95 struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
96 unsigned long qpn, int is_send ) {
97 struct ib_work_queue *wq;
99 list_for_each_entry ( wq, &cq->work_queues, list ) {
100 if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
108 /** Infiniband broadcast MAC address */
109 static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
112 * Transmit Infiniband packet
114 * @v iobuf I/O buffer
115 * @v netdev Network device
116 * @v net_protocol Network-layer protocol
117 * @v ll_dest Link-layer destination address
119 * Prepends the Infiniband link-layer header and transmits the packet.
121 static int ib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
122 struct net_protocol *net_protocol, const void *ll_dest ) {
123 struct ibhdr *ibhdr = iob_push ( iobuf, sizeof ( *ibhdr ) );
125 /* Build Infiniband header */
126 ibhdr->proto = net_protocol->net_proto;
131 /* Hand off to network device */
132 return netdev_tx ( netdev, iobuf );
136 * Process received Infiniband packet
138 * @v iobuf I/O buffer
139 * @v netdev Network device
141 * Strips off the Infiniband link-layer header and passes up to the
142 * network-layer protocol.
144 static int ib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
145 struct ibhdr *ibhdr = iobuf->data;
148 if ( iob_len ( iobuf ) < sizeof ( *ibhdr ) ) {
149 DBG ( "Infiniband packet too short (%d bytes)\n",
155 /* Strip off Infiniband header */
156 iob_pull ( iobuf, sizeof ( *ibhdr ) );
158 /* Hand off to network-layer protocol */
159 return net_rx ( iobuf, netdev, ibhdr->proto, NULL );
163 * Transcribe Infiniband address
165 * @v ll_addr Link-layer address
166 * @ret string Link-layer address in human-readable format
168 const char * ib_ntoa ( const void *ll_addr ) {
170 const uint8_t *ib_addr = ll_addr;
174 for ( i = 0 ; i < IB_ALEN ; i++ ) {
175 p += sprintf ( p, ":%02x", ib_addr[i] );
180 /** Infiniband protocol */
181 struct ll_protocol infiniband_protocol __ll_protocol = {
182 .name = "Infiniband",
183 .ll_proto = htons ( ARPHRD_INFINIBAND ),
184 .ll_addr_len = IB_ALEN,
185 .ll_header_len = IB_HLEN,
186 .ll_broadcast = ib_broadcast,