1219820Sjeff/* 2219820Sjeff * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff */ 32219820Sjeff 33219820Sjeff#include <linux/slab.h> 34219820Sjeff 35219820Sjeff#include "mlx4_ib.h" 36219820Sjeff 37219820Sjeffstruct mlx4_ib_user_db_page { 38219820Sjeff struct list_head list; 39219820Sjeff struct ib_umem *umem; 40219820Sjeff unsigned long user_virt; 41219820Sjeff int refcnt; 42219820Sjeff}; 43219820Sjeff 44219820Sjeffint mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, 45219820Sjeff struct mlx4_db *db) 46219820Sjeff{ 47219820Sjeff struct mlx4_ib_user_db_page *page; 48219820Sjeff struct ib_umem_chunk *chunk; 49219820Sjeff int err = 0; 50219820Sjeff 51219820Sjeff mutex_lock(&context->db_page_mutex); 52219820Sjeff 53219820Sjeff list_for_each_entry(page, &context->db_page_list, list) 54219820Sjeff if (page->user_virt == (virt & PAGE_MASK)) 55219820Sjeff goto found; 56219820Sjeff 57219820Sjeff page = kmalloc(sizeof *page, GFP_KERNEL); 58219820Sjeff if (!page) { 59219820Sjeff err = -ENOMEM; 60219820Sjeff goto out; 61219820Sjeff } 62219820Sjeff 63219820Sjeff page->user_virt = (virt & PAGE_MASK); 64219820Sjeff page->refcnt = 0; 65219820Sjeff page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK, 66219820Sjeff PAGE_SIZE, 0, 0); 67219820Sjeff if (IS_ERR(page->umem)) { 68219820Sjeff err = PTR_ERR(page->umem); 69219820Sjeff kfree(page); 70219820Sjeff goto out; 71219820Sjeff } 72219820Sjeff 73219820Sjeff list_add(&page->list, &context->db_page_list); 74219820Sjeff 75219820Sjefffound: 76219820Sjeff chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); 77219820Sjeff db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK); 78219820Sjeff db->u.user_page = page; 79219820Sjeff ++page->refcnt; 80219820Sjeff 81219820Sjeffout: 82219820Sjeff mutex_unlock(&context->db_page_mutex); 83219820Sjeff 84219820Sjeff return err; 85219820Sjeff} 86219820Sjeff 87219820Sjeffvoid mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db) 88219820Sjeff{ 89219820Sjeff mutex_lock(&context->db_page_mutex); 90219820Sjeff 91219820Sjeff if (!--db->u.user_page->refcnt) { 92219820Sjeff list_del(&db->u.user_page->list); 93219820Sjeff ib_umem_release(db->u.user_page->umem); 94219820Sjeff kfree(db->u.user_page); 95219820Sjeff } 96219820Sjeff 97219820Sjeff mutex_unlock(&context->db_page_mutex); 98219820Sjeff} 99