1 /* 2 * Copyright (c) 2016 Hisilicon Limited. 3 * Copyright (c) 2007, 2008 Mellanox Technologies. 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/platform_device.h> 35 #include <linux/vmalloc.h> 36 #include "hns_roce_device.h" 37 38 int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj) 39 { 40 int ret = 0; 41 42 spin_lock(&bitmap->lock); 43 *obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); 44 if (*obj >= bitmap->max) { 45 bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) 46 & bitmap->mask; 47 *obj = find_first_zero_bit(bitmap->table, bitmap->max); 48 } 49 50 if (*obj < bitmap->max) { 51 set_bit(*obj, bitmap->table); 52 bitmap->last = (*obj + 1); 53 if (bitmap->last == bitmap->max) 54 bitmap->last = 0; 55 *obj |= bitmap->top; 56 } else { 57 ret = -1; 58 } 59 60 spin_unlock(&bitmap->lock); 61 62 return ret; 63 } 64 65 void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj, 66 int rr) 67 { 68 hns_roce_bitmap_free_range(bitmap, obj, 1, rr); 69 } 70 71 int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt, 72 int align, unsigned long *obj) 73 { 74 int ret = 0; 75 int i; 76 77 if (likely(cnt == 1 && align == 1)) 78 return hns_roce_bitmap_alloc(bitmap, obj); 79 80 spin_lock(&bitmap->lock); 81 82 *obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, 83 bitmap->last, cnt, align - 1); 84 if (*obj >= bitmap->max) { 85 bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) 86 & bitmap->mask; 87 *obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, 0, 88 cnt, align - 1); 89 } 90 91 if (*obj < bitmap->max) { 92 for (i = 0; i < cnt; i++) 93 set_bit(*obj + i, bitmap->table); 94 95 if (*obj == bitmap->last) { 96 bitmap->last = (*obj + cnt); 97 if (bitmap->last >= bitmap->max) 98 bitmap->last = 0; 99 } 100 *obj |= bitmap->top; 101 } else { 102 ret = -1; 103 } 104 105 spin_unlock(&bitmap->lock); 106 107 return ret; 108 } 109 110 void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap, 111 unsigned long obj, int cnt, 112 int rr) 113 { 114 int i; 115 116 obj &= bitmap->max + bitmap->reserved_top - 1; 117 118 spin_lock(&bitmap->lock); 119 for (i = 0; i < cnt; i++) 120 clear_bit(obj + i, bitmap->table); 121 122 if (!rr) 123 bitmap->last = min(bitmap->last, obj); 124 bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) 125 & bitmap->mask; 126 spin_unlock(&bitmap->lock); 127 } 128 129 int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask, 130 u32 reserved_bot, u32 reserved_top) 131 { 132 u32 i; 133 134 if (num != roundup_pow_of_two(num)) 135 return -EINVAL; 136 137 bitmap->last = 0; 138 bitmap->top = 0; 139 bitmap->max = num - reserved_top; 140 bitmap->mask = mask; 141 bitmap->reserved_top = reserved_top; 142 spin_lock_init(&bitmap->lock); 143 bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long), 144 GFP_KERNEL); 145 if (!bitmap->table) 146 return -ENOMEM; 147 148 for (i = 0; i < reserved_bot; ++i) 149 set_bit(i, bitmap->table); 150 151 return 0; 152 } 153 154 void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap) 155 { 156 kfree(bitmap->table); 157 } 158 159 void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size, 160 struct hns_roce_buf *buf) 161 { 162 int i; 163 struct device *dev = &hr_dev->pdev->dev; 164 u32 bits_per_long = BITS_PER_LONG; 165 166 if (buf->nbufs == 1) { 167 dma_free_coherent(dev, size, buf->direct.buf, buf->direct.map); 168 } else { 169 if (bits_per_long == 64) 170 vunmap(buf->direct.buf); 171 172 for (i = 0; i < buf->nbufs; ++i) 173 if (buf->page_list[i].buf) 174 dma_free_coherent(&hr_dev->pdev->dev, PAGE_SIZE, 175 buf->page_list[i].buf, 176 buf->page_list[i].map); 177 kfree(buf->page_list); 178 } 179 } 180 181 int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct, 182 struct hns_roce_buf *buf) 183 { 184 int i = 0; 185 dma_addr_t t; 186 struct page **pages; 187 struct device *dev = &hr_dev->pdev->dev; 188 u32 bits_per_long = BITS_PER_LONG; 189 190 /* SQ/RQ buf lease than one page, SQ + RQ = 8K */ 191 if (size <= max_direct) { 192 buf->nbufs = 1; 193 /* Npages calculated by page_size */ 194 buf->npages = 1 << get_order(size); 195 buf->page_shift = PAGE_SHIFT; 196 /* MTT PA must be recorded in 4k alignment, t is 4k aligned */ 197 buf->direct.buf = dma_alloc_coherent(dev, size, &t, GFP_KERNEL); 198 if (!buf->direct.buf) 199 return -ENOMEM; 200 201 buf->direct.map = t; 202 203 while (t & ((1 << buf->page_shift) - 1)) { 204 --buf->page_shift; 205 buf->npages *= 2; 206 } 207 208 memset(buf->direct.buf, 0, size); 209 } else { 210 buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; 211 buf->npages = buf->nbufs; 212 buf->page_shift = PAGE_SHIFT; 213 buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list), 214 GFP_KERNEL); 215 216 if (!buf->page_list) 217 return -ENOMEM; 218 219 for (i = 0; i < buf->nbufs; ++i) { 220 buf->page_list[i].buf = dma_alloc_coherent(dev, 221 PAGE_SIZE, &t, 222 GFP_KERNEL); 223 224 if (!buf->page_list[i].buf) 225 goto err_free; 226 227 buf->page_list[i].map = t; 228 memset(buf->page_list[i].buf, 0, PAGE_SIZE); 229 } 230 if (bits_per_long == 64) { 231 pages = kmalloc_array(buf->nbufs, sizeof(*pages), 232 GFP_KERNEL); 233 if (!pages) 234 goto err_free; 235 236 for (i = 0; i < buf->nbufs; ++i) 237 pages[i] = virt_to_page(buf->page_list[i].buf); 238 239 buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, 240 PAGE_KERNEL); 241 kfree(pages); 242 if (!buf->direct.buf) 243 goto err_free; 244 } 245 } 246 247 return 0; 248 249 err_free: 250 hns_roce_buf_free(hr_dev, size, buf); 251 return -ENOMEM; 252 } 253 254 void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev) 255 { 256 hns_roce_cleanup_qp_table(hr_dev); 257 hns_roce_cleanup_cq_table(hr_dev); 258 hns_roce_cleanup_mr_table(hr_dev); 259 hns_roce_cleanup_pd_table(hr_dev); 260 hns_roce_cleanup_uar_table(hr_dev); 261 } 262