@@ -610,6 +610,7 @@
case RDMA_NODE_RNIC: return sprintf(buf, "%d: RNIC\n", dev->node_type);
case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type);
+ case RDMA_NODE_MIC: return sprintf(buf, "%d: MIC\n", dev->node_type);
default: return sprintf(buf, "%d: <unknown>\n", dev->node_type);
}
}
@@ -101,7 +101,6 @@
if (!umem)
return ERR_PTR(-ENOMEM);
- umem->context = context;
umem->length = size;
umem->offset = addr & ~PAGE_MASK;
umem->page_size = PAGE_SIZE;
@@ -216,7 +215,6 @@
return ret < 0 ? ERR_PTR(ret) : umem;
}
-EXPORT_SYMBOL(ib_umem_get);
static void ib_umem_account(struct work_struct *work)
{
@@ -230,10 +228,10 @@
}
/**
- * ib_umem_release - release memory pinned with ib_umem_get
+ * ib_release_umem - release memory pinned with ib_umem_get
* @umem: umem struct to release
*/
-void ib_umem_release(struct ib_umem *umem)
+void ib_release_umem(struct ib_umem *umem)
{
struct ib_ucontext *context = umem->context;
struct mm_struct *mm;
@@ -274,9 +272,8 @@
mmput(mm);
kfree(umem);
}
-EXPORT_SYMBOL(ib_umem_release);
-int ib_umem_page_count(struct ib_umem *umem)
+int ib_page_count_umem(struct ib_umem *umem)
{
struct ib_umem_chunk *chunk;
int shift;
@@ -292,4 +289,40 @@
return n;
}
+
+struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+ size_t size, int access, int dmasync)
+{
+ struct ib_umem_ops *ops = context->umem_ops;
+ struct ib_umem *umem;
+
+ umem = (ops && ops->get) ?
+ ops->get(context, addr, size, access, dmasync) :
+ ib_get_umem(context, addr, size, access, dmasync);
+
+ if (!IS_ERR(umem))
+ umem->context = context;
+
+ return umem;
+}
+EXPORT_SYMBOL(ib_umem_get);
+
+void ib_umem_release(struct ib_umem *umem)
+{
+ struct ib_umem_ops *ops = umem->context->umem_ops;
+
+ if (ops && ops->release)
+ ops->release(umem);
+ else
+ ib_release_umem(umem);
+}
+EXPORT_SYMBOL(ib_umem_release);
+
+int ib_umem_page_count(struct ib_umem *umem)
+{
+ struct ib_umem_ops *ops = umem->context->umem_ops;
+
+ return (ops && ops->page_count) ?
+ ops->page_count(umem) : ib_page_count_umem(umem);
+}
EXPORT_SYMBOL(ib_umem_page_count);
@@ -54,8 +54,24 @@
static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
+static int uverbs_copy_from_udata(void *dest, struct ib_udata *udata, size_t len)
+{
+ return copy_from_user(dest, udata->inbuf, len) ? -EFAULT : 0;
+}
+
+static int uverbs_copy_to_udata(struct ib_udata *udata, void *src, size_t len)
+{
+ return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0;
+}
+
+static struct ib_udata_ops uverbs_copy = {
+ .copy_from = uverbs_copy_from_udata,
+ .copy_to = uverbs_copy_to_udata
+};
+
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do { \
+ (udata)->ops = &uverbs_copy; \
(udata)->inbuf = (void __user *) (ibuf); \
(udata)->outbuf = (void __user *) (obuf); \
(udata)->inlen = (ilen); \
@@ -321,6 +337,7 @@
goto err;
}
+ ucontext->umem_ops = NULL;
ucontext->device = ibdev;
INIT_LIST_HEAD(&ucontext->pd_list);
INIT_LIST_HEAD(&ucontext->mr_list);
@@ -114,6 +114,8 @@
return RDMA_TRANSPORT_IB;
case RDMA_NODE_RNIC:
return RDMA_TRANSPORT_IWARP;
+ case RDMA_NODE_MIC:
+ return RDMA_TRANSPORT_SCIF;
default:
BUG();
return 0;
@@ -39,6 +39,12 @@
#include <asm/page.h>
+/* Must use the ib_umem routines to support the IB proxy server. */
+#define MTHCA_IB_UMEM
+#ifdef MTHCA_IB_UMEM
+#include <rdma/ib_umem.h>
+#endif
+
#include "mthca_memfree.h"
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -56,7 +62,11 @@
struct mutex mutex;
struct {
u64 uvirt;
+#ifdef MTHCA_IB_UMEM
+ struct ib_umem *umem;
+#else
struct scatterlist mem;
+#endif
int refcount;
} page[0];
};
@@ -446,7 +456,12 @@
int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
struct mthca_user_db_table *db_tab, int index, u64 uaddr)
{
+#ifdef MTHCA_IB_UMEM
+ struct mthca_ucontext *context;
+ struct ib_umem_chunk *chunk;
+#else
struct page *pages[1];
+#endif
int ret = 0;
int i;
@@ -472,6 +487,22 @@
goto out;
}
+#ifdef MTHCA_IB_UMEM
+ context = container_of(uar, struct mthca_ucontext, uar);
+
+ db_tab->page[i].umem = ib_umem_get(&context->ibucontext,
+ uaddr & PAGE_MASK, PAGE_SIZE, 0, 0);
+ if (IS_ERR(db_tab->page[i].umem)) {
+ ret = PTR_ERR(db_tab->page[i].umem);
+ goto out;
+ }
+
+ chunk = list_entry(db_tab->page[i].umem->chunk_list.next,
+ struct ib_umem_chunk, list);
+
+ ret = mthca_MAP_ICM_page(dev, sg_dma_address(&chunk->page_list[0]),
+ mthca_uarc_virt(dev, uar, i));
+#else
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
pages, NULL);
if (ret < 0)
@@ -488,9 +519,14 @@
ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
mthca_uarc_virt(dev, uar, i));
+#endif
if (ret) {
+#ifdef MTHCA_IB_UMEM
+ ib_umem_release(db_tab->page[i].umem);
+#else
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
+#endif
goto out;
}
@@ -505,17 +541,29 @@
void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
struct mthca_user_db_table *db_tab, int index)
{
+#ifdef MTHCA_IB_UMEM
+ int i;
+#endif
if (!mthca_is_memfree(dev))
return;
+ mutex_lock(&db_tab->mutex);
+
+#ifdef MTHCA_IB_UMEM
+ i = index / MTHCA_DB_REC_PER_PAGE;
+ if (!--db_tab->page[i].refcount) {
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
+ ib_umem_release(db_tab->page[i].umem);
+ db_tab->page[i].uvirt = 0;
+ }
+#else
/*
* To make our bookkeeping simpler, we don't unmap DB
* pages until we clean up the whole db table.
*/
- mutex_lock(&db_tab->mutex);
-
--db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount;
+#endif
mutex_unlock(&db_tab->mutex);
}
@@ -538,7 +586,11 @@
for (i = 0; i < npages; ++i) {
db_tab->page[i].refcount = 0;
db_tab->page[i].uvirt = 0;
+#ifdef MTHCA_IB_UMEM
+ db_tab->page[i].umem = NULL;
+#else
sg_init_table(&db_tab->page[i].mem, 1);
+#endif
}
return db_tab;
@@ -555,8 +607,12 @@
for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
if (db_tab->page[i].uvirt) {
mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
+#ifdef MTHCA_IB_UMEM
+ ib_umem_release(db_tab->page[i].umem);
+#else
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
+#endif
}
}
@@ -67,12 +67,14 @@
RDMA_NODE_IB_CA = 1,
RDMA_NODE_IB_SWITCH,
RDMA_NODE_IB_ROUTER,
- RDMA_NODE_RNIC
+ RDMA_NODE_RNIC,
+ RDMA_NODE_MIC
};
enum rdma_transport_type {
RDMA_TRANSPORT_IB,
- RDMA_TRANSPORT_IWARP
+ RDMA_TRANSPORT_IWARP,
+ RDMA_TRANSPORT_SCIF
};
enum rdma_transport_type
@@ -82,6 +84,7 @@
IB_LINK_LAYER_UNSPECIFIED,
IB_LINK_LAYER_INFINIBAND,
IB_LINK_LAYER_ETHERNET,
+ IB_LINK_LAYER_SCIF
};
enum ib_device_cap_flags {
@@ -877,7 +880,18 @@
u8 page_shift;
};
+struct ib_ucontext;
+struct ib_umem_ops {
+ struct ib_umem *(*get)(struct ib_ucontext *context,
+ unsigned long addr, size_t size,
+ int access, int dmasync);
+ void (*release)(struct ib_umem *umem);
+ int (*page_count)(struct ib_umem *umem);
+};
+
struct ib_ucontext {
+ struct ib_umem_ops *umem_ops; /* set to NULL for default ops */
+ void *umem_private_data;
struct ib_device *device;
struct list_head pd_list;
struct list_head mr_list;
@@ -901,11 +915,20 @@
int live;
};
+struct ib_udata;
+struct ib_udata_ops {
+ int (*copy_from)(void *dest, struct ib_udata *udata,
+ size_t len);
+ int (*copy_to)(struct ib_udata *udata, void *src,
+ size_t len);
+};
+
struct ib_udata {
- void __user *inbuf;
- void __user *outbuf;
- size_t inlen;
- size_t outlen;
+ struct ib_udata_ops *ops;
+ void __user *inbuf;
+ void __user *outbuf;
+ size_t inlen;
+ size_t outlen;
};
struct ib_pd {
@@ -1281,12 +1304,12 @@
static inline int ib_copy_from_udata(void *dest, struct ib_udata *udata, size_t len)
{
- return copy_from_user(dest, udata->inbuf, len) ? -EFAULT : 0;
+ return udata->ops->copy_from(dest, udata, len);
}
static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len)
{
- return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0;
+ return udata->ops->copy_to(udata, src, len);
}
/**