1/* 2 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2005, 2014 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/bitops.h> 35/* 36 #include <linux/io-mapping.h> 37 38 #include <linux/page.h> 39 */ 40#include "mlx4.h" 41#include <debug.h> 42/* 43 #include "icm.h" 44 */ 45enum { 46 MLX4_NUM_RESERVED_UARS = 8 47}; 48 49int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) { 50 struct mlx4_priv *priv = mlx4_priv(dev); 51 52 *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); 53 if (*pdn == -1) 54 return -ENOMEM; 55 56 return 0; 57} 58/* 59 EXPORT_SYMBOL_GPL(mlx4_pd_alloc); 60 61 void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) 62 { 63 mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR); 64 } 65 EXPORT_SYMBOL_GPL(mlx4_pd_free); 66 67 int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn) 68 { 69 struct mlx4_dev *dev = mlx4_priv(dev); 70 71 *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap); 72 if (*xrcdn == -1) 73 return -ENOMEM; 74 75 return 0; 76 } 77 78 int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn) 79 { 80 u64 out_param; 81 int err; 82 83 if (mlx4_is_mfunc(dev)) { 84 err = mlx4_cmd_imm(dev, 0, &out_param, 85 RES_XRCD, RES_OP_RESERVE, 86 MLX4_CMD_ALLOC_RES, 87 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 88 if (err) 89 return err; 90 91 *xrcdn = get_param_l(&out_param); 92 return 0; 93 } 94 return __mlx4_xrcd_alloc(dev, xrcdn); 95 } 96 EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc); 97 98 void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) 99 { 100 mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR); 101 } 102 103 void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) 104 { 105 u64 in_param = 0; 106 int err; 107 108 if (mlx4_is_mfunc(dev)) { 109 set_param_l(&in_param, xrcdn); 110 err = mlx4_cmd(dev, in_param, RES_XRCD, 111 RES_OP_RESERVE, MLX4_CMD_FREE_RES, 112 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 113 if (err) 114 mlx4_warn(dev, "Failed to release xrcdn %d\n", xrcdn); 115 } else 116 __mlx4_xrcd_free(dev, xrcdn); 117 } 118 EXPORT_SYMBOL_GPL(mlx4_xrcd_free); 119 */ 120int mlx4_init_pd_table(struct mlx4_priv *priv) { 121 return mlx4_bitmap_init(&priv->pd_bitmap, priv->dev.caps.num_pds, 122 (1 << NOT_MASKED_PD_BITS) - 1, priv->dev.caps.reserved_pds, 0); 123} 124/* 125 void mlx4_cleanup_pd_table(struct mlx4_dev *dev) 126 { 127 mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); 128 } 129 */ 130int mlx4_init_xrcd_table(struct mlx4_priv *priv) { 131 return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16), (1 << 16) - 1, 132 priv->dev.caps.reserved_xrcds + 1, 0); 133} 134/* 135 void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev) 136 { 137 mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap); 138 } 139 */ 140#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */ 141int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) { 142 struct mlx4_priv *priv = mlx4_priv(dev); 143 int offset; 144 145 uar->index = mlx4_bitmap_alloc(&priv->uar_table.bitmap); 146 if (uar->index == -1) 147 return -ENOMEM; 148 149 if (mlx4_is_slave(&priv->dev)) 150 offset = uar->index 151 % ((int) priv->dev.bar_info[1].bytes 152 / priv->dev.caps.uar_page_size); 153 else 154 offset = uar->index; 155 156 /*MLX4_DEBUG("%p, %d\n", priv->dev.bar_info[1].vaddr, offset);*/ 157 158 uar->pfn = ((volatile uint64_t) priv->dev.bar_info[1].vaddr >> PAGE_SHIFT) 159 + offset; 160 uar->map = NULL; 161 return 0; 162} 163/* 164 EXPORT_SYMBOL_GPL(mlx4_uar_alloc); 165 166 void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar) 167 { 168 mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR); 169 } 170 EXPORT_SYMBOL_GPL(mlx4_uar_free); 171 172 #ifndef CONFIG_PPC 173 */ 174int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node) { 175 struct mlx4_priv *priv = mlx4_priv(dev); 176 struct mlx4_uar *uar; 177 int err = 0; 178 int idx; 179 180 if (!priv->bf_mapping) 181 return -ENOMEM; 182 183 /*mutex_lock(&priv->bf_mutex);*/ 184 if (!list_empty(&priv->bf_list)) 185 uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list); 186 else { 187 if (mlx4_bitmap_avail(&priv->uar_table.bitmap) 188 < MLX4_NUM_RESERVED_UARS) { 189 err = -ENOMEM; 190 goto out; 191 } 192 /*uar = kmalloc_node(sizeof *uar, GFP_KERNEL, node); 193 if (!uar) {*/ 194 uar = malloc(sizeof *uar); 195 if (!uar) { 196 err = -ENOMEM; 197 goto out; 198 } 199 /*}*/ 200 err = mlx4_uar_alloc(dev, uar); 201 if (err) 202 goto free_kmalloc; 203 204 uar->map = (void *) (uar->pfn << PAGE_SHIFT); 205 if (!uar->map) { 206 err = -ENOMEM; 207 goto free_uar; 208 } 209 210 uar->bf_map = io_mapping_map_wc(priv->bf_mapping, 211 uar->index << PAGE_SHIFT); 212 if (!uar->bf_map) { 213 err = -ENOMEM; 214 goto unamp_uar; 215 } 216 uar->free_bf_bmap = 0; 217 list_add(&uar->bf_list, &priv->bf_list); 218 } 219 220 bf->uar = uar; 221 idx = ffz(uar->free_bf_bmap); 222 uar->free_bf_bmap |= 1 << idx; 223 bf->uar = uar; 224 bf->offset = 0; 225 bf->buf_size = priv->dev.caps.bf_reg_size / 2; 226 bf->reg = uar->bf_map + idx * priv->dev.caps.bf_reg_size; 227 if (uar->free_bf_bmap == (1 << priv->dev.caps.bf_regs_per_page) - 1) 228 list_del_init(&uar->bf_list); 229 230 goto out; 231 232 unamp_uar: bf->uar = NULL; 233 /*iounmap(uar->map);*/ 234 235 free_uar: /*mlx4_uar_free(dev, uar);*/ 236 237 free_kmalloc: free(uar); 238 239 out: /*mutex_unlock(&priv->bf_mutex);*/ 240 return err; 241} 242/* 243 EXPORT_SYMBOL_GPL(mlx4_bf_alloc); 244 245 void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf) 246 { 247 struct mlx4_priv *priv = mlx4_priv(dev); 248 int idx; 249 250 if (!bf->uar || !bf->uar->bf_map) 251 return; 252 253 mutex_lock(&priv->bf_mutex); 254 idx = (bf->reg - bf->uar->bf_map) / priv->dev.caps.bf_reg_size; 255 bf->uar->free_bf_bmap &= ~(1 << idx); 256 if (!bf->uar->free_bf_bmap) { 257 if (!list_empty(&bf->uar->bf_list)) 258 list_del(&bf->uar->bf_list); 259 260 io_mapping_unmap(bf->uar->bf_map); 261 iounmap(bf->uar->map); 262 mlx4_uar_free(dev, bf->uar); 263 kfree(bf->uar); 264 } else if (list_empty(&bf->uar->bf_list)) 265 list_add(&bf->uar->bf_list, &priv->bf_list); 266 267 mutex_unlock(&priv->bf_mutex); 268 } 269 EXPORT_SYMBOL_GPL(mlx4_bf_free); 270 271 #else 272 int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node) 273 { 274 memset(bf, 0, sizeof *bf); 275 return -ENOSYS; 276 } 277 EXPORT_SYMBOL_GPL(mlx4_bf_alloc); 278 279 void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf) 280 { 281 return; 282 } 283 EXPORT_SYMBOL_GPL(mlx4_bf_free); 284 #endif 285 */ 286int mlx4_init_uar_table(struct mlx4_priv *priv) { 287 if (priv->dev.caps.num_uars <= 128) { 288 MLX4_DEBUG("Only %d UAR pages (need more than 128)\n", 289 priv->dev.caps.num_uars); 290 MLX4_DEBUG("Increase firmware log2_uar_bar_megabytes?\n"); 291 return -ENODEV; 292 } 293 294 return mlx4_bitmap_init(&priv->uar_table.bitmap, priv->dev.caps.num_uars, 295 priv->dev.caps.num_uars - 1, priv->dev.caps.reserved_uars, 0); 296} 297/* 298 void mlx4_cleanup_uar_table(struct mlx4_dev *dev) 299 { 300 mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap); 301 }*/ 302