iPXE
Defines | Functions | Variables
infiniband.c File Reference

Infiniband protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/list.h>
#include <ipxe/errortab.h>
#include <ipxe/if_arp.h>
#include <ipxe/netdevice.h>
#include <ipxe/iobuf.h>
#include <ipxe/process.h>
#include <ipxe/profile.h>
#include <ipxe/infiniband.h>
#include <ipxe/ib_mi.h>
#include <ipxe/ib_sma.h>

Go to the source code of this file.

Defines

#define EINPROGRESS_INIT   __einfo_error ( EINFO_EINPROGRESS_INIT )
#define EINFO_EINPROGRESS_INIT
#define EINPROGRESS_ARMED   __einfo_error ( EINFO_EINPROGRESS_ARMED )
#define EINFO_EINPROGRESS_ARMED

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int ib_create_cq (struct ib_device *ibdev, unsigned int num_cqes, struct ib_completion_queue_operations *op, struct ib_completion_queue **new_cq)
 Create completion queue.
void ib_destroy_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Destroy completion queue.
void ib_poll_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Poll completion queue.
int ib_create_qp (struct ib_device *ibdev, enum ib_queue_pair_type type, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq, struct ib_queue_pair_operations *op, const char *name, struct ib_queue_pair **new_qp)
 Create queue pair.
int ib_modify_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Modify queue pair.
void ib_destroy_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Destroy queue pair.
struct ib_queue_pairib_find_qp_qpn (struct ib_device *ibdev, unsigned long qpn)
 Find queue pair by QPN.
struct ib_queue_pairib_find_qp_mgid (struct ib_device *ibdev, union ib_gid *gid)
 Find queue pair by multicast GID.
struct ib_work_queueib_find_wq (struct ib_completion_queue *cq, unsigned long qpn, int is_send)
 Find work queue belonging to completion queue.
int ib_post_send (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf)
 Post send work queue entry.
int ib_post_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf)
 Post receive work queue entry.
void ib_complete_send (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
 Complete send work queue entry.
void ib_complete_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc)
 Complete receive work queue entry.
void ib_refill_recv (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Refill receive work queue.
int ib_link_rc (struct ib_device *ibdev)
 Get link state.
static const char * ib_link_state_text (struct ib_device *ibdev)
 Textual representation of Infiniband link state.
static void ib_notify (struct ib_device *ibdev)
 Notify drivers of Infiniband device or link state change.
void ib_link_state_changed (struct ib_device *ibdev)
 Notify of Infiniband link state change.
int ib_open (struct ib_device *ibdev)
 Open port.
void ib_close (struct ib_device *ibdev)
 Close port.
int ib_mcast_attach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
 Attach to multicast group.
void ib_mcast_detach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
 Detach from multicast group.
int ib_count_ports (struct ib_device *ibdev)
 Count Infiniband HCA ports.
int ib_set_port_info (struct ib_device *ibdev, union ib_mad *mad)
 Set port information.
int ib_set_pkey_table (struct ib_device *ibdev, union ib_mad *mad)
 Set partition key table.
void ib_poll_eq (struct ib_device *ibdev)
 Poll event queue.
static void ib_step (struct process *process __unused)
 Single-step the Infiniband event queue.
 PERMANENT_PROCESS (ib_process, ib_step)
 Infiniband event queue process.
struct ib_devicealloc_ibdev (size_t priv_size)
 Allocate Infiniband device.
int register_ibdev (struct ib_device *ibdev)
 Register Infiniband device.
void unregister_ibdev (struct ib_device *ibdev)
 Unregister Infiniband device.
struct ib_devicefind_ibdev (union ib_gid *gid)
 Find Infiniband device by GID.
struct ib_devicelast_opened_ibdev (void)
 Get most recently opened Infiniband device.
 REQUIRING_SYMBOL (register_ibdev)
 REQUIRE_OBJECT (config_infiniband)

Variables

struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices )
 List of Infiniband devices.
static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices )
 List of open Infiniband devices, in reverse order of opening.
static unsigned int ibdev_index = 0
 Infiniband device index.
static struct profiler
ib_post_send_profiler 
__profiler
 Post send work queue entry profiler.
struct errortab infiniband_errors[] __errortab
 Human-readable message for the link statuses.

Detailed Description

Infiniband protocol.

Definition in file infiniband.c.


Define Documentation

Definition at line 69 of file infiniband.c.

Referenced by ib_link_rc().

Value:
__einfo_uniqify \
        ( EINFO_EINPROGRESS, 0x01, "Initialising" )

Definition at line 70 of file infiniband.c.

Definition at line 72 of file infiniband.c.

Referenced by ib_link_rc().

Value:
__einfo_uniqify \
        ( EINFO_EINPROGRESS, 0x02, "Armed" )

Definition at line 73 of file infiniband.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int ib_create_cq ( struct ib_device ibdev,
unsigned int  num_cqes,
struct ib_completion_queue_operations op,
struct ib_completion_queue **  new_cq 
)

Create completion queue.

Parameters:
ibdevInfiniband device
num_cqesNumber of completion queue entries
opCompletion queue operations
new_cqNew completion queue to fill in
Return values:
rcReturn status code

Definition at line 98 of file infiniband.c.

References ib_completion_queue::cqn, ib_device::cqs, ib_device_operations::create_cq, DBGC, ib_device_operations::destroy_cq, ENOMEM, free, ib_cq_get_drvdata(), ib_completion_queue::ibdev, INIT_LIST_HEAD, ib_completion_queue::list, list_add_tail, list_del, ib_device::name, ib_completion_queue::num_cqes, ib_completion_queue::op, op, ib_device::op, rc, strerror(), ib_completion_queue::work_queues, and zalloc().

Referenced by eoib_open(), flexboot_nodnic_eth_open(), hermon_eth_open(), ib_cmrc_open(), ib_create_mi(), and ipoib_open().

                                                         {
        struct ib_completion_queue *cq;
        int rc;

        DBGC ( ibdev, "IBDEV %s creating completion queue\n", ibdev->name );

        /* Allocate and initialise data structure */
        cq = zalloc ( sizeof ( *cq ) );
        if ( ! cq ) {
                rc = -ENOMEM;
                goto err_alloc_cq;
        }
        cq->ibdev = ibdev;
        list_add_tail ( &cq->list, &ibdev->cqs );
        cq->num_cqes = num_cqes;
        INIT_LIST_HEAD ( &cq->work_queues );
        cq->op = op;

        /* Perform device-specific initialisation and get CQN */
        if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not initialise completion "
                       "queue: %s\n", ibdev->name, strerror ( rc ) );
                goto err_dev_create_cq;
        }

        DBGC ( ibdev, "IBDEV %s created %d-entry completion queue %p (%p) "
               "with CQN %#lx\n", ibdev->name, num_cqes, cq,
               ib_cq_get_drvdata ( cq ), cq->cqn );
        *new_cq = cq;
        return 0;

        ibdev->op->destroy_cq ( ibdev, cq );
 err_dev_create_cq:
        list_del ( &cq->list );
        free ( cq );
 err_alloc_cq:
        return rc;
}
void ib_destroy_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
)

Destroy completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 145 of file infiniband.c.

References assert, ib_completion_queue::cqn, DBGC, ib_device_operations::destroy_cq, free, ib_completion_queue::list, list_del, list_empty, ib_device::name, ib_device::op, and ib_completion_queue::work_queues.

Referenced by eoib_close(), eoib_open(), flexboot_nodnic_eth_close(), hermon_eth_close(), hermon_eth_open(), ib_cmrc_open(), ib_cmrc_shutdown(), ib_create_mi(), ib_destroy_mi(), ipoib_close(), and ipoib_open().

                                                      {
        DBGC ( ibdev, "IBDEV %s destroying completion queue %#lx\n",
               ibdev->name, cq->cqn );
        assert ( list_empty ( &cq->work_queues ) );
        ibdev->op->destroy_cq ( ibdev, cq );
        list_del ( &cq->list );
        free ( cq );
}
void ib_poll_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
)

Poll completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 161 of file infiniband.c.

References ib_refill_recv(), ib_work_queue::is_send, ib_work_queue::list, list_for_each_entry, ib_device::op, ib_device_operations::poll_cq, ib_work_queue::qp, and ib_completion_queue::work_queues.

Referenced by flexboot_nodnic_complete_all_tx(), golan_cq_clean(), and ib_poll_eq().

                                                   {
        struct ib_work_queue *wq;

        /* Poll completion queue */
        ibdev->op->poll_cq ( ibdev, cq );

        /* Refill receive work queues */
        list_for_each_entry ( wq, &cq->work_queues, list ) {
                if ( ! wq->is_send )
                        ib_refill_recv ( ibdev, wq->qp );
        }
}
int ib_create_qp ( struct ib_device ibdev,
enum ib_queue_pair_type  type,
unsigned int  num_send_wqes,
struct ib_completion_queue send_cq,
unsigned int  num_recv_wqes,
struct ib_completion_queue recv_cq,
struct ib_queue_pair_operations op,
const char *  name,
struct ib_queue_pair **  new_qp 
)

Create queue pair.

Parameters:
ibdevInfiniband device
typeQueue pair type
num_send_wqesNumber of send work queue entries
send_cqSend completion queue
num_recv_wqesNumber of receive work queue entries
recv_cqReceive completion queue
opQueue pair operations
nameQueue pair name
new_qpNew queue pair to fill in
Return values:
rcReturn status code

The queue pair will be left in the INIT state; you must call ib_modify_qp() before it is ready to use for sending and receiving.

Definition at line 199 of file infiniband.c.

References ib_work_queue::cq, ib_device_operations::create_qp, DBGC, ib_device_operations::destroy_qp, ENOMEM, free, ib_qp_get_drvdata(), IB_QPN_GSI, IB_QPN_SMI, IB_QPT_GSI, IB_QPT_SMI, ib_queue_pair::ibdev, INIT_LIST_HEAD, ib_work_queue::iobufs, ib_work_queue::is_send, ib_work_queue::list, ib_queue_pair::list, list_add_tail, list_del, ib_queue_pair::mgids, ib_queue_pair::name, ib_device::name, name, ib_work_queue::num_wqes, ib_queue_pair::op, op, ib_device::op, ib_work_queue::psn, ib_work_queue::qp, qp, ib_queue_pair::qpn, ib_device::qps, random(), rc, ib_queue_pair::recv, ib_queue_pair::send, strerror(), ib_queue_pair::type, type, ib_completion_queue::work_queues, and zalloc().

Referenced by eoib_open(), flexboot_nodnic_eth_open(), hermon_eth_open(), ib_cmrc_open(), ib_create_mi(), and ipoib_open().

                                                   {
        struct ib_queue_pair *qp;
        size_t total_size;
        int rc;

        DBGC ( ibdev, "IBDEV %s creating queue pair\n", ibdev->name );

        /* Allocate and initialise data structure */
        total_size = ( sizeof ( *qp ) +
                       ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
                       ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
        qp = zalloc ( total_size );
        if ( ! qp ) {
                rc = -ENOMEM;
                goto err_alloc_qp;
        }
        qp->ibdev = ibdev;
        list_add_tail ( &qp->list, &ibdev->qps );
        qp->type = type;
        qp->send.qp = qp;
        qp->send.is_send = 1;
        qp->send.cq = send_cq;
        list_add_tail ( &qp->send.list, &send_cq->work_queues );
        qp->send.psn = ( random() & 0xffffffUL );
        qp->send.num_wqes = num_send_wqes;
        qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
        qp->recv.qp = qp;
        qp->recv.cq = recv_cq;
        list_add_tail ( &qp->recv.list, &recv_cq->work_queues );
        qp->recv.psn = ( random() & 0xffffffUL );
        qp->recv.num_wqes = num_recv_wqes;
        qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
                            ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
        INIT_LIST_HEAD ( &qp->mgids );
        qp->op = op;
        qp->name = name;

        /* Perform device-specific initialisation and get QPN */
        if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not initialise queue pair: "
                       "%s\n", ibdev->name, strerror ( rc ) );
                goto err_dev_create_qp;
        }
        DBGC ( ibdev, "IBDEV %s created queue pair %p (%p) with QPN %#lx\n",
               ibdev->name, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
        DBGC ( ibdev, "IBDEV %s QPN %#lx has %d send entries at [%p,%p)\n",
               ibdev->name, qp->qpn, num_send_wqes, qp->send.iobufs,
               qp->recv.iobufs );
        DBGC ( ibdev, "IBDEV %s QPN %#lx has %d receive entries at [%p,%p)\n",
               ibdev->name, qp->qpn, num_recv_wqes, qp->recv.iobufs,
               ( ( ( void * ) qp ) + total_size ) );

        /* Calculate externally-visible QPN */
        switch ( type ) {
        case IB_QPT_SMI:
                qp->ext_qpn = IB_QPN_SMI;
                break;
        case IB_QPT_GSI:
                qp->ext_qpn = IB_QPN_GSI;
                break;
        default:
                qp->ext_qpn = qp->qpn;
                break;
        }
        if ( qp->ext_qpn != qp->qpn ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx has external QPN %#lx\n",
                       ibdev->name, qp->qpn, qp->ext_qpn );
        }

        *new_qp = qp;
        return 0;

        ibdev->op->destroy_qp ( ibdev, qp );
 err_dev_create_qp:
        list_del ( &qp->send.list );
        list_del ( &qp->recv.list );
        list_del ( &qp->list );
        free ( qp );
 err_alloc_qp:
        return rc;
}
int ib_modify_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
)

Modify queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair
Return values:
rcReturn status code

Definition at line 294 of file infiniband.c.

References DBGC, ib_device_operations::modify_qp, ib_device::name, ib_device::op, ib_queue_pair::qpn, rc, and strerror().

Referenced by hermon_eth_open(), ib_cm_req_complete(), ib_create_mi(), and ib_mcast_complete().

                                                                       {
        int rc;

        DBGC ( ibdev, "IBDEV %s modifying QPN %#lx\n", ibdev->name, qp->qpn );

        if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not modify QPN %#lx: %s\n",
                       ibdev->name, qp->qpn, strerror ( rc ) );
                return rc;
        }

        return 0;
}
void ib_destroy_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
)

Destroy queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 314 of file infiniband.c.

References assert, DBGC, ib_device_operations::destroy_qp, ECANCELED, free, ib_complete_recv(), ib_complete_send(), ib_work_queue::iobufs, ib_work_queue::list, ib_queue_pair::list, list_del, list_empty, ib_queue_pair::mgids, ib_device::name, NULL, ib_work_queue::num_wqes, ib_device::op, ib_queue_pair::qpn, ib_queue_pair::recv, and ib_queue_pair::send.

Referenced by eoib_close(), eoib_open(), flexboot_nodnic_eth_close(), flexboot_nodnic_eth_open(), hermon_eth_close(), hermon_eth_open(), ib_cmrc_open(), ib_cmrc_shutdown(), ib_create_mi(), ib_destroy_mi(), ipoib_close(), and ipoib_open().

                                                                         {
        struct io_buffer *iobuf;
        unsigned int i;

        DBGC ( ibdev, "IBDEV %s destroying QPN %#lx\n",
               ibdev->name, qp->qpn );

        assert ( list_empty ( &qp->mgids ) );

        /* Perform device-specific destruction */
        ibdev->op->destroy_qp ( ibdev, qp );

        /* Complete any remaining I/O buffers with errors */
        for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
                if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
                        ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
        }
        for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
                if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
                        ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf,
                                           -ECANCELED );
                }
        }

        /* Remove work queues from completion queue */
        list_del ( &qp->send.list );
        list_del ( &qp->recv.list );

        /* Free QP */
        list_del ( &qp->list );
        free ( qp );
}
struct ib_queue_pair* ib_find_qp_qpn ( struct ib_device ibdev,
unsigned long  qpn 
) [read]

Find queue pair by QPN.

Parameters:
ibdevInfiniband device
qpnQueue pair number
Return values:
qpQueue pair, or NULL

Definition at line 354 of file infiniband.c.

References ib_queue_pair::ext_qpn, ib_queue_pair::list, list_for_each_entry, NULL, qp, ib_queue_pair::qpn, and ib_device::qps.

Referenced by ib_pull().

                                                            {
        struct ib_queue_pair *qp;

        list_for_each_entry ( qp, &ibdev->qps, list ) {
                if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
                        return qp;
        }
        return NULL;
}
struct ib_queue_pair* ib_find_qp_mgid ( struct ib_device ibdev,
union ib_gid gid 
) [read]

Find queue pair by multicast GID.

Parameters:
ibdevInfiniband device
gidMulticast GID
Return values:
qpQueue pair, or NULL

Definition at line 372 of file infiniband.c.

References ib_multicast_gid::gid, ib_multicast_gid::list, list_for_each_entry, memcmp(), mgid, ib_queue_pair::mgids, NULL, qp, and ib_device::qps.

Referenced by ib_pull().

                                                             {
        struct ib_queue_pair *qp;
        struct ib_multicast_gid *mgid;

        list_for_each_entry ( qp, &ibdev->qps, list ) {
                list_for_each_entry ( mgid, &qp->mgids, list ) {
                        if ( memcmp ( &mgid->gid, gid,
                                      sizeof ( mgid->gid ) ) == 0 ) {
                                return qp;
                        }
                }
        }
        return NULL;
}
struct ib_work_queue* ib_find_wq ( struct ib_completion_queue cq,
unsigned long  qpn,
int  is_send 
) [read]

Find work queue belonging to completion queue.

Parameters:
cqCompletion queue
qpnQueue pair number
is_sendFind send work queue (rather than receive)
Return values:
wqWork queue, or NULL if not found

Definition at line 396 of file infiniband.c.

References ib_work_queue::is_send, ib_work_queue::list, list_for_each_entry, NULL, ib_work_queue::qp, ib_queue_pair::qpn, and ib_completion_queue::work_queues.

Referenced by arbel_complete(), golan_complete(), and hermon_complete().

                                                                     {
        struct ib_work_queue *wq;

        list_for_each_entry ( wq, &cq->work_queues, list ) {
                if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
                        return wq;
        }
        return NULL;
}
int ib_post_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector dest,
struct io_buffer iobuf 
)

Post send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 416 of file infiniband.c.

References ib_queue_pair::av, DBGC, ENOBUFS, ib_work_queue::fill, IB_RATE_2_5, memcpy(), ib_device::name, ib_work_queue::num_wqes, ib_device::op, ib_device_operations::post_send, profile_start(), profile_stop(), ib_address_vector::qkey, ib_queue_pair::qkey, ib_queue_pair::qpn, ib_address_vector::rate, rc, ib_queue_pair::send, and strerror().

Referenced by eoib_duplicate(), eoib_transmit(), flexboot_nodnic_eth_transmit(), hermon_eth_transmit(), ib_cmrc_xfer_deliver(), ib_mi_send(), and ipoib_transmit().

                                             {
        struct ib_address_vector dest_copy;
        int rc;

        /* Start profiling */
        profile_start ( &ib_post_send_profiler );

        /* Check queue fill level */
        if ( qp->send.fill >= qp->send.num_wqes ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx send queue full\n",
                       ibdev->name, qp->qpn );
                return -ENOBUFS;
        }

        /* Use default address vector if none specified */
        if ( ! dest )
                dest = &qp->av;

        /* Make modifiable copy of address vector */
        memcpy ( &dest_copy, dest, sizeof ( dest_copy ) );
        dest = &dest_copy;

        /* Fill in optional parameters in address vector */
        if ( ! dest->qkey )
                dest->qkey = qp->qkey;
        if ( ! dest->rate )
                dest->rate = IB_RATE_2_5;

        /* Post to hardware */
        if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx could not post send WQE: "
                       "%s\n", ibdev->name, qp->qpn, strerror ( rc ) );
                return rc;
        }

        /* Increase fill level */
        qp->send.fill++;

        /* Stop profiling */
        profile_stop ( &ib_post_send_profiler );

        return 0;
}
int ib_post_recv ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct io_buffer iobuf 
)

Post receive work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 470 of file infiniband.c.

References DBGC, EINVAL, ENOBUFS, ib_work_queue::fill, IB_MAX_PAYLOAD_SIZE, iob_tailroom(), ib_device::name, ib_work_queue::num_wqes, ib_device::op, ib_device_operations::post_recv, profile_start(), profile_stop(), ib_queue_pair::qpn, rc, ib_queue_pair::recv, and strerror().

Referenced by ib_refill_recv().

                                             {
        int rc;

        /* Start profiling */
        profile_start ( &ib_post_recv_profiler );

        /* Check packet length */
        if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx wrong RX buffer size (%zd)\n",
                       ibdev->name, qp->qpn, iob_tailroom ( iobuf ) );
                return -EINVAL;
        }

        /* Check queue fill level */
        if ( qp->recv.fill >= qp->recv.num_wqes ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx receive queue full\n",
                       ibdev->name, qp->qpn );
                return -ENOBUFS;
        }

        /* Post to hardware */
        if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s QPN %#lx could not post receive WQE: "
                       "%s\n", ibdev->name, qp->qpn, strerror ( rc ) );
                return rc;
        }

        /* Increase fill level */
        qp->recv.fill++;

        /* Stop profiling */
        profile_stop ( &ib_post_recv_profiler );

        return 0;
}
void ib_complete_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct io_buffer iobuf,
int  rc 
)

Complete send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
iobufI/O buffer
rcCompletion status code

Definition at line 515 of file infiniband.c.

References ib_completion_queue_operations::complete_send, ib_work_queue::cq, ib_work_queue::fill, free_iob(), ib_completion_queue::op, and ib_queue_pair::send.

Referenced by arbel_complete(), flexboot_nodnic_complete(), golan_complete(), hermon_complete(), ib_destroy_qp(), linda_complete_send(), and qib7322_complete_send().

                                                          {

        if ( qp->send.cq->op->complete_send ) {
                qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
        } else {
                free_iob ( iobuf );
        }
        qp->send.fill--;
}
void ib_complete_recv ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector dest,
struct ib_address_vector source,
struct io_buffer iobuf,
int  rc 
)

Complete receive work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector, or NULL
sourceSource address vector, or NULL
iobufI/O buffer
rcCompletion status code

Definition at line 536 of file infiniband.c.

References ib_completion_queue_operations::complete_recv, ib_work_queue::cq, ib_work_queue::fill, free_iob(), ib_completion_queue::op, and ib_queue_pair::recv.

Referenced by arbel_complete(), flexboot_nodnic_complete(), golan_complete(), hermon_complete(), ib_destroy_qp(), linda_complete_recv(), and qib7322_complete_recv().

                                                          {

        if ( qp->recv.cq->op->complete_recv ) {
                qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source,
                                                 iobuf, rc );
        } else {
                free_iob ( iobuf );
        }
        qp->recv.fill--;
}
void ib_refill_recv ( struct ib_device ibdev,
struct ib_queue_pair qp 
)

Refill receive work queue.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 556 of file infiniband.c.

References ib_queue_pair_operations::alloc_iob, DBGC, ib_work_queue::fill, free_iob(), IB_MAX_PAYLOAD_SIZE, ib_post_recv(), ib_device::name, ib_work_queue::num_wqes, ib_queue_pair::op, rc, ib_queue_pair::recv, and strerror().

Referenced by eoib_open(), flexboot_nodnic_eth_open(), hermon_eth_open(), ib_create_mi(), ib_poll_cq(), and ipoib_open().

                                                                          {
        struct io_buffer *iobuf;
        int rc;

        /* Keep filling while unfilled entries remain */
        while ( qp->recv.fill < qp->recv.num_wqes ) {

                /* Allocate I/O buffer */
                iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE );
                if ( ! iobuf ) {
                        /* Non-fatal; we will refill on next attempt */
                        return;
                }

                /* Post I/O buffer */
                if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
                        DBGC ( ibdev, "IBDEV %s could not refill: %s\n",
                               ibdev->name, strerror ( rc ) );
                        free_iob ( iobuf );
                        /* Give up */
                        return;
                }
        }
}
int ib_link_rc ( struct ib_device ibdev)

Get link state.

Parameters:
ibdevInfiniband device
Return values:
rcLink status code

Definition at line 594 of file infiniband.c.

References EINPROGRESS_ARMED, EINPROGRESS_INIT, EINVAL, ENOTCONN, IB_PORT_STATE_ACTIVE, IB_PORT_STATE_ARMED, IB_PORT_STATE_DOWN, IB_PORT_STATE_INIT, and ib_device::port_state.

Referenced by eoib_link_state_changed(), and ipoib_link_state_changed().

                                           {
        switch ( ibdev->port_state ) {
        case IB_PORT_STATE_DOWN:        return -ENOTCONN;
        case IB_PORT_STATE_INIT:        return -EINPROGRESS_INIT;
        case IB_PORT_STATE_ARMED:       return -EINPROGRESS_ARMED;
        case IB_PORT_STATE_ACTIVE:      return 0;
        default:                        return -EINVAL;
        }
}
static const char* ib_link_state_text ( struct ib_device ibdev) [static]

Textual representation of Infiniband link state.

Parameters:
ibdevInfiniband device
Return values:
link_textLink state text

Definition at line 610 of file infiniband.c.

References IB_PORT_STATE_ACTIVE, IB_PORT_STATE_ARMED, IB_PORT_STATE_DOWN, IB_PORT_STATE_INIT, and ib_device::port_state.

Referenced by ib_link_state_changed().

                                                                   {
        switch ( ibdev->port_state ) {
        case IB_PORT_STATE_DOWN:        return "DOWN";
        case IB_PORT_STATE_INIT:        return "INIT";
        case IB_PORT_STATE_ARMED:       return "ARMED";
        case IB_PORT_STATE_ACTIVE:      return "ACTIVE";
        default:                        return "UNKNOWN";
        }
}
static void ib_notify ( struct ib_device ibdev) [static]

Notify drivers of Infiniband device or link state change.

Parameters:
ibdevInfiniband device

Definition at line 625 of file infiniband.c.

References driver, for_each_table_entry, IB_DRIVERS, and ib_driver::notify.

Referenced by ib_close(), ib_link_state_changed(), and ib_open().

                                                  {
        struct ib_driver *driver;

        for_each_table_entry ( driver, IB_DRIVERS )
                driver->notify ( ibdev );
}
void ib_link_state_changed ( struct ib_device ibdev)

Notify of Infiniband link state change.

Parameters:
ibdevInfiniband device

Definition at line 637 of file infiniband.c.

References DBGC, ib_link_state_text(), ib_notify(), and ib_device::name.

Referenced by golan_ib_update(), ib_smc_update(), linda_link_state_changed(), and qib7322_link_state_changed().

                                                       {

        DBGC ( ibdev, "IBDEV %s link state is %s\n",
               ibdev->name, ib_link_state_text ( ibdev ) );

        /* Notify drivers of link state change */
        ib_notify ( ibdev );
}
int ib_open ( struct ib_device ibdev)

Open port.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 652 of file infiniband.c.

References assert, ib_device_operations::close, DBGC, ib_device::gsi, ib_create_mi(), ib_create_sma(), ib_destroy_mi(), ib_destroy_sma(), ib_notify(), IB_QPT_GSI, IB_QPT_SMI, list_add, ib_device::name, ib_device::op, ib_device_operations::open, ib_device::open_count, ib_device::open_list, rc, ib_device::smi, and strerror().

Referenced by eoib_open(), ib_cmrc_open(), ipoib_open(), and xsigo_ib_open().

                                        {
        int rc;

        /* Increment device open request counter */
        if ( ibdev->open_count++ > 0 ) {
                /* Device was already open; do nothing */
                return 0;
        }

        /* Open device */
        if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not open: %s\n",
                       ibdev->name, strerror ( rc ) );
                goto err_open;
        }

        /* Create subnet management interface */
        if ( ( rc = ib_create_mi ( ibdev, IB_QPT_SMI, &ibdev->smi ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not create SMI: %s\n",
                       ibdev->name, strerror ( rc ) );
                goto err_create_smi;
        }

        /* Create subnet management agent */
        if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not create SMA: %s\n",
                       ibdev->name, strerror ( rc ) );
                goto err_create_sma;
        }

        /* Create general services interface */
        if ( ( rc = ib_create_mi ( ibdev, IB_QPT_GSI, &ibdev->gsi ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not create GSI: %s\n",
                       ibdev->name, strerror ( rc ) );
                goto err_create_gsi;
        }

        /* Add to head of open devices list */
        list_add ( &ibdev->open_list, &open_ib_devices );

        /* Notify drivers of device state change */
        ib_notify ( ibdev );

        assert ( ibdev->open_count == 1 );
        return 0;

        ib_destroy_mi ( ibdev, ibdev->gsi );
 err_create_gsi:
        ib_destroy_sma ( ibdev, ibdev->smi );
 err_create_sma:
        ib_destroy_mi ( ibdev, ibdev->smi );
 err_create_smi:
        ibdev->op->close ( ibdev );
 err_open:
        assert ( ibdev->open_count == 1 );
        ibdev->open_count = 0;
        return rc;
}
void ib_close ( struct ib_device ibdev)

Close port.

Parameters:
ibdevInfiniband device

Definition at line 716 of file infiniband.c.

References ib_device_operations::close, ib_device::gsi, ib_destroy_mi(), ib_destroy_sma(), ib_notify(), IB_PORT_STATE_DOWN, list_del, ib_device::op, ib_device::open_count, ib_device::open_list, ib_device::port_state, and ib_device::smi.

Referenced by eoib_close(), eoib_open(), ib_cmrc_open(), ib_cmrc_shutdown(), ipoib_close(), ipoib_open(), and xsigo_ib_remove().

                                          {

        /* Decrement device open request counter */
        ibdev->open_count--;

        /* Close device if this was the last remaining requested opening */
        if ( ibdev->open_count == 0 ) {
                ib_notify ( ibdev );
                list_del ( &ibdev->open_list );
                ib_destroy_mi ( ibdev, ibdev->gsi );
                ib_destroy_sma ( ibdev, ibdev->smi );
                ib_destroy_mi ( ibdev, ibdev->smi );
                ibdev->op->close ( ibdev );
                ibdev->port_state = IB_PORT_STATE_DOWN;
        }
}
int ib_mcast_attach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
)

Attach to multicast group.

Parameters:
ibdevInfiniband device
qpQueue pair
gidMulticast GID
Return values:
rcReturn status code

Note that this function handles only the local device's attachment to the multicast GID; it does not issue the relevant MADs to join the multicast group on the subnet.

Definition at line 752 of file infiniband.c.

References assert, ENOMEM, free, ib_multicast_gid::gid, ib_multicast_gid::list, list_add_tail, list_del, ib_device_operations::mcast_attach, memcpy(), mgid, ib_queue_pair::mgids, NULL, ib_device::op, rc, and zalloc().

Referenced by ib_mcast_join().

                                          {
        struct ib_multicast_gid *mgid;
        int rc;

        /* Sanity check */
        assert ( qp != NULL );

        /* Add to software multicast GID list */
        mgid = zalloc ( sizeof ( *mgid ) );
        if ( ! mgid ) {
                rc = -ENOMEM;
                goto err_alloc_mgid;
        }
        memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
        list_add_tail ( &mgid->list, &qp->mgids );

        /* Add to hardware multicast GID list */
        if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
                goto err_dev_mcast_attach;

        return 0;

 err_dev_mcast_attach:
        list_del ( &mgid->list );
        free ( mgid );
 err_alloc_mgid:
        return rc;
}
void ib_mcast_detach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
)

Detach from multicast group.

Parameters:
ibdevInfiniband device
qpQueue pair
gidMulticast GID

Definition at line 789 of file infiniband.c.

References assert, free, ib_multicast_gid::gid, ib_multicast_gid::list, list_del, list_for_each_entry, ib_device_operations::mcast_detach, memcmp(), mgid, ib_queue_pair::mgids, NULL, and ib_device::op.

Referenced by ib_mcast_join(), and ib_mcast_leave().

                                           {
        struct ib_multicast_gid *mgid;

        /* Sanity check */
        assert ( qp != NULL );

        /* Remove from hardware multicast GID list */
        ibdev->op->mcast_detach ( ibdev, qp, gid );

        /* Remove from software multicast GID list */
        list_for_each_entry ( mgid, &qp->mgids, list ) {
                if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
                        list_del ( &mgid->list );
                        free ( mgid );
                        break;
                }
        }
}
int ib_count_ports ( struct ib_device ibdev)

Count Infiniband HCA ports.

Parameters:
ibdevInfiniband device
Return values:
num_portsNumber of ports

Definition at line 822 of file infiniband.c.

References ib_device::dev, for_each_ibdev, and num_ports.

Referenced by ib_sma_node_info().

                                               {
        struct ib_device *tmp;
        int num_ports = 0;

        /* Search for IB devices with the same physical device to
         * identify port count.
         */
        for_each_ibdev ( tmp ) {
                if ( tmp->dev == ibdev->dev )
                        num_ports++;
        }
        return num_ports;
}
int ib_set_port_info ( struct ib_device ibdev,
union ib_mad mad 
)

Set port information.

Parameters:
ibdevInfiniband device
madSet port information MAD

Definition at line 842 of file infiniband.c.

References DBGC, ENOTSUP, ib_device::name, ib_device::op, rc, ib_device_operations::set_port_info, and strerror().

Referenced by ib_sma_set_port_info().

                                                                    {
        int rc;

        /* Adapters with embedded SMAs do not need to support this method */
        if ( ! ibdev->op->set_port_info ) {
                DBGC ( ibdev, "IBDEV %s does not support setting port "
                       "information\n", ibdev->name );
                return -ENOTSUP;
        }

        if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not set port information: %s\n",
                       ibdev->name, strerror ( rc ) );
                return rc;
        }

        return 0;
};
int ib_set_pkey_table ( struct ib_device ibdev,
union ib_mad mad 
)

Set partition key table.

Parameters:
ibdevInfiniband device
madSet partition key table MAD

Definition at line 867 of file infiniband.c.

References DBGC, ENOTSUP, ib_device::name, ib_device::op, rc, ib_device_operations::set_pkey_table, and strerror().

Referenced by ib_sma_set_pkey_table().

                                                                     {
        int rc;

        /* Adapters with embedded SMAs do not need to support this method */
        if ( ! ibdev->op->set_pkey_table ) {
                DBGC ( ibdev, "IBDEV %s does not support setting partition "
                       "key table\n", ibdev->name );
                return -ENOTSUP;
        }

        if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
                DBGC ( ibdev, "IBDEV %s could not set partition key table: "
                       "%s\n", ibdev->name, strerror ( rc ) );
                return rc;
        }

        return 0;
};
void ib_poll_eq ( struct ib_device ibdev)

Poll event queue.

Parameters:
ibdevInfiniband device

Definition at line 898 of file infiniband.c.

References ib_device::cqs, ib_poll_cq(), ib_completion_queue::list, list_for_each_entry, ib_device::op, and ib_device_operations::poll_eq.

Referenced by eoib_poll(), flexboot_nodnic_eth_poll(), hermon_eth_poll(), ib_step(), and ipoib_poll().

                                            {
        struct ib_completion_queue *cq;

        /* Poll device's event queue */
        ibdev->op->poll_eq ( ibdev );

        /* Poll all completion queues */
        list_for_each_entry ( cq, &ibdev->cqs, list )
                ib_poll_cq ( ibdev, cq );
}
static void ib_step ( struct process *process  __unused) [static]

Single-step the Infiniband event queue.

Parameters:
processInfiniband event queue process

Definition at line 914 of file infiniband.c.

References ib_poll_eq(), list_for_each_entry, and ib_device::open_list.

                                                         {
        struct ib_device *ibdev;

        list_for_each_entry ( ibdev, &open_ib_devices, open_list )
                ib_poll_eq ( ibdev );
}
PERMANENT_PROCESS ( ib_process  ,
ib_step   
)

Infiniband event queue process.

struct ib_device* alloc_ibdev ( size_t  priv_size) [read]

Allocate Infiniband device.

Parameters:
priv_sizeSize of driver private data area
Return values:
ibdevInfiniband device, or NULL

Definition at line 937 of file infiniband.c.

References ib_device::cqs, ib_device::drv_priv, IB_LID_NONE, IB_PKEY_DEFAULT, IB_PORT_STATE_DOWN, ib_set_drvdata(), INIT_LIST_HEAD, ib_device::lid, ib_device::list, ib_device::open_list, ib_device::pkey, ib_device::port_state, ib_device::qps, and zalloc().

Referenced by arbel_probe(), flexboot_nodnic_allocate_infiniband_devices(), golan_probe_normal(), hermon_probe(), linda_probe(), and qib7322_probe().

                                                    {
        struct ib_device *ibdev;
        void *drv_priv;
        size_t total_len;

        total_len = ( sizeof ( *ibdev ) + priv_size );
        ibdev = zalloc ( total_len );
        if ( ibdev ) {
                drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
                ib_set_drvdata ( ibdev, drv_priv );
                INIT_LIST_HEAD ( &ibdev->list );
                INIT_LIST_HEAD ( &ibdev->open_list );
                INIT_LIST_HEAD ( &ibdev->cqs );
                INIT_LIST_HEAD ( &ibdev->qps );
                ibdev->port_state = IB_PORT_STATE_DOWN;
                ibdev->lid = IB_LID_NONE;
                ibdev->pkey = IB_PKEY_DEFAULT;
        }
        return ibdev;
}
int register_ibdev ( struct ib_device ibdev)

Register Infiniband device.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 964 of file infiniband.c.

References DBGC, ib_device::dev, driver, for_each_table_entry, for_each_table_entry_continue_reverse, IB_DRIVERS, ibdev_get(), ibdev_index, ibdev_put(), ib_device::index, ib_device::list, list_add_tail, list_del, device::name, ib_device::name, ib_driver::name, ib_driver::probe, rc, ib_driver::remove, snprintf(), and strerror().

Referenced by arbel_probe(), golan_register_ibdev(), hermon_register_ibdev(), linda_probe(), and qib7322_probe().

                                               {
        struct ib_driver *driver;
        int rc;

        /* Record device index and create device name */
        if ( ibdev->name[0] == '\0' ) {
                snprintf ( ibdev->name, sizeof ( ibdev->name ), "inf%d",
                           ibdev_index );
        }
        ibdev->index = ++ibdev_index;

        /* Add to device list */
        ibdev_get ( ibdev );
        list_add_tail ( &ibdev->list, &ib_devices );
        DBGC ( ibdev, "IBDEV %s registered (phys %s)\n", ibdev->name,
               ibdev->dev->name );

        /* Probe device */
        for_each_table_entry ( driver, IB_DRIVERS ) {
                if ( ( rc = driver->probe ( ibdev ) ) != 0 ) {
                        DBGC ( ibdev, "IBDEV %s could not add %s device: %s\n",
                               ibdev->name, driver->name, strerror ( rc ) );
                        goto err_probe;
                }
        }

        return 0;

 err_probe:
        for_each_table_entry_continue_reverse ( driver, IB_DRIVERS )
                driver->remove ( ibdev );
        list_del ( &ibdev->list );
        ibdev_put ( ibdev );
        return rc;
}
void unregister_ibdev ( struct ib_device ibdev)

Unregister Infiniband device.

Parameters:
ibdevInfiniband device

Definition at line 1005 of file infiniband.c.

References DBGC, driver, for_each_table_entry_reverse, IB_DRIVERS, ibdev_index, ibdev_put(), ib_device::list, list_del, list_empty, ib_device::name, and ib_driver::remove.

Referenced by arbel_probe(), arbel_remove(), golan_probe_normal(), golan_remove_normal(), hermon_unregister_ibdev(), linda_probe(), linda_remove(), qib7322_probe(), and qib7322_remove().

                                                  {
        struct ib_driver *driver;

        /* Remove device */
        for_each_table_entry_reverse ( driver, IB_DRIVERS )
                driver->remove ( ibdev );

        /* Remove from device list */
        list_del ( &ibdev->list );
        ibdev_put ( ibdev );
        DBGC ( ibdev, "IBDEV %s unregistered\n", ibdev->name );

        /* Reset device index if no devices remain */
        if ( list_empty ( &ib_devices ) )
                ibdev_index = 0;
}
struct ib_device* find_ibdev ( union ib_gid gid) [read]

Find Infiniband device by GID.

Parameters:
gidGID
Return values:
ibdevInfiniband device, or NULL

Definition at line 1028 of file infiniband.c.

References for_each_ibdev, ib_device::gid, memcmp(), and NULL.

Referenced by ib_srp_open_uri().

                                                    {
        struct ib_device *ibdev;

        for_each_ibdev ( ibdev ) {
                if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
                        return ibdev;
        }
        return NULL;
}
struct ib_device* last_opened_ibdev ( void  ) [read]

Get most recently opened Infiniband device.

Return values:
ibdevMost recently opened Infiniband device, or NULL

Definition at line 1043 of file infiniband.c.

References assert, list_first_entry, NULL, ib_device::open_count, and ib_device::open_list.

Referenced by ib_srp_parse_sgid().

                                              {
        struct ib_device *ibdev;

        ibdev = list_first_entry ( &open_ib_devices, struct ib_device,
                                   open_list );
        if ( ! ibdev )
                return NULL;

        assert ( ibdev->open_count != 0 );
        return ibdev;
}
REQUIRE_OBJECT ( config_infiniband  )

Variable Documentation

List of Infiniband devices.

Definition at line 52 of file infiniband.c.

List of open Infiniband devices, in reverse order of opening.

Definition at line 55 of file infiniband.c.

unsigned int ibdev_index = 0 [static]

Infiniband device index.

Definition at line 58 of file infiniband.c.

Referenced by register_ibdev(), and unregister_ibdev().

struct profiler ib_post_recv_profiler __profiler [static]
Initial value:
        { .name = "ib.post_send" }

Post send work queue entry profiler.

Post receive work queue entry profiler.

Definition at line 61 of file infiniband.c.

struct errortab infiniband_errors [] __errortab
Initial value:

Human-readable message for the link statuses.

Definition at line 77 of file infiniband.c.