Started to add code for CQ creation
authorMichael Brown <mcb30@etherboot.org>
Sun, 16 Sep 2007 11:52:58 +0000 (12:52 +0100)
committerMichael Brown <mcb30@etherboot.org>
Sun, 16 Sep 2007 11:52:58 +0000 (12:52 +0100)
src/drivers/net/mlx_ipoib/arbel.h
src/drivers/net/mlx_ipoib/mt25218.c
src/drivers/net/mlx_ipoib/mt25218.h

index a41b633..68c6282 100644 (file)
@@ -85,6 +85,12 @@ union arbelprm_doorbell_register {
  *
  */
 
+/** Arbel device limits */
+struct arbel_dev_limits {
+       /** Number of reserved CQs */
+       unsigned long reserved_cqs;
+};
+
 /** Alignment of Arbel send work queue entries */
 #define ARBEL_SEND_WQE_ALIGN 128
 
@@ -129,6 +135,12 @@ struct arbel_queue_pair {
        struct arbel_recv_work_queue recv;
 };
 
+/** Maximum number of allocatable completion queues
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define ARBEL_MAX_CQS          8
+
 /** An Arbel completion queue */
 struct arbel_completion_queue {
        /** Infiniband completion queue */
@@ -139,6 +151,14 @@ struct arbel_completion_queue {
        union arbelprm_completion_entry *cqe;
 };
 
+/** An Arbel resource bitmask */
+typedef uint32_t arbel_bitmask_t;
+
+/** Size of an Arbel resource bitmask */
+#define ARBEL_BITMASK_SIZE(max_entries)                                             \
+       ( ( (max_entries) + ( 8 * sizeof ( arbel_bitmask_t ) ) - 1 ) /       \
+         ( 8 * sizeof ( arbel_bitmask_t ) ) )
+
 /** An Arbel device */
 struct arbel {
        /** Configuration registers */
@@ -157,7 +177,12 @@ struct arbel {
         * Used to get unrestricted memory access.
         */
        unsigned long reserved_lkey;
+
+       /** Completion queue in-use bitmask */
+       arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ];
        
+       /** Device limits */
+       struct arbel_dev_limits limits;
 };
 
 /*
@@ -203,4 +228,64 @@ struct arbel {
 #define ARBEL_HCR_OUT_CMD( _opcode, _out_mbox, _out_len )                   \
        ARBEL_HCR_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
 
+/*
+ * Doorbell record allocation
+ *
+ * The doorbell record map looks like:
+ *
+ *    ARBEL_MAX_CQS * Arm completion queue doorbell
+ *    ARBEL_MAX_QPS * Send work request doorbell
+ *    Group separator
+ *    ...(empty space)...
+ *    ARBEL_MAX_QPS * Receive work request doorbell
+ *    ARBEL_MAX_CQS * Completion queue consumer counter update doorbell
+ */
+
+#define ARBEL_MAX_DOORBELL_RECORDS 512
+#define ARBEL_GROUP_SEPARATOR_DOORBELL ( ARBEL_MAX_CQS + ARBEL_MAX_QPS )
+
+/**
+ * Get arm completion queue doorbell index
+ *
+ * @v cqn_offset       Completion queue number offset
+ * @ret doorbell_idx   Doorbell index
+ */
+static inline unsigned int
+arbel_arm_cq_doorbell_idx ( unsigned int cqn_offset ) {
+       return cqn_offset;
+}
+
+/**
+ * Get send work request doorbell index
+ *
+ * @v qpn_offset       Queue pair number offset
+ * @ret doorbell_idx   Doorbell index
+ */
+static inline unsigned int
+arbel_send_doorbell_idx ( unsigned int qpn_offset ) {
+       return ( ARBEL_MAX_CQS + qpn_offset );
+}
+
+/**
+ * Get receive work request doorbell index
+ *
+ * @v qpn_offset       Queue pair number offset
+ * @ret doorbell_idx   Doorbell index
+ */
+static inline unsigned int
+arbel_recv_doorbell_idx ( unsigned int qpn_offset ) {
+       return ( ARBEL_MAX_DOORBELL_RECORDS - ARBEL_MAX_CQS - qpn_offset - 1 );
+}
+
+/**
+ * Get commpletion queue consumer counter doorbell index
+ *
+ * @v cqn_offset       Completion queue number offset
+ * @ret doorbell_idx   Doorbell index
+ */
+static inline unsigned int
+arbel_cq_ci_doorbell_idx ( unsigned int cqn_offset ) {
+       return ( ARBEL_MAX_DOORBELL_RECORDS - cqn_offset - 1 );
+}
+
 #endif /* _ARBEL_H */
index 4fcc6a3..925b00f 100644 (file)
@@ -12,6 +12,7 @@ Skeleton NIC driver for Etherboot
 
 #include <errno.h>
 #include <gpxe/pci.h>
+#include <gpxe/malloc.h>
 #include <gpxe/iobuf.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/infiniband.h>
@@ -266,6 +267,50 @@ static struct net_device_operations mlx_operations = {
        .irq            = mlx_irq,
 };
 
+
+
+
+/**
+ * Allocate queue number
+ *
+ * @v q_inuse          Queue usage bitmask
+ * @v max_inuse                Maximum number of in-use queues
+ * @ret qn_offset      Free queue number offset, or negative error
+ */
+static int arbel_alloc_qn_offset ( arbel_bitmask_t *q_inuse,
+                                  unsigned int max_inuse ) {
+       unsigned int qn_offset = 0;
+       arbel_bitmask_t mask = 1;
+
+       while ( qn_offset < max_inuse ) {
+               if ( ( mask & *q_inuse ) == 0 ) {
+                       *q_inuse |= mask;
+                       return qn_offset;
+               }
+               qn_offset++;
+               mask <<= 1;
+               if ( ! mask ) {
+                       mask = 1;
+                       q_inuse++;
+               }
+       }
+       return -ENFILE;
+}
+
+/**
+ * Free queue number
+ *
+ * @v q_inuse          Queue usage bitmask
+ * @v qn_offset                Queue number offset
+ */
+static void arbel_free_qn_offset ( arbel_bitmask_t *q_inuse, int qn_offset ) {
+       arbel_bitmask_t mask;
+
+       mask = ( 1 << ( qn_offset % ( 8 * sizeof ( mask ) ) ) );
+       q_inuse += ( qn_offset / ( 8 * sizeof ( mask ) ) );
+       *q_inuse &= ~mask;
+}
+
 /***************************************************************************
  *
  * HCA commands
@@ -412,22 +457,78 @@ arbel_cmd_sw2hw_cq ( struct arbel *arbel, unsigned long cqn,
  * @v ibdev            Infiniband device
  * @v 
  */
-static int arbel_create_cq ( struct ib_device *ibdev,
+static int arbel_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
                             struct ib_completion_queue **new_cq ) {
        struct arbel *arbel = ibdev->priv;
+       struct arbel_completion_queue *arbel_cq;
        struct arbelprm_completion_queue_context cqctx;
-       struct ib_completion_queue *cq;
+       int cqn_offset;
+       unsigned int cqn;
+       size_t cqe_size;
+       unsigned int i;
+       int rc;
 
-       cq = zalloc ( sizeof ( *cq ) );
-       if ( ! cq )
-               return -ENOMEM;
+       /* Find a free completion queue number */
+       cqn_offset = arbel_alloc_qn_offset ( arbel->cq_inuse, ARBEL_MAX_CQS );
+       if ( cqn_offset < 0 ) {
+               rc = cqn_offset;
+               goto err_cqn_offset;
+       }
+       cqn = ( arbel->limits.reserved_cqs + cqn_offset );
 
-       
+       /* Allocate control structures */
+       arbel_cq = zalloc ( sizeof ( *arbel_cq ) );
+       if ( ! arbel_cq ) {
+               rc = -ENOMEM;
+               goto err_arbel_cq;
+       }
+       arbel_cq->cq.cqn = cqn;
+       arbel_cq->cq.num_cqes = num_cqes;
+       INIT_LIST_HEAD ( &arbel_cq->cq.work_queues );
+       arbel_cq->doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
+
+       /* Allocate completion queue itself */
+       cqe_size = ( num_cqes * sizeof ( arbel_cq->cqe[0] ) );
+       arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) );
+       if ( ! arbel_cq->cqe ) {
+               rc = -ENOMEM;
+               goto err_cqe;
+       }
+       memset ( arbel_cq->cqe, 0, cqe_size );
+       for ( i = 0 ; i < num_cqes ; i++ ) {
+               MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 );
+       }
+       barrier();
+
+       /* Initialise doorbell records */
+       // ...
 
+       /* Hand queue over to hardware */
        memset ( &cqctx, 0, sizeof ( cqctx ) );
-       
+       MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
+       MLX_FILL_1 ( &cqctx, 2, start_address_l,
+                    virt_to_bus ( arbel_cq->cqe ) );
+       ///     ....
+
+       if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cqn, &cqctx ) ) != 0 ) {
+               // ...
+       }
 
-       return arbel_cmd_sw2hw_cq ( arbel, 0, &cqctx );
+
+       // completion queue number
+       // doorbell index
+
+       *new_cq = &arbel_cq->cq;
+
+
+       return 0;
+
+ err_cqe:
+       free ( arbel_cq );
+ err_arbel_cq:
+       arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset );
+ err_cqn_offset:
+       return rc;
 }
 
 
@@ -764,6 +865,8 @@ static void arbel_remove ( struct pci_device *pci ) {
 static int arbel_probe ( struct pci_device *pci,
                         const struct pci_device_id *id __unused ) {
        struct net_device *netdev;
+       struct arbelprm_query_dev_lim dev_lim;
+       struct arbel *arbel = &static_arbel;
        struct mlx_nic *mlx;
        struct ib_mac *mac;
        udqp_t qph;
@@ -815,12 +918,14 @@ static int arbel_probe ( struct pci_device *pci,
        list_add ( &static_ipoib_qp.qp.recv.list,
                   &static_ipoib_recv_cq.cq.work_queues );
 
-       struct arbelprm_query_dev_lim dev_lim;
-       memset ( &dev_lim, 0xaa, sizeof ( dev_lim ) );
-       if ( ( rc = arbel_cmd_query_dev_lim ( &static_arbel,
-                                             &dev_lim ) ) != 0 ) {
-               DBG ( "QUERY_DEV_LIM failed: %s\n", strerror ( rc ) );
+       /* Get device limits */
+       if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
+               DBGC ( arbel, "Arbel %p could not get device limits: %s\n",
+                      arbel, strerror ( rc ) );
+               goto err_query_dev_lim;
        }
+       arbel->limits.reserved_cqs =
+               ( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) );
        DBG ( "Device limits:\n ");
        DBG_HD ( &dev_lim, sizeof ( dev_lim ) );
 
@@ -830,6 +935,7 @@ static int arbel_probe ( struct pci_device *pci,
 
        return 0;
 
+ err_query_dev_lim:
  err_register_netdev:
  err_ipoib_init:
        ib_driver_close ( 0 );
index 590d72f..85c60a0 100644 (file)
 
 /* uar context indexes */
 enum {
-       MADS_RCV_CQ_ARM_DB_IDX,
        MADS_SND_CQ_ARM_DB_IDX,
-       IPOIB_RCV_CQ_ARM_DB_IDX,
+       MADS_RCV_CQ_ARM_DB_IDX,
        IPOIB_SND_CQ_ARM_DB_IDX,
+       IPOIB_RCV_CQ_ARM_DB_IDX,
        MADS_SND_QP_DB_IDX,
        IPOIB_SND_QP_DB_IDX,
        GROUP_SEP_IDX,
@@ -158,12 +158,12 @@ enum {
           unmapped doorbell records
           -------------------------- */
        END_UNMAPPED_DB_IDX = 505,
-       MADS_RCV_QP_DB_IDX = 506,
-       IPOIB_RCV_QP_DB_IDX = 507,
-       MADS_RCV_CQ_CI_DB_IDX = 508,
-       MADS_SND_CQ_CI_DB_IDX = 509,
-       IPOIB_RCV_CQ_CI_DB_IDX = 510,
-       IPOIB_SND_CQ_CI_DB_IDX = 511
+       IPOIB_RCV_QP_DB_IDX = 506,
+       MADS_RCV_QP_DB_IDX = 507,
+       IPOIB_RCV_CQ_CI_DB_IDX = 508,
+       IPOIB_SND_CQ_CI_DB_IDX = 509,
+       MADS_RCV_CQ_CI_DB_IDX = 510,
+       MADS_SND_CQ_CI_DB_IDX = 511,
 };
 
 /* uar resources types */