1e126ba97SEli Cohen /* 2e126ba97SEli Cohen * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. 3e126ba97SEli Cohen * 4e126ba97SEli Cohen * This software is available to you under a choice of one of two 5e126ba97SEli Cohen * licenses. You may choose to be licensed under the terms of the GNU 6e126ba97SEli Cohen * General Public License (GPL) Version 2, available from the file 7e126ba97SEli Cohen * COPYING in the main directory of this source tree, or the 8e126ba97SEli Cohen * OpenIB.org BSD license below: 9e126ba97SEli Cohen * 10e126ba97SEli Cohen * Redistribution and use in source and binary forms, with or 11e126ba97SEli Cohen * without modification, are permitted provided that the following 12e126ba97SEli Cohen * conditions are met: 13e126ba97SEli Cohen * 14e126ba97SEli Cohen * - Redistributions of source code must retain the above 15e126ba97SEli Cohen * copyright notice, this list of conditions and the following 16e126ba97SEli Cohen * disclaimer. 17e126ba97SEli Cohen * 18e126ba97SEli Cohen * - Redistributions in binary form must reproduce the above 19e126ba97SEli Cohen * copyright notice, this list of conditions and the following 20e126ba97SEli Cohen * disclaimer in the documentation and/or other materials 21e126ba97SEli Cohen * provided with the distribution. 22e126ba97SEli Cohen * 23e126ba97SEli Cohen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e126ba97SEli Cohen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e126ba97SEli Cohen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e126ba97SEli Cohen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e126ba97SEli Cohen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e126ba97SEli Cohen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e126ba97SEli Cohen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e126ba97SEli Cohen * SOFTWARE. 31e126ba97SEli Cohen */ 32e126ba97SEli Cohen 33e126ba97SEli Cohen #include <linux/kref.h> 34e126ba97SEli Cohen #include <linux/slab.h> 35e126ba97SEli Cohen #include <rdma/ib_umem.h> 36e126ba97SEli Cohen 37e126ba97SEli Cohen #include "mlx5_ib.h" 38e126ba97SEli Cohen 39e126ba97SEli Cohen struct mlx5_ib_user_db_page { 40e126ba97SEli Cohen struct list_head list; 41e126ba97SEli Cohen struct ib_umem *umem; 42e126ba97SEli Cohen unsigned long user_virt; 43e126ba97SEli Cohen int refcnt; 44e126ba97SEli Cohen }; 45e126ba97SEli Cohen 46e126ba97SEli Cohen int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt, 47e126ba97SEli Cohen struct mlx5_db *db) 48e126ba97SEli Cohen { 49e126ba97SEli Cohen struct mlx5_ib_user_db_page *page; 50e126ba97SEli Cohen struct ib_umem_chunk *chunk; 51e126ba97SEli Cohen int err = 0; 52e126ba97SEli Cohen 53e126ba97SEli Cohen mutex_lock(&context->db_page_mutex); 54e126ba97SEli Cohen 55e126ba97SEli Cohen list_for_each_entry(page, &context->db_page_list, list) 56e126ba97SEli Cohen if (page->user_virt == (virt & PAGE_MASK)) 57e126ba97SEli Cohen goto found; 58e126ba97SEli Cohen 59e126ba97SEli Cohen page = kmalloc(sizeof(*page), GFP_KERNEL); 60e126ba97SEli Cohen if (!page) { 61e126ba97SEli Cohen err = -ENOMEM; 62e126ba97SEli Cohen goto out; 63e126ba97SEli Cohen } 64e126ba97SEli Cohen 65e126ba97SEli Cohen page->user_virt = (virt & PAGE_MASK); 66e126ba97SEli Cohen page->refcnt = 0; 67e126ba97SEli Cohen page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK, 68e126ba97SEli Cohen PAGE_SIZE, 0, 0); 69e126ba97SEli Cohen if (IS_ERR(page->umem)) { 70e126ba97SEli Cohen err = PTR_ERR(page->umem); 71e126ba97SEli Cohen kfree(page); 72e126ba97SEli Cohen goto out; 73e126ba97SEli Cohen } 74e126ba97SEli Cohen 75e126ba97SEli Cohen list_add(&page->list, &context->db_page_list); 76e126ba97SEli Cohen 77e126ba97SEli Cohen found: 78e126ba97SEli Cohen chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); 79e126ba97SEli Cohen db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK); 80e126ba97SEli Cohen db->u.user_page = page; 81e126ba97SEli Cohen ++page->refcnt; 82e126ba97SEli Cohen 83e126ba97SEli Cohen out: 84e126ba97SEli Cohen mutex_unlock(&context->db_page_mutex); 85e126ba97SEli Cohen 86e126ba97SEli Cohen return err; 87e126ba97SEli Cohen } 88e126ba97SEli Cohen 89e126ba97SEli Cohen void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db) 90e126ba97SEli Cohen { 91e126ba97SEli Cohen mutex_lock(&context->db_page_mutex); 92e126ba97SEli Cohen 93e126ba97SEli Cohen if (!--db->u.user_page->refcnt) { 94e126ba97SEli Cohen list_del(&db->u.user_page->list); 95e126ba97SEli Cohen ib_umem_release(db->u.user_page->umem); 96e126ba97SEli Cohen kfree(db->u.user_page); 97e126ba97SEli Cohen } 98e126ba97SEli Cohen 99e126ba97SEli Cohen mutex_unlock(&context->db_page_mutex); 100e126ba97SEli Cohen } 101