1f48ad614SDennis Dalessandro /* 22280740fSVishwanathapura, Niranjana * Copyright(c) 2015-2017 Intel Corporation. 3f48ad614SDennis Dalessandro * 4f48ad614SDennis Dalessandro * This file is provided under a dual BSD/GPLv2 license. When using or 5f48ad614SDennis Dalessandro * redistributing this file, you may do so under either license. 6f48ad614SDennis Dalessandro * 7f48ad614SDennis Dalessandro * GPL LICENSE SUMMARY 8f48ad614SDennis Dalessandro * 9f48ad614SDennis Dalessandro * This program is free software; you can redistribute it and/or modify 10f48ad614SDennis Dalessandro * it under the terms of version 2 of the GNU General Public License as 11f48ad614SDennis Dalessandro * published by the Free Software Foundation. 12f48ad614SDennis Dalessandro * 13f48ad614SDennis Dalessandro * This program is distributed in the hope that it will be useful, but 14f48ad614SDennis Dalessandro * WITHOUT ANY WARRANTY; without even the implied warranty of 15f48ad614SDennis Dalessandro * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16f48ad614SDennis Dalessandro * General Public License for more details. 17f48ad614SDennis Dalessandro * 18f48ad614SDennis Dalessandro * BSD LICENSE 19f48ad614SDennis Dalessandro * 20f48ad614SDennis Dalessandro * Redistribution and use in source and binary forms, with or without 21f48ad614SDennis Dalessandro * modification, are permitted provided that the following conditions 22f48ad614SDennis Dalessandro * are met: 23f48ad614SDennis Dalessandro * 24f48ad614SDennis Dalessandro * - Redistributions of source code must retain the above copyright 25f48ad614SDennis Dalessandro * notice, this list of conditions and the following disclaimer. 26f48ad614SDennis Dalessandro * - Redistributions in binary form must reproduce the above copyright 27f48ad614SDennis Dalessandro * notice, this list of conditions and the following disclaimer in 28f48ad614SDennis Dalessandro * the documentation and/or other materials provided with the 29f48ad614SDennis Dalessandro * distribution. 30f48ad614SDennis Dalessandro * - Neither the name of Intel Corporation nor the names of its 31f48ad614SDennis Dalessandro * contributors may be used to endorse or promote products derived 32f48ad614SDennis Dalessandro * from this software without specific prior written permission. 33f48ad614SDennis Dalessandro * 34f48ad614SDennis Dalessandro * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 35f48ad614SDennis Dalessandro * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36f48ad614SDennis Dalessandro * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 37f48ad614SDennis Dalessandro * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 38f48ad614SDennis Dalessandro * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 39f48ad614SDennis Dalessandro * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 40f48ad614SDennis Dalessandro * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 41f48ad614SDennis Dalessandro * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 42f48ad614SDennis Dalessandro * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 43f48ad614SDennis Dalessandro * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 44f48ad614SDennis Dalessandro * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45f48ad614SDennis Dalessandro * 46f48ad614SDennis Dalessandro */ 47f48ad614SDennis Dalessandro 48f48ad614SDennis Dalessandro #include <linux/mm.h> 493f07c014SIngo Molnar #include <linux/sched/signal.h> 50f48ad614SDennis Dalessandro #include <linux/device.h> 51f48ad614SDennis Dalessandro #include <linux/module.h> 52f48ad614SDennis Dalessandro 53f48ad614SDennis Dalessandro #include "hfi.h" 54f48ad614SDennis Dalessandro 55f48ad614SDennis Dalessandro static unsigned long cache_size = 256; 56f48ad614SDennis Dalessandro module_param(cache_size, ulong, S_IRUGO | S_IWUSR); 57f48ad614SDennis Dalessandro MODULE_PARM_DESC(cache_size, "Send and receive side cache size limit (in MB)"); 58f48ad614SDennis Dalessandro 59f48ad614SDennis Dalessandro /* 60f48ad614SDennis Dalessandro * Determine whether the caller can pin pages. 61f48ad614SDennis Dalessandro * 62f48ad614SDennis Dalessandro * This function should be used in the implementation of buffer caches. 63f48ad614SDennis Dalessandro * The cache implementation should call this function prior to attempting 64f48ad614SDennis Dalessandro * to pin buffer pages in order to determine whether they should do so. 65f48ad614SDennis Dalessandro * The function computes cache limits based on the configured ulimit and 66f48ad614SDennis Dalessandro * cache size. Use of this function is especially important for caches 67f48ad614SDennis Dalessandro * which are not limited in any other way (e.g. by HW resources) and, thus, 68f48ad614SDennis Dalessandro * could keeping caching buffers. 69f48ad614SDennis Dalessandro * 70f48ad614SDennis Dalessandro */ 713faa3d9aSIra Weiny bool hfi1_can_pin_pages(struct hfi1_devdata *dd, struct mm_struct *mm, 723faa3d9aSIra Weiny u32 nlocked, u32 npages) 73f48ad614SDennis Dalessandro { 74f48ad614SDennis Dalessandro unsigned long ulimit = rlimit(RLIMIT_MEMLOCK), pinned, cache_limit, 75f48ad614SDennis Dalessandro size = (cache_size * (1UL << 20)); /* convert to bytes */ 762280740fSVishwanathapura, Niranjana unsigned int usr_ctxts = 772280740fSVishwanathapura, Niranjana dd->num_rcv_contexts - dd->first_dyn_alloc_ctxt; 78f48ad614SDennis Dalessandro bool can_lock = capable(CAP_IPC_LOCK); 79f48ad614SDennis Dalessandro 80f48ad614SDennis Dalessandro /* 81f48ad614SDennis Dalessandro * Calculate per-cache size. The calculation below uses only a quarter 82f48ad614SDennis Dalessandro * of the available per-context limit. This leaves space for other 83f48ad614SDennis Dalessandro * pinning. Should we worry about shared ctxts? 84f48ad614SDennis Dalessandro */ 85f48ad614SDennis Dalessandro cache_limit = (ulimit / usr_ctxts) / 4; 86f48ad614SDennis Dalessandro 87f48ad614SDennis Dalessandro /* If ulimit isn't set to "unlimited" and is smaller than cache_size. */ 88f48ad614SDennis Dalessandro if (ulimit != (-1UL) && size > cache_limit) 89f48ad614SDennis Dalessandro size = cache_limit; 90f48ad614SDennis Dalessandro 91f48ad614SDennis Dalessandro /* Convert to number of pages */ 92f48ad614SDennis Dalessandro size = DIV_ROUND_UP(size, PAGE_SIZE); 93f48ad614SDennis Dalessandro 943faa3d9aSIra Weiny down_read(&mm->mmap_sem); 95*70f8a3caSDavidlohr Bueso pinned = atomic64_read(&mm->pinned_vm); 963faa3d9aSIra Weiny up_read(&mm->mmap_sem); 97f48ad614SDennis Dalessandro 98f48ad614SDennis Dalessandro /* First, check the absolute limit against all pinned pages. */ 99f48ad614SDennis Dalessandro if (pinned + npages >= ulimit && !can_lock) 100f48ad614SDennis Dalessandro return false; 101f48ad614SDennis Dalessandro 102f48ad614SDennis Dalessandro return ((nlocked + npages) <= size) || can_lock; 103f48ad614SDennis Dalessandro } 104f48ad614SDennis Dalessandro 1053faa3d9aSIra Weiny int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t npages, 1063faa3d9aSIra Weiny bool writable, struct page **pages) 107f48ad614SDennis Dalessandro { 108f48ad614SDennis Dalessandro int ret; 109f48ad614SDennis Dalessandro 110f48ad614SDennis Dalessandro ret = get_user_pages_fast(vaddr, npages, writable, pages); 111f48ad614SDennis Dalessandro if (ret < 0) 112f48ad614SDennis Dalessandro return ret; 113f48ad614SDennis Dalessandro 1143faa3d9aSIra Weiny down_write(&mm->mmap_sem); 115*70f8a3caSDavidlohr Bueso atomic64_add(ret, &mm->pinned_vm); 1163faa3d9aSIra Weiny up_write(&mm->mmap_sem); 117f48ad614SDennis Dalessandro 118f48ad614SDennis Dalessandro return ret; 119f48ad614SDennis Dalessandro } 120f48ad614SDennis Dalessandro 121f48ad614SDennis Dalessandro void hfi1_release_user_pages(struct mm_struct *mm, struct page **p, 122f48ad614SDennis Dalessandro size_t npages, bool dirty) 123f48ad614SDennis Dalessandro { 124f48ad614SDennis Dalessandro size_t i; 125f48ad614SDennis Dalessandro 126f48ad614SDennis Dalessandro for (i = 0; i < npages; i++) { 127f48ad614SDennis Dalessandro if (dirty) 128f48ad614SDennis Dalessandro set_page_dirty_lock(p[i]); 129f48ad614SDennis Dalessandro put_page(p[i]); 130f48ad614SDennis Dalessandro } 131f48ad614SDennis Dalessandro 132f48ad614SDennis Dalessandro if (mm) { /* during close after signal, mm can be NULL */ 133f48ad614SDennis Dalessandro down_write(&mm->mmap_sem); 134*70f8a3caSDavidlohr Bueso atomic64_sub(npages, &mm->pinned_vm); 135f48ad614SDennis Dalessandro up_write(&mm->mmap_sem); 136f48ad614SDennis Dalessandro } 137f48ad614SDennis Dalessandro } 138