[infiniband] Split queue set functionality out of ipoib.c to ib_qset.c
authorMichael Brown <mcb30@etherboot.org>
Thu, 2 Jul 2009 08:56:14 +0000 (09:56 +0100)
committerMichael Brown <mcb30@etherboot.org>
Fri, 17 Jul 2009 22:06:33 +0000 (23:06 +0100)
src/drivers/net/ipoib.c
src/include/gpxe/errfile.h
src/include/gpxe/ib_qset.h [new file with mode: 0644]
src/net/infiniband/ib_qset.c [new file with mode: 0644]

index d330d5a..51223e6 100644 (file)
@@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/iobuf.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/infiniband.h>
+#include <gpxe/ib_qset.h>
 #include <gpxe/ipoib.h>
 
 /** @file
@@ -53,16 +54,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 /** Number of IPoIB metadata completion entries */
 #define IPOIB_META_NUM_CQES 8
 
-/** An IPoIB queue set */
-struct ipoib_queue_set {
-       /** Completion queue */
-       struct ib_completion_queue *cq;
-       /** Queue pair */
-       struct ib_queue_pair *qp;
-       /** Receive work queue maximum fill level */
-       unsigned int recv_max_fill;
-};
-
 /** An IPoIB device */
 struct ipoib_device {
        /** Network device */
@@ -70,9 +61,9 @@ struct ipoib_device {
        /** Underlying Infiniband device */
        struct ib_device *ibdev;
        /** Data queue set */
-       struct ipoib_queue_set data;
+       struct ib_queue_set data;
        /** Data queue set */
-       struct ipoib_queue_set meta;
+       struct ib_queue_set meta;
        /** Broadcast GID */
        struct ib_gid broadcast_gid;
        /** Broadcast LID */
@@ -361,79 +352,6 @@ struct ll_protocol ipoib_protocol __ll_protocol = {
  ****************************************************************************
  */
 
-/**
- * Destroy queue set
- *
- * @v ipoib            IPoIB device
- * @v qset             Queue set
- */
-static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
-                                struct ipoib_queue_set *qset ) {
-       struct ib_device *ibdev = ipoib->ibdev;
-
-       if ( qset->qp )
-               ib_destroy_qp ( ibdev, qset->qp );
-       if ( qset->cq )
-               ib_destroy_cq ( ibdev, qset->cq );
-       memset ( qset, 0, sizeof ( *qset ) );
-}
-
-/**
- * Create queue set
- *
- * @v ipoib            IPoIB device
- * @v qset             Queue set
- * @v num_cqes         Number of completion queue entries
- * @v cq_op            Completion queue operations
- * @v num_send_wqes    Number of send work queue entries
- * @v num_recv_wqes    Number of receive work queue entries
- * @v qkey             Queue key
- * @ret rc             Return status code
- */
-static int ipoib_create_qset ( struct ipoib_device *ipoib,
-                              struct ipoib_queue_set *qset,
-                              unsigned int num_cqes,
-                              struct ib_completion_queue_operations *cq_op,
-                              unsigned int num_send_wqes,
-                              unsigned int num_recv_wqes,
-                              unsigned long qkey ) {
-       struct ib_device *ibdev = ipoib->ibdev;
-       int rc;
-
-       /* Sanity check */
-       assert ( qset->cq == NULL );
-       assert ( qset->qp == NULL );
-
-       /* Store queue parameters */
-       qset->recv_max_fill = num_recv_wqes;
-
-       /* Allocate completion queue */
-       qset->cq = ib_create_cq ( ibdev, num_cqes, cq_op );
-       if ( ! qset->cq ) {
-               DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
-                      ipoib );
-               rc = -ENOMEM;
-               goto err;
-       }
-
-       /* Allocate queue pair */
-       qset->qp = ib_create_qp ( ibdev, num_send_wqes, qset->cq,
-                                 num_recv_wqes, qset->cq, qkey );
-       if ( ! qset->qp ) {
-               DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
-                      ipoib );
-               rc = -ENOMEM;
-               goto err;
-       }
-       ib_qp_set_ownerdata ( qset->qp, ipoib->netdev );
-
-       return 0;
-
- err:
-       ipoib_destroy_qset ( ipoib, qset );
-       return rc;
-}
-
 /**
  * Transmit path record request
  *
@@ -625,9 +543,9 @@ static int ipoib_transmit ( struct net_device *netdev,
 static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
                                       struct ib_queue_pair *qp,
                                       struct io_buffer *iobuf, int rc ) {
-       struct net_device *netdev = ib_qp_get_ownerdata ( qp );
+       struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
 
-       netdev_tx_complete_err ( netdev, iobuf, rc );
+       netdev_tx_complete_err ( ipoib->netdev, iobuf, rc );
 }
 
 /**
@@ -643,8 +561,8 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
                                       struct ib_queue_pair *qp,
                                       struct ib_address_vector *av,
                                       struct io_buffer *iobuf, int rc ) {
-       struct net_device *netdev = ib_qp_get_ownerdata ( qp );
-       struct ipoib_device *ipoib = netdev->priv;
+       struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
+       struct net_device *netdev = ipoib->netdev;
        struct ipoib_hdr *ipoib_hdr;
        struct ipoib_peer *src;
 
@@ -690,8 +608,7 @@ static struct ib_completion_queue_operations ipoib_data_cq_op = {
 static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
                                       struct ib_queue_pair *qp,
                                       struct io_buffer *iobuf, int rc ) {
-       struct net_device *netdev = ib_qp_get_ownerdata ( qp );
-       struct ipoib_device *ipoib = netdev->priv;
+       struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
 
        if ( rc != 0 ) {
                DBGC ( ipoib, "IPoIB %p metadata TX completion error: %s\n",
@@ -769,8 +686,7 @@ ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
                           struct ib_queue_pair *qp,
                           struct ib_address_vector *av __unused,
                           struct io_buffer *iobuf, int rc ) {
-       struct net_device *netdev = ib_qp_get_ownerdata ( qp );
-       struct ipoib_device *ipoib = netdev->priv;
+       struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
        struct ib_mad_sa *sa;
 
        if ( rc != 0 ) {
@@ -818,28 +734,6 @@ static struct ib_completion_queue_operations ipoib_meta_cq_op = {
        .complete_recv = ipoib_meta_complete_recv,
 };
 
-/**
- * Refill IPoIB receive ring
- *
- * @v ipoib            IPoIB device
- */
-static void ipoib_refill_recv ( struct ipoib_device *ipoib,
-                               struct ipoib_queue_set *qset ) {
-       struct ib_device *ibdev = ipoib->ibdev;
-       struct io_buffer *iobuf;
-       int rc;
-
-       while ( qset->qp->recv.fill < qset->recv_max_fill ) {
-               iobuf = alloc_iob ( IPOIB_PKT_LEN );
-               if ( ! iobuf )
-                       break;
-               if ( ( rc = ib_post_recv ( ibdev, qset->qp, iobuf ) ) != 0 ) {
-                       free_iob ( iobuf );
-                       break;
-               }
-       }
-}
-
 /**
  * Poll IPoIB network device
  *
@@ -851,8 +745,8 @@ static void ipoib_poll ( struct net_device *netdev ) {
 
        ib_poll_cq ( ibdev, ipoib->meta.cq );
        ib_poll_cq ( ibdev, ipoib->data.cq );
-       ipoib_refill_recv ( ipoib, &ipoib->meta );
-       ipoib_refill_recv ( ipoib, &ipoib->data );
+       ib_qset_refill_recv ( ibdev, &ipoib->meta );
+       ib_qset_refill_recv ( ibdev, &ipoib->data );
 }
 
 /**
@@ -928,46 +822,47 @@ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
  */
 static int ipoib_open ( struct net_device *netdev ) {
        struct ipoib_device *ipoib = netdev->priv;
+       struct ib_device *ibdev = ipoib->ibdev;
        struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
        int rc;
 
        /* Open IB device */
-       if ( ( rc = ib_open ( ipoib->ibdev ) ) != 0 ) {
+       if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
                DBGC ( ipoib, "IPoIB %p could not open device: %s\n",
                       ipoib, strerror ( rc ) );
                goto err_ib_open;
        }
 
        /* Allocate metadata queue set */
-       if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
-                                       IPOIB_META_NUM_CQES,
-                                       &ipoib_meta_cq_op,
-                                       IPOIB_META_NUM_SEND_WQES,
-                                       IPOIB_META_NUM_RECV_WQES,
-                                       IB_GLOBAL_QKEY ) ) != 0 ) {
+       if ( ( rc = ib_create_qset ( ibdev, &ipoib->meta,
+                                    IPOIB_META_NUM_CQES, &ipoib_meta_cq_op,
+                                    IPOIB_META_NUM_SEND_WQES,
+                                    IPOIB_META_NUM_RECV_WQES,
+                                    IPOIB_PKT_LEN, IB_GLOBAL_QKEY ) ) != 0 ) {
                DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
                       ipoib, strerror ( rc ) );
                goto err_create_meta_qset;
        }
+       ib_qp_set_ownerdata ( ipoib->meta.qp, ipoib );
 
        /* Allocate data queue set */
-       if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
-                                       IPOIB_DATA_NUM_CQES,
-                                       &ipoib_data_cq_op,
-                                       IPOIB_DATA_NUM_SEND_WQES,
-                                       IPOIB_DATA_NUM_RECV_WQES,
-                                       IB_GLOBAL_QKEY ) ) != 0 ) {
+       if ( ( rc = ib_create_qset ( ibdev, &ipoib->data,
+                                    IPOIB_DATA_NUM_CQES, &ipoib_data_cq_op,
+                                    IPOIB_DATA_NUM_SEND_WQES,
+                                    IPOIB_DATA_NUM_RECV_WQES,
+                                    IPOIB_PKT_LEN, IB_GLOBAL_QKEY ) ) != 0 ) {
                DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
                       ipoib, strerror ( rc ) );
                goto err_create_data_qset;
        }
+       ib_qp_set_ownerdata ( ipoib->data.qp, ipoib );
 
        /* Update MAC address with data QPN */
        mac->qpn = htonl ( ipoib->data.qp->qpn );
 
        /* Fill receive rings */
-       ipoib_refill_recv ( ipoib, &ipoib->meta );
-       ipoib_refill_recv ( ipoib, &ipoib->data );
+       ib_qset_refill_recv ( ibdev, &ipoib->meta );
+       ib_qset_refill_recv ( ibdev, &ipoib->data );
 
        /* Join broadcast group */
        if ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) {
@@ -979,11 +874,11 @@ static int ipoib_open ( struct net_device *netdev ) {
        return 0;
 
  err_join_broadcast:
-       ipoib_destroy_qset ( ipoib, &ipoib->data );
+       ib_destroy_qset ( ibdev, &ipoib->data );
  err_create_data_qset:
-       ipoib_destroy_qset ( ipoib, &ipoib->meta );
+       ib_destroy_qset ( ibdev, &ipoib->meta );
  err_create_meta_qset:
-       ib_close ( ipoib->ibdev );
+       ib_close ( ibdev );
  err_ib_open:
        return rc;
 }
@@ -1004,8 +899,8 @@ static void ipoib_close ( struct net_device *netdev ) {
        mac->qpn = 0;
 
        /* Tear down the queues */
-       ipoib_destroy_qset ( ipoib, &ipoib->data );
-       ipoib_destroy_qset ( ipoib, &ipoib->meta );
+       ib_destroy_qset ( ipoib->ibdev, &ipoib->data );
+       ib_destroy_qset ( ipoib->ibdev, &ipoib->meta );
 
        /* Close IB device */
        ib_close ( ipoib->ibdev );
index 1312cbc..4b56000 100644 (file)
@@ -143,6 +143,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_ib_sma                 ( ERRFILE_NET | 0x00170000 )
 #define ERRFILE_ib_packet              ( ERRFILE_NET | 0x00180000 )
 #define ERRFILE_icmp                   ( ERRFILE_NET | 0x00190000 )
+#define ERRFILE_ib_qset                        ( ERRFILE_NET | 0x001a0000 )
 
 #define ERRFILE_image                ( ERRFILE_IMAGE | 0x00000000 )
 #define ERRFILE_elf                  ( ERRFILE_IMAGE | 0x00010000 )
diff --git a/src/include/gpxe/ib_qset.h b/src/include/gpxe/ib_qset.h
new file mode 100644 (file)
index 0000000..90c92a5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _GPXE_IB_QSET_H
+#define _GPXE_IB_QSET_H
+
+/** @file
+ *
+ * Infiniband queue sets
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/infiniband.h>
+
+/** An Infiniband queue set */
+struct ib_queue_set {
+       /** Completion queue */
+       struct ib_completion_queue *cq;
+       /** Queue pair */
+       struct ib_queue_pair *qp;
+       /** Receive work queue maximum fill level */
+       unsigned int recv_max_fill;
+       /** Receive packet length */
+       size_t recv_pkt_len;
+};
+
+extern int ib_create_qset ( struct ib_device *ibdev,
+                           struct ib_queue_set *qset, unsigned int num_cqes,
+                           struct ib_completion_queue_operations *cq_op,
+                           unsigned int num_send_wqes,
+                           unsigned int num_recv_wqes, size_t recv_pkt_len,
+                           unsigned long qkey );
+extern void ib_qset_refill_recv ( struct ib_device *ibdev,
+                                 struct ib_queue_set *qset );
+extern void ib_destroy_qset ( struct ib_device *ibdev,
+                             struct ib_queue_set *qset );
+
+#endif /* _GPXE_IB_QSET_H */
diff --git a/src/net/infiniband/ib_qset.c b/src/net/infiniband/ib_qset.c
new file mode 100644 (file)
index 0000000..1972b7a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <string.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_qset.h>
+
+/**
+ * @file
+ *
+ * Infiniband queue sets
+ *
+ */
+
+/**
+ * Create queue set
+ *
+ * @v ibdev            Infiniband device
+ * @v qset             Queue set
+ * @v num_cqes         Number of completion queue entries
+ * @v cq_op            Completion queue operations
+ * @v num_send_wqes    Number of send work queue entries
+ * @v num_recv_wqes    Number of receive work queue entries
+ * @v recv_pkt_len     Receive packet length
+ * @v qkey             Queue key
+ * @ret rc             Return status code
+ */
+int ib_create_qset ( struct ib_device *ibdev, struct ib_queue_set *qset,
+                    unsigned int num_cqes,
+                    struct ib_completion_queue_operations *cq_op,
+                    unsigned int num_send_wqes, unsigned int num_recv_wqes,
+                    size_t recv_pkt_len, unsigned long qkey ) {
+       int rc;
+
+       /* Sanity check */
+       assert ( qset->cq == NULL );
+       assert ( qset->qp == NULL );
+
+       /* Store queue parameters */
+       qset->recv_max_fill = num_recv_wqes;
+       qset->recv_pkt_len = recv_pkt_len;
+
+       /* Allocate completion queue */
+       qset->cq = ib_create_cq ( ibdev, num_cqes, cq_op );
+       if ( ! qset->cq ) {
+               DBGC ( ibdev, "IBDEV %p could not allocate completion queue\n",
+                      ibdev );
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       /* Allocate queue pair */
+       qset->qp = ib_create_qp ( ibdev, num_send_wqes, qset->cq,
+                                 num_recv_wqes, qset->cq, qkey );
+       if ( ! qset->qp ) {
+               DBGC ( ibdev, "IBDEV %p could not allocate queue pair\n",
+                      ibdev );
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       return 0;
+
+ err:
+       ib_destroy_qset ( ibdev, qset );
+       return rc;
+}
+
+/**
+ * Refill IPoIB receive ring
+ *
+ * @v ibdev            Infiniband device
+ * @v qset             Queue set
+ */
+void ib_qset_refill_recv ( struct ib_device *ibdev,
+                          struct ib_queue_set *qset ) {
+       struct io_buffer *iobuf;
+       int rc;
+
+       while ( qset->qp->recv.fill < qset->recv_max_fill ) {
+
+               /* Allocate I/O buffer */
+               iobuf = alloc_iob ( qset->recv_pkt_len );
+               if ( ! iobuf ) {
+                       /* Non-fatal; we will refill on next attempt */
+                       return;
+               }
+
+               /* Post I/O buffer */
+               if ( ( rc = ib_post_recv ( ibdev, qset->qp, iobuf ) ) != 0 ) {
+                       DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
+                              ibdev, strerror ( rc ) );
+                       free_iob ( iobuf );
+                       /* Give up */
+                       return;
+               }
+       }
+}
+
+/**
+ * Destroy queue set
+ *
+ * @v ibdev            Infiniband device
+ * @v qset             Queue set
+ */
+void ib_destroy_qset ( struct ib_device *ibdev,
+                      struct ib_queue_set *qset ) {
+
+       if ( qset->qp )
+               ib_destroy_qp ( ibdev, qset->qp );
+       if ( qset->cq )
+               ib_destroy_cq ( ibdev, qset->cq );
+       memset ( qset, 0, sizeof ( *qset ) );
+}