cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pd.c (7517B)


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