linux/drivers/infiniband/hw/qib/qib_user_pages.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
   3 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
   4 *
   5 * This software is available to you under a choice of one of two
   6 * licenses.  You may choose to be licensed under the terms of the GNU
   7 * General Public License (GPL) Version 2, available from the file
   8 * COPYING in the main directory of this source tree, or the
   9 * OpenIB.org BSD license below:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      - Redistributions of source code must retain the above
  16 *        copyright notice, this list of conditions and the following
  17 *        disclaimer.
  18 *
  19 *      - Redistributions in binary form must reproduce the above
  20 *        copyright notice, this list of conditions and the following
  21 *        disclaimer in the documentation and/or other materials
  22 *        provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 */
  33
  34#include <linux/mm.h>
  35#include <linux/device.h>
  36
  37#include "qib.h"
  38
  39static void __qib_release_user_pages(struct page **p, size_t num_pages,
  40                                     int dirty)
  41{
  42        size_t i;
  43
  44        for (i = 0; i < num_pages; i++) {
  45                if (dirty)
  46                        set_page_dirty_lock(p[i]);
  47                put_page(p[i]);
  48        }
  49}
  50
  51/*
  52 * Call with current->mm->mmap_sem held.
  53 */
  54static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
  55                                struct page **p, struct vm_area_struct **vma)
  56{
  57        unsigned long lock_limit;
  58        size_t got;
  59        int ret;
  60
  61        lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
  62
  63        if (num_pages > lock_limit && !capable(CAP_IPC_LOCK)) {
  64                ret = -ENOMEM;
  65                goto bail;
  66        }
  67
  68        for (got = 0; got < num_pages; got += ret) {
  69                ret = get_user_pages(current, current->mm,
  70                                     start_page + got * PAGE_SIZE,
  71                                     num_pages - got, 1, 1,
  72                                     p + got, vma);
  73                if (ret < 0)
  74                        goto bail_release;
  75        }
  76
  77        current->mm->pinned_vm += num_pages;
  78
  79        ret = 0;
  80        goto bail;
  81
  82bail_release:
  83        __qib_release_user_pages(p, got, 0);
  84bail:
  85        return ret;
  86}
  87
  88/**
  89 * qib_map_page - a safety wrapper around pci_map_page()
  90 *
  91 * A dma_addr of all 0's is interpreted by the chip as "disabled".
  92 * Unfortunately, it can also be a valid dma_addr returned on some
  93 * architectures.
  94 *
  95 * The powerpc iommu assigns dma_addrs in ascending order, so we don't
  96 * have to bother with retries or mapping a dummy page to insure we
  97 * don't just get the same mapping again.
  98 *
  99 * I'm sure we won't be so lucky with other iommu's, so FIXME.
 100 */
 101dma_addr_t qib_map_page(struct pci_dev *hwdev, struct page *page,
 102                        unsigned long offset, size_t size, int direction)
 103{
 104        dma_addr_t phys;
 105
 106        phys = pci_map_page(hwdev, page, offset, size, direction);
 107
 108        if (phys == 0) {
 109                pci_unmap_page(hwdev, phys, size, direction);
 110                phys = pci_map_page(hwdev, page, offset, size, direction);
 111                /*
 112                 * FIXME: If we get 0 again, we should keep this page,
 113                 * map another, then free the 0 page.
 114                 */
 115        }
 116
 117        return phys;
 118}
 119
 120/**
 121 * qib_get_user_pages - lock user pages into memory
 122 * @start_page: the start page
 123 * @num_pages: the number of pages
 124 * @p: the output page structures
 125 *
 126 * This function takes a given start page (page aligned user virtual
 127 * address) and pins it and the following specified number of pages.  For
 128 * now, num_pages is always 1, but that will probably change at some point
 129 * (because caller is doing expected sends on a single virtually contiguous
 130 * buffer, so we can do all pages at once).
 131 */
 132int qib_get_user_pages(unsigned long start_page, size_t num_pages,
 133                       struct page **p)
 134{
 135        int ret;
 136
 137        down_write(&current->mm->mmap_sem);
 138
 139        ret = __qib_get_user_pages(start_page, num_pages, p, NULL);
 140
 141        up_write(&current->mm->mmap_sem);
 142
 143        return ret;
 144}
 145
 146void qib_release_user_pages(struct page **p, size_t num_pages)
 147{
 148        if (current->mm) /* during close after signal, mm can be NULL */
 149                down_write(&current->mm->mmap_sem);
 150
 151        __qib_release_user_pages(p, num_pages, 1);
 152
 153        if (current->mm) {
 154                current->mm->pinned_vm -= num_pages;
 155                up_write(&current->mm->mmap_sem);
 156        }
 157}
 158