/drivers/net/mlx4/pd.c
C | 210 lines | 143 code | 35 blank | 32 comment | 21 complexity | b81dff108ac30f19f20bd44e506ee71c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* 2 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2005 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/errno.h> 35#include <linux/io-mapping.h> 36 37#include <asm/page.h> 38 39#include "mlx4.h" 40#include "icm.h" 41 42enum { 43 MLX4_NUM_RESERVED_UARS = 8 44}; 45 46int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) 47{ 48 struct mlx4_priv *priv = mlx4_priv(dev); 49 50 *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); 51 if (*pdn == -1) 52 return -ENOMEM; 53 54 return 0; 55} 56EXPORT_SYMBOL_GPL(mlx4_pd_alloc); 57 58void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) 59{ 60 mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn); 61} 62EXPORT_SYMBOL_GPL(mlx4_pd_free); 63 64int mlx4_init_pd_table(struct mlx4_dev *dev) 65{ 66 struct mlx4_priv *priv = mlx4_priv(dev); 67 68 return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds, 69 (1 << 24) - 1, dev->caps.reserved_pds, 0); 70} 71 72void mlx4_cleanup_pd_table(struct mlx4_dev *dev) 73{ 74 mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); 75} 76 77 78int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) 79{ 80 uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap); 81 if (uar->index == -1) 82 return -ENOMEM; 83 84 uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index; 85 uar->map = NULL; 86 87 return 0; 88} 89EXPORT_SYMBOL_GPL(mlx4_uar_alloc); 90 91void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar) 92{ 93 mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index); 94} 95EXPORT_SYMBOL_GPL(mlx4_uar_free); 96 97int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf) 98{ 99 struct mlx4_priv *priv = mlx4_priv(dev); 100 struct mlx4_uar *uar; 101 int err = 0; 102 int idx; 103 104 if (!priv->bf_mapping) 105 return -ENOMEM; 106 107 mutex_lock(&priv->bf_mutex); 108 if (!list_empty(&priv->bf_list)) 109 uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list); 110 else { 111 if (mlx4_bitmap_avail(&priv->uar_table.bitmap) < MLX4_NUM_RESERVED_UARS) { 112 err = -ENOMEM; 113 goto out; 114 } 115 uar = kmalloc(sizeof *uar, GFP_KERNEL); 116 if (!uar) { 117 err = -ENOMEM; 118 goto out; 119 } 120 err = mlx4_uar_alloc(dev, uar); 121 if (err) 122 goto free_kmalloc; 123 124 uar->map = ioremap(uar->pfn << PAGE_SHIFT, PAGE_SIZE); 125 if (!uar->map) { 126 err = -ENOMEM; 127 goto free_uar; 128 } 129 130 uar->bf_map = io_mapping_map_wc(priv->bf_mapping, uar->index << PAGE_SHIFT); 131 if (!uar->bf_map) { 132 err = -ENOMEM; 133 goto unamp_uar; 134 } 135 uar->free_bf_bmap = 0; 136 list_add(&uar->bf_list, &priv->bf_list); 137 } 138 139 bf->uar = uar; 140 idx = ffz(uar->free_bf_bmap); 141 uar->free_bf_bmap |= 1 << idx; 142 bf->uar = uar; 143 bf->offset = 0; 144 bf->buf_size = dev->caps.bf_reg_size / 2; 145 bf->reg = uar->bf_map + idx * dev->caps.bf_reg_size; 146 if (uar->free_bf_bmap == (1 << dev->caps.bf_regs_per_page) - 1) 147 list_del_init(&uar->bf_list); 148 149 goto out; 150 151unamp_uar: 152 bf->uar = NULL; 153 iounmap(uar->map); 154 155free_uar: 156 mlx4_uar_free(dev, uar); 157 158free_kmalloc: 159 kfree(uar); 160 161out: 162 mutex_unlock(&priv->bf_mutex); 163 return err; 164} 165EXPORT_SYMBOL_GPL(mlx4_bf_alloc); 166 167void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf) 168{ 169 struct mlx4_priv *priv = mlx4_priv(dev); 170 int idx; 171 172 if (!bf->uar || !bf->uar->bf_map) 173 return; 174 175 mutex_lock(&priv->bf_mutex); 176 idx = (bf->reg - bf->uar->bf_map) / dev->caps.bf_reg_size; 177 bf->uar->free_bf_bmap &= ~(1 << idx); 178 if (!bf->uar->free_bf_bmap) { 179 if (!list_empty(&bf->uar->bf_list)) 180 list_del(&bf->uar->bf_list); 181 182 io_mapping_unmap(bf->uar->bf_map); 183 iounmap(bf->uar->map); 184 mlx4_uar_free(dev, bf->uar); 185 kfree(bf->uar); 186 } else if (list_empty(&bf->uar->bf_list)) 187 list_add(&bf->uar->bf_list, &priv->bf_list); 188 189 mutex_unlock(&priv->bf_mutex); 190} 191EXPORT_SYMBOL_GPL(mlx4_bf_free); 192 193int mlx4_init_uar_table(struct mlx4_dev *dev) 194{ 195 if (dev->caps.num_uars <= 128) { 196 mlx4_err(dev, "Only %d UAR pages (need more than 128)\n", 197 dev->caps.num_uars); 198 mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n"); 199 return -ENODEV; 200 } 201 202 return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap, 203 dev->caps.num_uars, dev->caps.num_uars - 1, 204 max(128, dev->caps.reserved_uars), 0); 205} 206 207void mlx4_cleanup_uar_table(struct mlx4_dev *dev) 208{ 209 mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap); 210}