iPXE
Data Structures | Defines | Functions | Variables
ib_cmrc.c File Reference

Infiniband Communication-managed Reliable Connections. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/process.h>
#include <ipxe/infiniband.h>
#include <ipxe/ib_cm.h>
#include <ipxe/ib_cmrc.h>

Go to the source code of this file.

Data Structures

struct  ib_cmrc_connection
 An Infiniband Communication-Managed Reliable Connection. More...

Defines

#define IB_CMRC_NUM_SEND_WQES   4
 CMRC number of send WQEs.
#define IB_CMRC_NUM_RECV_WQES   2
 CMRC number of receive WQEs.
#define IB_CMRC_NUM_CQES   8
 CMRC number of completion queue entries.

Functions

 FILE_LICENCE (BSD2)
static void ib_cmrc_shutdown (struct ib_cmrc_connection *cmrc)
 Shut down CMRC connection gracefully.
static void ib_cmrc_close (struct ib_cmrc_connection *cmrc, int rc)
 Close CMRC connection.
static void ib_cmrc_changed (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_connection *conn __unused, int rc_cm, void *private_data, size_t private_data_len)
 Handle change of CMRC connection status.
static void ib_cmrc_complete_send (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
 Handle CMRC send completion.
static void ib_cmrc_complete_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest __unused, struct ib_address_vector *source __unused, struct io_buffer *iobuf, int rc)
 Handle CMRC receive completion.
static int ib_cmrc_xfer_deliver (struct ib_cmrc_connection *cmrc, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Send data via CMRC.
static size_t ib_cmrc_xfer_window (struct ib_cmrc_connection *cmrc)
 Check CMRC flow control window.
static struct deviceib_cmrc_identify_device (struct ib_cmrc_connection *cmrc)
 Identify device underlying CMRC connection.
int ib_cmrc_open (struct interface *xfer, struct ib_device *ibdev, union ib_gid *dgid, union ib_guid *service_id, const char *name)
 Open CMRC connection.

Variables

static struct
ib_connection_operations 
ib_cmrc_conn_op
 CMRC connection operations.
static struct
ib_completion_queue_operations 
ib_cmrc_completion_ops
 Infiniband CMRC completion operations.
static struct
ib_queue_pair_operations 
ib_cmrc_queue_pair_ops
 Infiniband CMRC queue pair operations.
static struct interface_operation ib_cmrc_xfer_operations []
 CMRC data transfer interface operations.
static struct interface_descriptor ib_cmrc_xfer_desc
 CMRC data transfer interface descriptor.
static struct process_descriptor ib_cmrc_shutdown_desc
 CMRC shutdown process descriptor.

Detailed Description

Infiniband Communication-managed Reliable Connections.

Definition in file ib_cmrc.c.


Define Documentation

#define IB_CMRC_NUM_SEND_WQES   4

CMRC number of send WQEs.

This is a policy decision.

Definition at line 54 of file ib_cmrc.c.

Referenced by ib_cmrc_open().

#define IB_CMRC_NUM_RECV_WQES   2

CMRC number of receive WQEs.

This is a policy decision.

Definition at line 60 of file ib_cmrc.c.

Referenced by ib_cmrc_open().

#define IB_CMRC_NUM_CQES   8

CMRC number of completion queue entries.

This is a policy decision

Definition at line 66 of file ib_cmrc.c.

Referenced by ib_cmrc_open().


Function Documentation

FILE_LICENCE ( BSD2  )
static void ib_cmrc_shutdown ( struct ib_cmrc_connection cmrc) [static]

Shut down CMRC connection gracefully.

Parameters:
cmrcCommunication-Managed Reliable Connection

The Infiniband data structures are not reference-counted or guarded. It is therefore unsafe to shut them down while we may be in the middle of a callback from the Infiniband stack (e.g. in a receive completion handler).

This shutdown process will run some time after the call to ib_cmrc_close(), after control has returned out of the Infiniband core, and will shut down the Infiniband interfaces cleanly.

The shutdown process holds an implicit reference on the CMRC connection, ensuring that the structure is not freed before the shutdown process has run.

Definition at line 112 of file ib_cmrc.c.

References ib_cmrc_connection::conn, ib_cmrc_connection::cq, DBGC, ib_close(), ib_destroy_conn(), ib_destroy_cq(), ib_destroy_qp(), ib_cmrc_connection::ibdev, ib_cmrc_connection::name, ib_device::name, process_del(), ib_cmrc_connection::qp, ref_put, ib_cmrc_connection::refcnt, and ib_cmrc_connection::shutdown.

                                                                 {
        struct ib_device *ibdev = cmrc->ibdev;

        DBGC ( cmrc, "CMRC %s %s shutting down\n",
               ibdev->name, cmrc->name );

        /* Shut down Infiniband interface */
        ib_destroy_conn ( ibdev, cmrc->qp, cmrc->conn );
        ib_destroy_qp ( ibdev, cmrc->qp );
        ib_destroy_cq ( ibdev, cmrc->cq );
        ib_close ( ibdev );

        /* Cancel any pending shutdown */
        process_del ( &cmrc->shutdown );

        /* Drop the remaining reference */
        ref_put ( &cmrc->refcnt );
}
static void ib_cmrc_close ( struct ib_cmrc_connection cmrc,
int  rc 
) [static]

Close CMRC connection.

Parameters:
cmrcCommunication-Managed Reliable Connection
rcReason for close

Definition at line 137 of file ib_cmrc.c.

References intf_shutdown(), process_add(), ib_cmrc_connection::shutdown, and ib_cmrc_connection::xfer.

Referenced by ib_cmrc_changed(), ib_cmrc_complete_recv(), ib_cmrc_complete_send(), and ib_cmrc_xfer_deliver().

                                                                      {

        /* Close data transfer interface */
        intf_shutdown ( &cmrc->xfer, rc );

        /* Schedule shutdown process */
        process_add ( &cmrc->shutdown );
}
static void ib_cmrc_changed ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_connection *conn  __unused,
int  rc_cm,
void *  private_data,
size_t  private_data_len 
) [static]

Handle change of CMRC connection status.

Parameters:
ibdevInfiniband device
qpQueue pair
connConnection
rc_cmConnection status code
private_dataPrivate data, if available
private_data_lenLength of private data

Definition at line 156 of file ib_cmrc.c.

References ib_cmrc_connection::connected, DBGC, DBGC2, DBGC2_HDA, ib_cmrc_close(), ib_qp_get_ownerdata(), ib_cmrc_connection::name, ib_device::name, strerror(), ib_cmrc_connection::xfer, xfer_deliver_raw(), and xfer_window_changed().

                                                                            {
        struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
        int rc_xfer;

        /* Record connection status */
        if ( rc_cm == 0 ) {
                DBGC ( cmrc, "CMRC %s %s connected\n",
                       ibdev->name, cmrc->name );
                cmrc->connected = 1;
        } else {
                DBGC ( cmrc, "CMRC %s %s disconnected: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc_cm ) );
                cmrc->connected = 0;
        }

        /* Pass up any private data */
        DBGC2 ( cmrc, "CMRC %s %s received private data:\n",
                ibdev->name, cmrc->name );
        DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
        if ( private_data &&
             ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
                                            private_data_len ) ) != 0 ) {
                DBGC ( cmrc, "CMRC %s %s could not deliver private data: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc_xfer ) );
                ib_cmrc_close ( cmrc, rc_xfer );
                return;
        }

        /* Notify upper connection of window change */
        xfer_window_changed ( &cmrc->xfer );

        /* If we are disconnected, close the upper connection */
        if ( rc_cm != 0 ) {
                ib_cmrc_close ( cmrc, rc_cm );
                return;
        }
}
static void ib_cmrc_complete_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct io_buffer iobuf,
int  rc 
) [static]

Handle CMRC send completion.

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

Definition at line 210 of file ib_cmrc.c.

References DBGC, free_iob(), ib_cmrc_close(), ib_qp_get_ownerdata(), ib_cmrc_connection::name, ib_device::name, and strerror().

                                                                      {
        struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );

        /* Free the completed I/O buffer */
        free_iob ( iobuf );

        /* Close the connection on any send errors */
        if ( rc != 0 ) {
                DBGC ( cmrc, "CMRC %s %s send error: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc ) );
                ib_cmrc_close ( cmrc, rc );
                return;
        }
}
static void ib_cmrc_complete_recv ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector *dest  __unused,
struct ib_address_vector *source  __unused,
struct io_buffer iobuf,
int  rc 
) [static]

Handle CMRC receive completion.

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

Definition at line 237 of file ib_cmrc.c.

References io_buffer::data, DBGC, DBGC2, DBGC2_HDA, free_iob(), ib_cmrc_close(), ib_qp_get_ownerdata(), iob_len(), ib_cmrc_connection::name, ib_device::name, strerror(), ib_cmrc_connection::xfer, and xfer_deliver_iob().

                                                                      {
        struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );

        /* Close the connection on any receive errors */
        if ( rc != 0 ) {
                DBGC ( cmrc, "CMRC %s %s receive error: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc ) );
                free_iob ( iobuf );
                ib_cmrc_close ( cmrc, rc );
                return;
        }

        DBGC2 ( cmrc, "CMRC %s %s received:\n", ibdev->name, cmrc->name );
        DBGC2_HDA ( cmrc, 0, iobuf->data, iob_len ( iobuf ) );

        /* Pass up data */
        if ( ( rc = xfer_deliver_iob ( &cmrc->xfer, iobuf ) ) != 0 ) {
                DBGC ( cmrc, "CMRC %s %s could not deliver data: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc ) );
                ib_cmrc_close ( cmrc, rc );
                return;
        }
}
static int ib_cmrc_xfer_deliver ( struct ib_cmrc_connection cmrc,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
) [static]

Send data via CMRC.

Parameters:
cmrcCMRC connection
iobufDatagram I/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 284 of file ib_cmrc.c.

References ib_cmrc_connection::conn, ib_cmrc_connection::connected, io_buffer::data, DBGC, ib_cmrc_connection::dgid, EIO, ENOMEM, free_iob(), ib_cmrc_close(), ib_create_conn(), ib_post_send(), ib_cmrc_connection::ibdev, iob_disown, iob_len(), ib_connection::local_id, ib_cmrc_connection::name, ib_device::name, NULL, out, ib_cmrc_connection::qp, rc, ib_cmrc_connection::service_id, and strerror().

                                                                        {
        struct ib_device *ibdev = cmrc->ibdev;
        int rc;

        /* If no connection has yet been attempted, send this datagram
         * as the CM REQ private data.  Otherwise, send it via the QP.
         */
        if ( ! cmrc->connected ) {

                /* Abort if we have already sent a CM connection request */
                if ( cmrc->conn ) {
                        DBGC ( cmrc, "CMRC %s %s attempt to send before "
                               "connection is complete\n",
                               ibdev->name, cmrc->name );
                        rc = -EIO;
                        goto out;
                }

                /* Send via CM connection request */
                cmrc->conn = ib_create_conn ( cmrc->ibdev, cmrc->qp,
                                              &cmrc->dgid, &cmrc->service_id,
                                              iobuf->data, iob_len ( iobuf ),
                                              &ib_cmrc_conn_op );
                if ( ! cmrc->conn ) {
                        DBGC ( cmrc, "CMRC %s %s could not connect\n",
                               ibdev->name, cmrc->name );
                        rc = -ENOMEM;
                        goto out;
                }
                DBGC ( cmrc, "CMRC %s %s using CM %08x\n",
                       ibdev->name, cmrc->name, cmrc->conn->local_id );

        } else {

                /* Send via QP */
                if ( ( rc = ib_post_send ( cmrc->ibdev, cmrc->qp, NULL,
                                           iob_disown ( iobuf ) ) ) != 0 ) {
                        DBGC ( cmrc, "CMRC %s %s could not send: %s\n",
                               ibdev->name, cmrc->name, strerror ( rc ) );
                        goto out;
                }

        }
        return 0;

 out:
        /* Free the I/O buffer if necessary */
        free_iob ( iobuf );

        /* Close the connection on any errors */
        if ( rc != 0 )
                ib_cmrc_close ( cmrc, rc );

        return rc;
}
static size_t ib_cmrc_xfer_window ( struct ib_cmrc_connection cmrc) [static]

Check CMRC flow control window.

Parameters:
cmrcCMRC connection
Return values:
lenLength of window

Definition at line 348 of file ib_cmrc.c.

References ib_cmrc_connection::connected, and IB_MAX_PAYLOAD_SIZE.

                                                                      {

        /* We indicate a window only when we are successfully
         * connected.
         */
        return ( cmrc->connected ? IB_MAX_PAYLOAD_SIZE : 0 );
}
static struct device* ib_cmrc_identify_device ( struct ib_cmrc_connection cmrc) [static, read]

Identify device underlying CMRC connection.

Parameters:
cmrcCMRC connection
Return values:
deviceUnderlying device

Definition at line 363 of file ib_cmrc.c.

References ib_device::dev, and ib_cmrc_connection::ibdev.

                                                            {
        return cmrc->ibdev->dev;
}
int ib_cmrc_open ( struct interface xfer,
struct ib_device ibdev,
union ib_gid dgid,
union ib_guid service_id,
const char *  name 
)

Open CMRC connection.

Parameters:
xferData transfer interface
ibdevInfiniband device
dgidDestination GID
service_idService ID
nameConnection name
Return values:
rcReturns status code

Definition at line 397 of file ib_cmrc.c.

References ib_cmrc_connection::cq, DBGC, ib_cmrc_connection::dgid, ENOMEM, ib_close(), IB_CMRC_NUM_CQES, IB_CMRC_NUM_RECV_WQES, IB_CMRC_NUM_SEND_WQES, ib_create_cq(), ib_create_qp(), ib_destroy_cq(), ib_destroy_qp(), ib_open(), ib_qp_set_ownerdata(), IB_QPT_RC, ib_cmrc_connection::ibdev, intf_init(), intf_plug_plug(), memcpy(), ib_cmrc_connection::name, ib_device::name, name, NULL, process_init_stopped(), ib_cmrc_connection::qp, ib_queue_pair::qpn, rc, ref_init, ref_put, ib_cmrc_connection::refcnt, ib_cmrc_connection::service_id, ib_cmrc_connection::shutdown, strerror(), ib_cmrc_connection::xfer, and zalloc().

Referenced by ib_srp_open(), and xcm_reopen().

                                      {
        struct ib_cmrc_connection *cmrc;
        int rc;

        /* Allocate and initialise structure */
        cmrc = zalloc ( sizeof ( *cmrc ) );
        if ( ! cmrc ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &cmrc->refcnt, NULL );
        cmrc->name = name;
        intf_init ( &cmrc->xfer, &ib_cmrc_xfer_desc, &cmrc->refcnt );
        cmrc->ibdev = ibdev;
        memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
        memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
        process_init_stopped ( &cmrc->shutdown, &ib_cmrc_shutdown_desc,
                               &cmrc->refcnt );

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

        /* Create completion queue */
        if ( ( rc = ib_create_cq ( ibdev, IB_CMRC_NUM_CQES,
                                   &ib_cmrc_completion_ops, &cmrc->cq ) ) != 0){
                DBGC ( cmrc, "CMRC %s %s could not create completion queue: "
                       "%s\n", ibdev->name, cmrc->name, strerror ( rc ) );
                goto err_create_cq;
        }

        /* Create queue pair */
        if ( ( rc = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
                                   cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq,
                                   &ib_cmrc_queue_pair_ops, name,
                                   &cmrc->qp ) ) != 0 ) {
                DBGC ( cmrc, "CMRC %s %s could not create queue pair: %s\n",
                       ibdev->name, cmrc->name, strerror ( rc ) );
                goto err_create_qp;
        }
        ib_qp_set_ownerdata ( cmrc->qp, cmrc );
        DBGC ( cmrc, "CMRC %s %s using QPN %#lx\n",
               ibdev->name, cmrc->name, cmrc->qp->qpn );

        /* Attach to parent interface, transfer reference (implicitly)
         * to our shutdown process, and return.
         */
        intf_plug_plug ( &cmrc->xfer, xfer );
        return 0;

        ib_destroy_qp ( ibdev, cmrc->qp );
 err_create_qp:
        ib_destroy_cq ( ibdev, cmrc->cq );
 err_create_cq:
        ib_close ( ibdev );
 err_open:
        ref_put ( &cmrc->refcnt );
 err_alloc:
        return rc;
}

Variable Documentation

Initial value:
 {
        .changed = ib_cmrc_changed,
}

CMRC connection operations.

Definition at line 198 of file ib_cmrc.c.

Initial value:
 {
        .complete_send = ib_cmrc_complete_send,
        .complete_recv = ib_cmrc_complete_recv,
}

Infiniband CMRC completion operations.

Definition at line 266 of file ib_cmrc.c.

Initial value:
 {
        .alloc_iob = alloc_iob,
}

Infiniband CMRC queue pair operations.

Definition at line 272 of file ib_cmrc.c.

Initial value:

CMRC data transfer interface operations.

Definition at line 368 of file ib_cmrc.c.

Initial value:

CMRC data transfer interface descriptor.

Definition at line 379 of file ib_cmrc.c.

Initial value:

CMRC shutdown process descriptor.

Definition at line 383 of file ib_cmrc.c.