[ofa-general] [PATCH 3/8 V2] mlx4: implement XRC qps (including XRC receive-only)
Jack Morgenstein
jackm at dev.mellanox.co.il
Mon Jan 28 02:36:36 PST 2008
mlx4: Implements XRC support for userspace XRC QPs.
Changes:
Added support for XRC RCV-only QP (requested by userspace,
but resides in kernel space).
V2 changes:
Added xrc_reg_mutex to the mlx4_ib_dev structure, since the qp mutex
was not sufficient to protect against a reg_xrc/unreg_xrc race.
Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
Index: infiniband/include/linux/mlx4/device.h
===================================================================
--- infiniband.orig/include/linux/mlx4/device.h 2008-01-28 10:56:29.000000000 +0200
+++ infiniband/include/linux/mlx4/device.h 2008-01-28 12:12:55.000000000 +0200
@@ -56,6 +56,7 @@ enum {
MLX4_DEV_CAP_FLAG_RC = 1 << 0,
MLX4_DEV_CAP_FLAG_UC = 1 << 1,
MLX4_DEV_CAP_FLAG_UD = 1 << 2,
+ MLX4_DEV_CAP_FLAG_XRC = 1 << 3,
MLX4_DEV_CAP_FLAG_SRQ = 1 << 6,
MLX4_DEV_CAP_FLAG_IPOIB_CSUM = 1 << 7,
MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR = 1 << 8,
@@ -176,6 +177,8 @@ struct mlx4_caps {
int num_pds;
int reserved_pds;
int mtt_entry_sz;
+ int reserved_xrcds;
+ int max_xrcds;
u32 max_msg_sz;
u32 page_size_cap;
u32 flags;
@@ -312,6 +315,9 @@ void mlx4_buf_free(struct mlx4_dev *dev,
int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn);
void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn);
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
+
int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar);
void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar);
@@ -336,8 +342,8 @@ void mlx4_cq_free(struct mlx4_dev *dev,
int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
- u64 db_rec, struct mlx4_srq *srq);
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
+ struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq);
void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
Index: infiniband/drivers/infiniband/hw/mlx4/main.c
===================================================================
--- infiniband.orig/drivers/infiniband/hw/mlx4/main.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/infiniband/hw/mlx4/main.c 2008-01-28 11:39:27.000000000 +0200
@@ -99,6 +99,8 @@ static int mlx4_ib_query_device(struct i
props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT)
props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
+ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+ props->device_cap_flags |= IB_DEVICE_XRC;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
@@ -406,6 +408,7 @@ static struct ib_pd *mlx4_ib_alloc_pd(st
if (!pd)
return ERR_PTR(-ENOMEM);
+ memset(pd, 0, sizeof *pd);
err = mlx4_pd_alloc(to_mdev(ibdev)->dev, &pd->pdn);
if (err) {
kfree(pd);
@@ -442,6 +445,80 @@ static int mlx4_ib_mcg_detach(struct ib_
&to_mqp(ibqp)->mqp, gid->raw);
}
+static void mlx4_dummy_comp_handler(struct ib_cq *cq, void *cq_context)
+{
+}
+
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct mlx4_ib_xrcd *xrcd;
+ struct mlx4_ib_dev *mdev = to_mdev(ibdev);
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+ int err;
+
+ if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
+
+ xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+ if (!xrcd)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx4_xrcd_alloc(mdev->dev, &xrcd->xrcdn);
+ if (err)
+ goto err_xrcd;
+
+ pd = mlx4_ib_alloc_pd(ibdev,NULL,NULL);
+ if (IS_ERR(pd)) {
+ err = PTR_ERR(pd);
+ goto err_pd;
+ }
+ pd->device = ibdev;
+
+ cq = mlx4_ib_create_cq(ibdev, 1, 0, NULL, NULL);
+ if (IS_ERR(cq)) {
+ err = PTR_ERR(cq);
+ goto err_cq;
+ }
+ cq->device = ibdev;
+ cq->comp_handler = mlx4_dummy_comp_handler;
+
+ if (context)
+ if (ib_copy_to_udata(udata, &xrcd->xrcdn, sizeof (__u32))) {
+ err = -EFAULT;
+ goto err_copy;
+ }
+
+ xrcd->cq = cq;
+ xrcd->pd = pd;
+ return &xrcd->ibxrcd;
+
+err_copy:
+ mlx4_ib_destroy_cq(cq);
+err_cq:
+ mlx4_ib_dealloc_pd(pd);
+err_pd:
+ mlx4_xrcd_free(mdev->dev, xrcd->xrcdn);
+err_xrcd:
+ kfree(xrcd);
+ return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+ struct mlx4_ib_xrcd *mxrcd = to_mxrcd(xrcd);
+
+ mlx4_ib_destroy_cq(mxrcd->cq);
+ mlx4_ib_dealloc_pd(mxrcd->pd);
+ mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+ kfree(xrcd);
+
+ return 0;
+}
+
+
static int init_node_data(struct mlx4_ib_dev *dev)
{
struct ib_smp *in_mad = NULL;
@@ -611,12 +688,32 @@ static void *mlx4_ib_add(struct mlx4_dev
ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr;
ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+ ibdev->ib_dev.create_xrc_srq = mlx4_ib_create_xrc_srq;
+ ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+ ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+ ibdev->ib_dev.create_xrc_rcv_qp = mlx4_ib_create_xrc_rcv_qp;
+ ibdev->ib_dev.modify_xrc_rcv_qp = mlx4_ib_modify_xrc_rcv_qp;
+ ibdev->ib_dev.query_xrc_rcv_qp = mlx4_ib_query_xrc_rcv_qp;
+ ibdev->ib_dev.reg_xrc_rcv_qp = mlx4_ib_reg_xrc_rcv_qp;
+ ibdev->ib_dev.unreg_xrc_rcv_qp = mlx4_ib_unreg_xrc_rcv_qp;
+ ibdev->ib_dev.uverbs_cmd_mask |=
+ (1ull << IB_USER_VERBS_CMD_CREATE_XRC_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN) |
+ (1ull << IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_XRC_RCV_QP) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_XRC_RCV_QP) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_XRC_RCV_QP) |
+ (1ull << IB_USER_VERBS_CMD_REG_XRC_RCV_QP) |
+ (1ull << IB_USER_VERBS_CMD_UNREG_XRC_RCV_QP);
+ }
if (init_node_data(ibdev))
goto err_map;
spin_lock_init(&ibdev->sm_lock);
mutex_init(&ibdev->cap_mask_mutex);
+ mutex_init(&ibdev->xrc_reg_mutex);
if (ib_register_device(&ibdev->ib_dev))
goto err_map;
Index: infiniband/drivers/infiniband/hw/mlx4/mlx4_ib.h
===================================================================
--- infiniband.orig/drivers/infiniband/hw/mlx4/mlx4_ib.h 2008-01-28 10:56:29.000000000 +0200
+++ infiniband/drivers/infiniband/hw/mlx4/mlx4_ib.h 2008-01-28 11:38:46.000000000 +0200
@@ -73,6 +73,13 @@ struct mlx4_ib_pd {
u32 pdn;
};
+struct mlx4_ib_xrcd {
+ struct ib_xrcd ibxrcd;
+ u32 xrcdn;
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+};
+
struct mlx4_ib_cq_buf {
struct mlx4_buf buf;
struct mlx4_mtt mtt;
@@ -127,6 +134,9 @@ struct mlx4_ib_qp {
struct mlx4_mtt mtt;
int buf_size;
struct mutex mutex;
+ enum qp_create_flags create_flags;
+ struct list_head xrc_reg_list;
+ u16 xrcdn;
u8 port;
u8 alt_port;
u8 atomic_rd_en;
@@ -172,6 +182,7 @@ struct mlx4_ib_dev {
spinlock_t sm_lock;
struct mutex cap_mask_mutex;
+ struct mutex xrc_reg_mutex;
};
static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
@@ -189,6 +200,11 @@ static inline struct mlx4_ib_pd *to_mpd(
return container_of(ibpd, struct mlx4_ib_pd, ibpd);
}
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+ return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct mlx4_ib_cq, ibcq);
@@ -263,6 +279,11 @@ int mlx4_ib_destroy_ah(struct ib_ah *ah)
struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
struct ib_srq_init_attr *init_attr,
struct ib_udata *udata);
+struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
+ struct ib_cq *xrc_cq,
+ struct ib_xrcd *xrcd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata);
int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
int mlx4_ib_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
@@ -299,6 +320,16 @@ int mlx4_ib_map_phys_fmr(struct ib_fmr *
u64 iova);
int mlx4_ib_unmap_fmr(struct list_head *fmr_list);
int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr);
+int mlx4_ib_create_xrc_rcv_qp(struct ib_qp_init_attr *init_attr,
+ u32 *qp_num);
+int mlx4_ib_modify_xrc_rcv_qp(struct ib_xrcd *xrcd, u32 qp_num,
+ struct ib_qp_attr *attr, int attr_mask);
+int mlx4_ib_query_xrc_rcv_qp(struct ib_xrcd *xrcd, u32 qp_num,
+ struct ib_qp_attr *attr, int attr_mask,
+ struct ib_qp_init_attr *init_attr);
+int mlx4_ib_reg_xrc_rcv_qp(struct ib_xrcd *xrcd, void * context, u32 qp_num);
+int mlx4_ib_unreg_xrc_rcv_qp(struct ib_xrcd *xrcd, void * context, u32 qp_num);
+
static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah)
{
Index: infiniband/drivers/net/mlx4/xrcd.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ infiniband/drivers/net/mlx4/xrcd.c 2008-01-28 10:56:59.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include "mlx4.h"
+
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap);
+ if (*xrcdn == -1)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
+
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
+{
+ mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
+
+int __devinit mlx4_init_xrcd_table(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16),
+ (1 << 16) - 1, dev->caps.reserved_xrcds + 1);
+}
+
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev)
+{
+ mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap);
+}
+
+
Index: infiniband/drivers/net/mlx4/mlx4.h
===================================================================
--- infiniband.orig/drivers/net/mlx4/mlx4.h 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/mlx4.h 2008-01-28 12:12:55.000000000 +0200
@@ -260,6 +260,7 @@ struct mlx4_priv {
struct mlx4_cmd cmd;
struct mlx4_bitmap pd_bitmap;
+ struct mlx4_bitmap xrcd_bitmap;
struct mlx4_uar_table uar_table;
struct mlx4_mr_table mr_table;
struct mlx4_cq_table cq_table;
@@ -289,6 +290,7 @@ void mlx4_bitmap_cleanup(struct mlx4_bit
int mlx4_reset(struct mlx4_dev *dev);
int mlx4_init_pd_table(struct mlx4_dev *dev);
+int mlx4_init_xrcd_table(struct mlx4_dev *dev);
int mlx4_init_uar_table(struct mlx4_dev *dev);
int mlx4_init_mr_table(struct mlx4_dev *dev);
int mlx4_init_eq_table(struct mlx4_dev *dev);
@@ -305,6 +307,7 @@ void mlx4_cleanup_cq_table(struct mlx4_d
void mlx4_cleanup_qp_table(struct mlx4_dev *dev);
void mlx4_cleanup_srq_table(struct mlx4_dev *dev);
void mlx4_cleanup_mcg_table(struct mlx4_dev *dev);
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev);
void mlx4_start_catas_poll(struct mlx4_dev *dev);
void mlx4_stop_catas_poll(struct mlx4_dev *dev);
Index: infiniband/drivers/net/mlx4/main.c
===================================================================
--- infiniband.orig/drivers/net/mlx4/main.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/main.c 2008-01-28 10:56:59.000000000 +0200
@@ -159,6 +159,10 @@ static int mlx4_dev_cap(struct mlx4_dev
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
+ dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+ dev_cap->reserved_xrcds : 0;
+ dev->caps.max_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+ dev_cap->max_xrcds : 0;
return 0;
}
@@ -586,11 +590,18 @@ static int mlx4_setup_hca(struct mlx4_de
goto err_kar_unmap;
}
+ err = mlx4_init_xrcd_table(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to initialize "
+ "extended reliably connected domain table, aborting.\n");
+ goto err_pd_table_free;
+ }
+
err = mlx4_init_mr_table(dev);
if (err) {
mlx4_err(dev, "Failed to initialize "
"memory region table, aborting.\n");
- goto err_pd_table_free;
+ goto err_xrcd_table_free;
}
err = mlx4_init_eq_table(dev);
@@ -674,6 +685,9 @@ err_eq_table_free:
err_mr_table_free:
mlx4_cleanup_mr_table(dev);
+err_xrcd_table_free:
+ mlx4_cleanup_xrcd_table(dev);
+
err_pd_table_free:
mlx4_cleanup_pd_table(dev);
@@ -847,6 +861,7 @@ err_cleanup:
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
+ mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
mlx4_cleanup_uar_table(dev);
@@ -906,6 +921,7 @@ static void mlx4_remove_one(struct pci_d
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
+ mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
iounmap(priv->kar);
Index: infiniband/drivers/net/mlx4/srq.c
===================================================================
--- infiniband.orig/drivers/net/mlx4/srq.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/srq.c 2008-01-28 12:12:55.000000000 +0200
@@ -40,20 +40,20 @@
struct mlx4_srq_context {
__be32 state_logsize_srqn;
u8 logstride;
- u8 reserved1[3];
- u8 pg_offset;
- u8 reserved2[3];
- u32 reserved3;
+ u8 reserved1;
+ __be16 xrc_domain;
+ __be32 pg_offset_cqn;
+ u32 reserved2;
u8 log_page_size;
- u8 reserved4[2];
+ u8 reserved3[2];
u8 mtt_base_addr_h;
__be32 mtt_base_addr_l;
__be32 pd;
__be16 limit_watermark;
__be16 wqe_cnt;
- u16 reserved5;
+ u16 reserved4;
__be16 wqe_counter;
- u32 reserved6;
+ u32 reserved5;
__be64 db_rec_addr;
};
@@ -109,8 +109,8 @@ static int mlx4_QUERY_SRQ(struct mlx4_de
MLX4_CMD_TIME_CLASS_A);
}
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
- u64 db_rec, struct mlx4_srq *srq)
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
+ struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
{
struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
struct mlx4_cmd_mailbox *mailbox;
@@ -148,6 +148,8 @@ int mlx4_srq_alloc(struct mlx4_dev *dev,
srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
srq->srqn);
srq_context->logstride = srq->wqe_shift - 4;
+ srq_context->xrc_domain = cpu_to_be16(xrcd);
+ srq_context->pg_offset_cqn = cpu_to_be32(cqn & 0xffffff);
srq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
mtt_addr = mlx4_mtt_addr(dev, mtt);
Index: infiniband/drivers/net/mlx4/fw.c
===================================================================
--- infiniband.orig/drivers/net/mlx4/fw.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/fw.c 2008-01-28 10:56:59.000000000 +0200
@@ -159,6 +159,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63
#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64
#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65
+#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
+#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
@@ -262,6 +264,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
dev_cap->max_pds = 1 << (field & 0x3f);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
+ dev_cap->reserved_xrcds = field >> 4;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET);
+ dev_cap->max_xrcds = 1 << (field & 0x1f);
+
MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
dev_cap->rdmarc_entry_sz = size;
MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET);
Index: infiniband/drivers/net/mlx4/fw.h
===================================================================
--- infiniband.orig/drivers/net/mlx4/fw.h 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/fw.h 2008-01-28 10:56:59.000000000 +0200
@@ -82,6 +82,8 @@ struct mlx4_dev_cap {
int max_mcgs;
int reserved_pds;
int max_pds;
+ int reserved_xrcds;
+ int max_xrcds;
int qpc_entry_sz;
int rdmarc_entry_sz;
int altc_entry_sz;
Index: infiniband/drivers/infiniband/hw/mlx4/qp.c
===================================================================
--- infiniband.orig/drivers/infiniband/hw/mlx4/qp.c 2008-01-28 10:56:29.000000000 +0200
+++ infiniband/drivers/infiniband/hw/mlx4/qp.c 2008-01-28 12:20:46.000000000 +0200
@@ -54,6 +54,12 @@ enum {
MLX4_IB_UD_HEADER_SIZE = 72
};
+
+struct mlx4_ib_xrc_reg_entry {
+ struct list_head list;
+ void *context;
+};
+
struct mlx4_ib_sqp {
struct mlx4_ib_qp qp;
int pkey_index;
@@ -130,14 +136,15 @@ static void stamp_send_wqe(struct mlx4_i
static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
{
struct ib_event event;
- struct ib_qp *ibqp = &to_mibqp(qp)->ibqp;
+ struct mlx4_ib_qp *mqp = to_mibqp(qp);
+ struct ib_qp *ibqp = &mqp->ibqp;
+ struct mlx4_ib_xrc_reg_entry *ctx_entry;
if (type == MLX4_EVENT_TYPE_PATH_MIG)
to_mibqp(qp)->port = to_mibqp(qp)->alt_port;
if (ibqp->event_handler) {
event.device = ibqp->device;
- event.element.qp = ibqp;
switch (type) {
case MLX4_EVENT_TYPE_PATH_MIG:
event.event = IB_EVENT_PATH_MIG;
@@ -169,7 +176,16 @@ static void mlx4_ib_qp_event(struct mlx4
return;
}
- ibqp->event_handler(&event, ibqp->qp_context);
+ if (!(ibqp->qp_type == IB_QPT_XRC &&
+ mqp->create_flags & XRC_RCV_QP)) {
+ event.element.qp = ibqp;
+ ibqp->event_handler(&event, ibqp->qp_context);
+ } else {
+ event.event |= IB_XRC_QP_EVENT_FLAG;
+ event.element.xrc_qp_num = ibqp->qp_num;
+ list_for_each_entry(ctx_entry, &mqp->xrc_reg_list, list)
+ ibqp->event_handler(&event, ctx_entry->context);
+ }
}
}
@@ -209,14 +225,14 @@ static int send_wqe_overhead(enum ib_qp_
}
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
- int is_user, int has_srq, struct mlx4_ib_qp *qp)
+ int is_user, int has_srq_or_is_xrc, struct mlx4_ib_qp *qp)
{
/* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL;
- if (has_srq) {
+ if (has_srq_or_is_xrc) {
/* QPs attached to an SRQ should have no RQ */
if (cap->max_recv_wr)
return -EINVAL;
@@ -328,7 +344,8 @@ static int create_qp_common(struct mlx4_
qp->sq.head = 0;
qp->sq.tail = 0;
- err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+ err = set_rq_size(dev, &init_attr->cap, !!pd->uobject,
+ !!init_attr->srq || !!init_attr->xrc_domain , qp);
if (err)
goto err;
@@ -362,7 +379,7 @@ static int create_qp_common(struct mlx4_
if (err)
goto err_mtt;
- if (!init_attr->srq) {
+ if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC) {
err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
ucmd.db_addr, &qp->db);
if (err)
@@ -375,7 +392,7 @@ static int create_qp_common(struct mlx4_
if (err)
goto err;
- if (!init_attr->srq) {
+ if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC) {
err = mlx4_ib_db_alloc(dev, &qp->db, 0);
if (err)
goto err;
@@ -410,6 +427,9 @@ static int create_qp_common(struct mlx4_
if (err)
goto err_wrid;
+ if (init_attr->qp_type == IB_QPT_XRC)
+ qp->mqp.qpn |= (1 << 23);
+
/*
* Hardware wants QPN written in big-endian order (after
* shifting) for send doorbell. Precompute this value to save
@@ -428,7 +448,7 @@ static int create_qp_common(struct mlx4_
err_wrid:
if (pd->uobject) {
- if (!init_attr->srq)
+ if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC)
mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
&qp->db);
} else {
@@ -446,7 +466,7 @@ err_buf:
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
err_db:
- if (!pd->uobject && !init_attr->srq)
+ if (!pd->uobject && !init_attr->srq && init_attr->qp_type != IB_QPT_XRC)
mlx4_ib_db_free(dev, &qp->db);
err:
@@ -524,7 +544,7 @@ static void destroy_qp_common(struct mlx
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) {
- if (!qp->ibqp.srq)
+ if (!qp->ibqp.srq && qp->ibqp.qp_type != IB_QPT_XRC)
mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
&qp->db);
ib_umem_release(qp->umem);
@@ -532,7 +552,7 @@ static void destroy_qp_common(struct mlx
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
- if (!qp->ibqp.srq)
+ if (!qp->ibqp.srq && qp->ibqp.qp_type != IB_QPT_XRC)
mlx4_ib_db_free(dev, &qp->db);
}
}
@@ -547,6 +567,9 @@ struct ib_qp *mlx4_ib_create_qp(struct i
int err;
switch (init_attr->qp_type) {
+ case IB_QPT_XRC:
+ if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
case IB_QPT_RC:
case IB_QPT_UC:
case IB_QPT_UD:
@@ -555,12 +578,20 @@ struct ib_qp *mlx4_ib_create_qp(struct i
if (!qp)
return ERR_PTR(-ENOMEM);
+ memset(qp, 0, sizeof *qp);
+ INIT_LIST_HEAD(&qp->xrc_reg_list);
+ qp->create_flags = init_attr->create_flags;
err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
if (err) {
kfree(qp);
return ERR_PTR(err);
}
+ if (init_attr->qp_type == IB_QPT_XRC)
+ qp->xrcdn = to_mxrcd(init_attr->xrc_domain)->xrcdn;
+ else
+ qp->xrcdn = 0;
+
qp->ibqp.qp_num = qp->mqp.qpn;
break;
@@ -625,6 +656,7 @@ static int to_mlx4_st(enum ib_qp_type ty
case IB_QPT_RC: return MLX4_QP_ST_RC;
case IB_QPT_UC: return MLX4_QP_ST_UC;
case IB_QPT_UD: return MLX4_QP_ST_UD;
+ case IB_QPT_XRC: return MLX4_QP_ST_XRC;
case IB_QPT_SMI:
case IB_QPT_GSI: return MLX4_QP_ST_MLX;
default: return -1;
@@ -769,8 +801,11 @@ static int __mlx4_ib_modify_qp(struct ib
context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4;
- if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+ if (ibqp->qp_type == IB_QPT_XRC)
+ context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+ }
if (qp->ibqp.uobject)
context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -882,7 +917,8 @@ static int __mlx4_ib_modify_qp(struct ib
if (ibqp->srq)
context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
- if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (!ibqp->srq && ibqp->qp_type != IB_QPT_XRC &&
+ cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
context->db_rec_addr = cpu_to_be64(qp->db.dma);
if (cur_state == IB_QPS_INIT &&
@@ -969,7 +1005,7 @@ static int __mlx4_ib_modify_qp(struct ib
qp->rq.tail = 0;
qp->sq.head = 0;
qp->sq.tail = 0;
- if (!ibqp->srq)
+ if (!ibqp->srq && ibqp->qp_type != IB_QPT_XRC)
*qp->db.db = 0;
}
@@ -1662,3 +1698,260 @@ done:
return 0;
}
+int mlx4_ib_create_xrc_rcv_qp(struct ib_qp_init_attr *init_attr,
+ u32 *qp_num)
+{
+ struct mlx4_ib_dev *dev = to_mdev(init_attr->xrc_domain->device);
+ struct mlx4_ib_xrcd *xrcd = to_mxrcd(init_attr->xrc_domain);
+ struct ib_qp_init_attr ia = *init_attr;
+ struct mlx4_ib_qp *qp;
+ struct ib_qp *ibqp;
+ struct mlx4_ib_xrc_reg_entry *ctx_entry;
+
+ if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return -ENOSYS;
+
+ ctx_entry = kmalloc(sizeof *ctx_entry, GFP_KERNEL);
+ if (!ctx_entry)
+ return -ENOMEM;
+
+ ia.qp_type = IB_QPT_XRC;
+ ia.create_flags = XRC_RCV_QP;
+ ia.recv_cq = ia.send_cq = xrcd->cq;
+
+ ibqp = mlx4_ib_create_qp(xrcd->pd, &ia, NULL);
+ if (IS_ERR(ibqp)) {
+ kfree(ctx_entry);
+ return PTR_ERR(ibqp);
+ }
+
+ /* set the ibpq attributes which will be used by the mlx4 module */
+ ibqp->device = init_attr->xrc_domain->device;
+ ibqp->pd = xrcd->pd;
+ ibqp->send_cq = ibqp->recv_cq = xrcd->cq;
+ ibqp->event_handler = init_attr->event_handler;
+ ibqp->qp_context = init_attr->qp_context;
+ ibqp->qp_type = init_attr->qp_type;
+ ibqp->xrcd = init_attr->xrc_domain;
+
+ qp = to_mqp(ibqp);
+
+ mutex_lock(&qp->mutex);
+ ctx_entry->context = init_attr->qp_context;
+ list_add_tail(&ctx_entry->list, &qp->xrc_reg_list);
+ mutex_unlock(&qp->mutex);
+ *qp_num = qp->mqp.qpn;
+ return 0;
+}
+
+int mlx4_ib_modify_xrc_rcv_qp(struct ib_xrcd *ibxrcd, u32 qp_num,
+ struct ib_qp_attr *attr, int attr_mask)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibxrcd->device);
+ struct mlx4_ib_xrcd *xrcd = to_mxrcd(ibxrcd);
+ struct mlx4_qp *mqp;
+ int err;
+
+ if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return -ENOSYS;
+
+ mqp = __mlx4_qp_lookup(dev->dev, qp_num);
+ if (unlikely(!mqp)) {
+ printk(KERN_WARNING "mlx4_ib_reg_xrc_rcv_qp: unknown QPN %06x\n",
+ qp_num);
+ return -EINVAL;
+ }
+
+ if (xrcd->xrcdn != to_mxrcd(to_mibqp(mqp)->ibqp.xrcd)->xrcdn)
+ return -EINVAL;
+
+ err = mlx4_ib_modify_qp(&(to_mibqp(mqp)->ibqp), attr, attr_mask, NULL);
+ return err;
+}
+
+int mlx4_ib_query_xrc_rcv_qp(struct ib_xrcd *ibxrcd, u32 qp_num,
+ struct ib_qp_attr *qp_attr, int qp_attr_mask,
+ struct ib_qp_init_attr *qp_init_attr)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibxrcd->device);
+ struct mlx4_ib_xrcd *xrcd = to_mxrcd(ibxrcd);
+ struct mlx4_ib_qp *qp;
+ struct mlx4_qp *mqp;
+ struct mlx4_qp_context context;
+ int mlx4_state;
+ int err;
+
+ if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return -ENOSYS;
+
+ mqp = __mlx4_qp_lookup(dev->dev, qp_num);
+ if (unlikely(!mqp)) {
+ printk(KERN_WARNING "mlx4_ib_reg_xrc_rcv_qp: unknown QPN %06x\n",
+ qp_num);
+ return -EINVAL;
+ }
+
+ qp = to_mibqp(mqp);
+ if (xrcd->xrcdn != to_mxrcd(qp->ibqp.xrcd)->xrcdn)
+ return -EINVAL;
+
+ if (qp->state == IB_QPS_RESET) {
+ qp_attr->qp_state = IB_QPS_RESET;
+ goto done;
+ }
+
+ err = mlx4_qp_query(dev->dev, mqp, &context);
+ if (err)
+ return -EINVAL;
+
+ mlx4_state = be32_to_cpu(context.flags) >> 28;
+
+ qp_attr->qp_state = to_ib_qp_state(mlx4_state);
+ qp_attr->path_mtu = context.mtu_msgmax >> 5;
+ qp_attr->path_mig_state =
+ to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+ qp_attr->qkey = be32_to_cpu(context.qkey);
+ qp_attr->rq_psn = be32_to_cpu(context.rnr_nextrecvpsn) & 0xffffff;
+ qp_attr->sq_psn = be32_to_cpu(context.next_send_psn) & 0xffffff;
+ qp_attr->dest_qp_num = be32_to_cpu(context.remote_qpn) & 0xffffff;
+ qp_attr->qp_access_flags =
+ to_ib_qp_access_flags(be32_to_cpu(context.params2));
+
+ if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC ||
+ qp->ibqp.qp_type == IB_QPT_XRC) {
+ to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
+ to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+ qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
+ qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num;
+ }
+
+ qp_attr->pkey_index = context.pri_path.pkey_index & 0x7f;
+ if (qp_attr->qp_state == IB_QPS_INIT)
+ qp_attr->port_num = qp->port;
+ else
+ qp_attr->port_num = context.pri_path.sched_queue & 0x40 ? 2 : 1;
+
+ /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
+ qp_attr->sq_draining = mlx4_state == MLX4_QP_STATE_SQ_DRAINING;
+
+ qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context.params1) >> 21) & 0x7);
+
+ qp_attr->max_dest_rd_atomic =
+ 1 << ((be32_to_cpu(context.params2) >> 21) & 0x7);
+ qp_attr->min_rnr_timer =
+ (be32_to_cpu(context.rnr_nextrecvpsn) >> 24) & 0x1f;
+ qp_attr->timeout = context.pri_path.ackto >> 3;
+ qp_attr->retry_cnt = (be32_to_cpu(context.params1) >> 16) & 0x7;
+ qp_attr->rnr_retry = (be32_to_cpu(context.params1) >> 13) & 0x7;
+ qp_attr->alt_timeout = context.alt_path.ackto >> 3;
+
+done:
+ qp_attr->cur_qp_state = qp_attr->qp_state;
+ qp_attr->cap.max_recv_wr = 0;
+ qp_attr->cap.max_recv_sge = 0;
+ qp_attr->cap.max_send_wr = 0;
+ qp_attr->cap.max_send_sge = 0;
+ qp_attr->cap.max_inline_data = 0;
+ qp_init_attr->cap = qp_attr->cap;
+
+ return 0;
+}
+
+int mlx4_ib_reg_xrc_rcv_qp(struct ib_xrcd *xrcd, void *context, u32 qp_num)
+{
+
+ struct mlx4_ib_xrcd *mxrcd = to_mxrcd(xrcd);
+
+ struct mlx4_qp *mqp;
+ struct mlx4_ib_qp *mibqp;
+ struct mlx4_ib_xrc_reg_entry *ctx_entry, *tmp;
+ int err = -EINVAL;
+
+ mutex_lock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ mqp = __mlx4_qp_lookup(to_mdev(xrcd->device)->dev, qp_num);
+ if (unlikely(!mqp)) {
+ printk(KERN_WARNING "mlx4_ib_reg_xrc_rcv_qp: unknown QPN %06x\n",
+ qp_num);
+ goto err_out;
+ }
+
+ mibqp = to_mibqp(mqp);
+
+ if (mxrcd->xrcdn != to_mxrcd(mibqp->ibqp.xrcd)->xrcdn)
+ goto err_out;
+
+ ctx_entry = kmalloc(sizeof *ctx_entry, GFP_KERNEL);
+ if (!ctx_entry) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ mutex_lock(&mibqp->mutex);
+ list_for_each_entry(tmp, &mibqp->xrc_reg_list, list)
+ if (tmp->context == context) {
+ mutex_unlock(&mibqp->mutex);
+ kfree(ctx_entry);
+ mutex_unlock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ return 0;
+ }
+
+ ctx_entry->context = context;
+ list_add_tail(&ctx_entry->list, &mibqp->xrc_reg_list);
+ mutex_unlock(&mibqp->mutex);
+ mutex_unlock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ return 0;
+
+err_out:
+ mutex_unlock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ return err;
+}
+
+int mlx4_ib_unreg_xrc_rcv_qp(struct ib_xrcd *xrcd, void *context, u32 qp_num)
+{
+
+ struct mlx4_ib_xrcd *mxrcd = to_mxrcd(xrcd);
+
+ struct mlx4_qp *mqp;
+ struct mlx4_ib_qp *mibqp;
+ struct mlx4_ib_xrc_reg_entry *ctx_entry, *tmp;
+ int found = 0;
+ int err = -EINVAL;
+
+ mutex_lock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ mqp = __mlx4_qp_lookup(to_mdev(xrcd->device)->dev, qp_num);
+ if (unlikely(!mqp)) {
+ printk(KERN_WARNING "mlx4_ib_unreg_xrc_rcv_qp: unknown QPN %06x\n",
+ qp_num);
+ goto err_out;
+ }
+
+ mibqp = to_mibqp(mqp);
+
+ if (mxrcd->xrcdn != (mibqp->xrcdn & 0xffff))
+ goto err_out;
+
+ mutex_lock(&mibqp->mutex);
+ list_for_each_entry_safe(ctx_entry, tmp, &mibqp->xrc_reg_list, list)
+ if (ctx_entry->context == context) {
+ found = 1;
+ list_del(&ctx_entry->list);
+ kfree(ctx_entry);
+ break;
+ }
+
+ mutex_unlock(&mibqp->mutex);
+ if (!found)
+ goto err_out;
+
+ /* destroy the QP if the registration list is empty */
+ if (list_empty(&mibqp->xrc_reg_list))
+ mlx4_ib_destroy_qp(&mibqp->ibqp);
+
+ mutex_unlock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ return 0;
+
+err_out:
+ mutex_unlock(&to_mdev(xrcd->device)->xrc_reg_mutex);
+ return err;
+}
+
Index: infiniband/drivers/infiniband/hw/mlx4/srq.c
===================================================================
--- infiniband.orig/drivers/infiniband/hw/mlx4/srq.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/infiniband/hw/mlx4/srq.c 2008-01-28 12:12:55.000000000 +0200
@@ -72,13 +72,17 @@ static void mlx4_ib_srq_event(struct mlx
}
}
-struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
- struct ib_srq_init_attr *init_attr,
- struct ib_udata *udata)
+struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
+ struct ib_cq *xrc_cq,
+ struct ib_xrcd *xrcd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata)
{
struct mlx4_ib_dev *dev = to_mdev(pd->device);
struct mlx4_ib_srq *srq;
struct mlx4_wqe_srq_next_seg *next;
+ u32 cqn;
+ u16 xrcdn;
int desc_size;
int buf_size;
int err;
@@ -172,7 +176,11 @@ struct ib_srq *mlx4_ib_create_srq(struct
}
}
- err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+ cqn = xrc_cq ? (u32) (to_mcq(xrc_cq)->mcq.cqn) : 0;
+ xrcdn = xrcd ? (u16) (to_mxrcd(xrcd)->xrcdn) :
+ (u16) dev->dev->caps.reserved_xrcds;
+
+ err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
srq->db.dma, &srq->msrq);
if (err)
goto err_wrid;
@@ -240,6 +248,13 @@ int mlx4_ib_modify_srq(struct ib_srq *ib
return 0;
}
+struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ return mlx4_ib_create_xrc_srq(pd, NULL, NULL, init_attr, udata);
+}
+
int mlx4_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
{
struct mlx4_ib_dev *dev = to_mdev(ibsrq->device);
Index: infiniband/include/linux/mlx4/qp.h
===================================================================
--- infiniband.orig/include/linux/mlx4/qp.h 2008-01-28 10:56:29.000000000 +0200
+++ infiniband/include/linux/mlx4/qp.h 2008-01-28 10:56:59.000000000 +0200
@@ -74,6 +74,7 @@ enum {
MLX4_QP_ST_UC = 0x1,
MLX4_QP_ST_RD = 0x2,
MLX4_QP_ST_UD = 0x3,
+ MLX4_QP_ST_XRC = 0x6,
MLX4_QP_ST_MLX = 0x7
};
@@ -136,7 +137,7 @@ struct mlx4_qp_context {
__be32 ssn;
__be32 params2;
__be32 rnr_nextrecvpsn;
- __be32 srcd;
+ __be32 xrcd;
__be32 cqn_recv;
__be64 db_rec_addr;
__be32 qkey;
Index: infiniband/drivers/net/mlx4/Makefile
===================================================================
--- infiniband.orig/drivers/net/mlx4/Makefile 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/Makefile 2008-01-28 10:56:59.000000000 +0200
@@ -1,4 +1,4 @@
obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
- mr.o pd.o profile.o qp.o reset.o srq.o
+ mr.o pd.o profile.o qp.o reset.o srq.o xrcd.o
Index: infiniband/drivers/net/mlx4/qp.c
===================================================================
--- infiniband.orig/drivers/net/mlx4/qp.c 2008-01-27 10:44:25.000000000 +0200
+++ infiniband/drivers/net/mlx4/qp.c 2008-01-28 10:56:59.000000000 +0200
@@ -263,10 +263,12 @@ int mlx4_init_qp_table(struct mlx4_dev *
* We reserve 2 extra QPs per port for the special QPs. The
* block of special QPs must be aligned to a multiple of 8, so
* round up.
+ * We also reserve the MSB of the 24-bit QP number to indicate
+ * an XRC qp.
*/
dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8);
err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
- (1 << 24) - 1, dev->caps.sqp_start + 8);
+ (1 << 23) - 1, dev->caps.sqp_start + 8);
if (err)
return err;
Index: infiniband/drivers/infiniband/hw/mlx4/cq.c
===================================================================
--- infiniband.orig/drivers/infiniband/hw/mlx4/cq.c 2008-01-28 10:56:29.000000000 +0200
+++ infiniband/drivers/infiniband/hw/mlx4/cq.c 2008-01-28 12:12:55.000000000 +0200
@@ -108,6 +108,7 @@ struct ib_cq *mlx4_ib_create_cq(struct i
if (!cq)
return ERR_PTR(-ENOMEM);
+ memset(cq, 0, sizeof *cq);
entries = roundup_pow_of_two(entries + 1);
cq->ibcq.cqe = entries - 1;
buf_size = entries * sizeof (struct mlx4_cqe);
More information about the general
mailing list