summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/ehca/ehca_pd.c
diff options
context:
space:
mode:
authorStefan Roscher <stefan.roscher at de.ibm.com>2007-07-20 14:04:17 (GMT)
committerRoland Dreier <rolandd@cisco.com>2007-07-21 04:19:47 (GMT)
commite2f81daf23efde23d8cac1fc253d41838f0347cf (patch)
tree310c493f007cc10625426118eaf217e50dd978f3 /drivers/infiniband/hw/ehca/ehca_pd.c
parent0c10f7b79b5bb07a37aa5927072abdc3f45ac8d3 (diff)
downloadlinux-fsl-qoriq-e2f81daf23efde23d8cac1fc253d41838f0347cf.tar.xz
IB/ehca: Support small QP queues
eHCA2 supports QP queues that can be as small as 512 bytes. This greatly reduces memory overhead for consumers that use lots of QPs with small queues (e.g. RDMA-only QPs). Apart from dealing with firmware, this code needs to manage bite-sized chunks of kernel pages, making sure that no kernel page is shared between different protection domains. Signed-off-by: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_pd.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_pd.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
index c85312a..3dafd7f 100644
--- a/drivers/infiniband/hw/ehca/ehca_pd.c
+++ b/drivers/infiniband/hw/ehca/ehca_pd.c
@@ -49,6 +49,7 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
struct ib_ucontext *context, struct ib_udata *udata)
{
struct ehca_pd *pd;
+ int i;
pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL);
if (!pd) {
@@ -58,6 +59,11 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
}
pd->ownpid = current->tgid;
+ for (i = 0; i < 2; i++) {
+ INIT_LIST_HEAD(&pd->free[i]);
+ INIT_LIST_HEAD(&pd->full[i]);
+ }
+ mutex_init(&pd->lock);
/*
* Kernel PD: when device = -1, 0
@@ -81,6 +87,9 @@ int ehca_dealloc_pd(struct ib_pd *pd)
{
u32 cur_pid = current->tgid;
struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+ int i, leftovers = 0;
+ extern struct kmem_cache *small_qp_cache;
+ struct ipz_small_queue_page *page, *tmp;
if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
my_pd->ownpid != cur_pid) {
@@ -89,8 +98,20 @@ int ehca_dealloc_pd(struct ib_pd *pd)
return -EINVAL;
}
- kmem_cache_free(pd_cache,
- container_of(pd, struct ehca_pd, ib_pd));
+ for (i = 0; i < 2; i++) {
+ list_splice(&my_pd->full[i], &my_pd->free[i]);
+ list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
+ leftovers = 1;
+ free_page(page->page);
+ kmem_cache_free(small_qp_cache, page);
+ }
+ }
+
+ if (leftovers)
+ ehca_warn(pd->device,
+ "Some small queue pages were not freed");
+
+ kmem_cache_free(pd_cache, my_pd);
return 0;
}