Path: blob/master/drivers/infiniband/hw/ehca/ehca_pd.c
15112 views
/*1* IBM eServer eHCA Infiniband device driver for Linux on POWER2*3* PD functions4*5* Authors: Christoph Raisch <[email protected]>6*7* Copyright (c) 2005 IBM Corporation8*9* All rights reserved.10*11* This source code is distributed under a dual license of GPL v2.0 and OpenIB12* BSD.13*14* OpenIB BSD License15*16* Redistribution and use in source and binary forms, with or without17* modification, are permitted provided that the following conditions are met:18*19* Redistributions of source code must retain the above copyright notice, this20* list of conditions and the following disclaimer.21*22* Redistributions in binary form must reproduce the above copyright notice,23* this list of conditions and the following disclaimer in the documentation24* and/or other materials25* provided with the distribution.26*27* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"28* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE29* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE30* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE31* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR32* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF33* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR34* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER35* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)36* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE37* POSSIBILITY OF SUCH DAMAGE.38*/3940#include <linux/slab.h>4142#include "ehca_tools.h"43#include "ehca_iverbs.h"4445static struct kmem_cache *pd_cache;4647struct ib_pd *ehca_alloc_pd(struct ib_device *device,48struct ib_ucontext *context, struct ib_udata *udata)49{50struct ehca_pd *pd;51int i;5253pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL);54if (!pd) {55ehca_err(device, "device=%p context=%p out of memory",56device, context);57return ERR_PTR(-ENOMEM);58}5960for (i = 0; i < 2; i++) {61INIT_LIST_HEAD(&pd->free[i]);62INIT_LIST_HEAD(&pd->full[i]);63}64mutex_init(&pd->lock);6566/*67* Kernel PD: when device = -1, 068* User PD: when context != -169*/70if (!context) {71/*72* Kernel PDs after init reuses always73* the one created in ehca_shca_reopen()74*/75struct ehca_shca *shca = container_of(device, struct ehca_shca,76ib_device);77pd->fw_pd.value = shca->pd->fw_pd.value;78} else79pd->fw_pd.value = (u64)pd;8081return &pd->ib_pd;82}8384int ehca_dealloc_pd(struct ib_pd *pd)85{86struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);87int i, leftovers = 0;88struct ipz_small_queue_page *page, *tmp;8990for (i = 0; i < 2; i++) {91list_splice(&my_pd->full[i], &my_pd->free[i]);92list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {93leftovers = 1;94free_page(page->page);95kmem_cache_free(small_qp_cache, page);96}97}9899if (leftovers)100ehca_warn(pd->device,101"Some small queue pages were not freed");102103kmem_cache_free(pd_cache, my_pd);104105return 0;106}107108int ehca_init_pd_cache(void)109{110pd_cache = kmem_cache_create("ehca_cache_pd",111sizeof(struct ehca_pd), 0,112SLAB_HWCACHE_ALIGN,113NULL);114if (!pd_cache)115return -ENOMEM;116return 0;117}118119void ehca_cleanup_pd_cache(void)120{121if (pd_cache)122kmem_cache_destroy(pd_cache);123}124125126