root/drivers/fpga/dfl-afu-region.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. afu_mmio_region_init
  2. get_region_by_index
  3. afu_mmio_region_add
  4. afu_mmio_region_destroy
  5. afu_mmio_region_get_by_index
  6. afu_mmio_region_get_by_offset

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Driver for FPGA Accelerated Function Unit (AFU) MMIO Region Management
   4  *
   5  * Copyright (C) 2017-2018 Intel Corporation, Inc.
   6  *
   7  * Authors:
   8  *   Wu Hao <hao.wu@intel.com>
   9  *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
  10  */
  11 #include "dfl-afu.h"
  12 
  13 /**
  14  * afu_mmio_region_init - init function for afu mmio region support
  15  * @pdata: afu platform device's pdata.
  16  */
  17 void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
  18 {
  19         struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
  20 
  21         INIT_LIST_HEAD(&afu->regions);
  22 }
  23 
  24 #define for_each_region(region, afu)    \
  25         list_for_each_entry((region), &(afu)->regions, node)
  26 
  27 static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
  28                                                        u32 region_index)
  29 {
  30         struct dfl_afu_mmio_region *region;
  31 
  32         for_each_region(region, afu)
  33                 if (region->index == region_index)
  34                         return region;
  35 
  36         return NULL;
  37 }
  38 
  39 /**
  40  * afu_mmio_region_add - add a mmio region to given feature dev.
  41  *
  42  * @region_index: region index.
  43  * @region_size: region size.
  44  * @phys: region's physical address of this region.
  45  * @flags: region flags (access permission).
  46  *
  47  * Return: 0 on success, negative error code otherwise.
  48  */
  49 int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
  50                         u32 region_index, u64 region_size, u64 phys, u32 flags)
  51 {
  52         struct dfl_afu_mmio_region *region;
  53         struct dfl_afu *afu;
  54         int ret = 0;
  55 
  56         region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
  57         if (!region)
  58                 return -ENOMEM;
  59 
  60         region->index = region_index;
  61         region->size = region_size;
  62         region->phys = phys;
  63         region->flags = flags;
  64 
  65         mutex_lock(&pdata->lock);
  66 
  67         afu = dfl_fpga_pdata_get_private(pdata);
  68 
  69         /* check if @index already exists */
  70         if (get_region_by_index(afu, region_index)) {
  71                 mutex_unlock(&pdata->lock);
  72                 ret = -EEXIST;
  73                 goto exit;
  74         }
  75 
  76         region_size = PAGE_ALIGN(region_size);
  77         region->offset = afu->region_cur_offset;
  78         list_add(&region->node, &afu->regions);
  79 
  80         afu->region_cur_offset += region_size;
  81         afu->num_regions++;
  82         mutex_unlock(&pdata->lock);
  83 
  84         return 0;
  85 
  86 exit:
  87         devm_kfree(&pdata->dev->dev, region);
  88         return ret;
  89 }
  90 
  91 /**
  92  * afu_mmio_region_destroy - destroy all mmio regions under given feature dev.
  93  * @pdata: afu platform device's pdata.
  94  */
  95 void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
  96 {
  97         struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
  98         struct dfl_afu_mmio_region *tmp, *region;
  99 
 100         list_for_each_entry_safe(region, tmp, &afu->regions, node)
 101                 devm_kfree(&pdata->dev->dev, region);
 102 }
 103 
 104 /**
 105  * afu_mmio_region_get_by_index - find an afu region by index.
 106  * @pdata: afu platform device's pdata.
 107  * @region_index: region index.
 108  * @pregion: ptr to region for result.
 109  *
 110  * Return: 0 on success, negative error code otherwise.
 111  */
 112 int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
 113                                  u32 region_index,
 114                                  struct dfl_afu_mmio_region *pregion)
 115 {
 116         struct dfl_afu_mmio_region *region;
 117         struct dfl_afu *afu;
 118         int ret = 0;
 119 
 120         mutex_lock(&pdata->lock);
 121         afu = dfl_fpga_pdata_get_private(pdata);
 122         region = get_region_by_index(afu, region_index);
 123         if (!region) {
 124                 ret = -EINVAL;
 125                 goto exit;
 126         }
 127         *pregion = *region;
 128 exit:
 129         mutex_unlock(&pdata->lock);
 130         return ret;
 131 }
 132 
 133 /**
 134  * afu_mmio_region_get_by_offset - find an afu mmio region by offset and size
 135  *
 136  * @pdata: afu platform device's pdata.
 137  * @offset: region offset from start of the device fd.
 138  * @size: region size.
 139  * @pregion: ptr to region for result.
 140  *
 141  * Find the region which fully contains the region described by input
 142  * parameters (offset and size) from the feature dev's region linked list.
 143  *
 144  * Return: 0 on success, negative error code otherwise.
 145  */
 146 int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
 147                                   u64 offset, u64 size,
 148                                   struct dfl_afu_mmio_region *pregion)
 149 {
 150         struct dfl_afu_mmio_region *region;
 151         struct dfl_afu *afu;
 152         int ret = 0;
 153 
 154         mutex_lock(&pdata->lock);
 155         afu = dfl_fpga_pdata_get_private(pdata);
 156         for_each_region(region, afu)
 157                 if (region->offset <= offset &&
 158                     region->offset + region->size >= offset + size) {
 159                         *pregion = *region;
 160                         goto exit;
 161                 }
 162         ret = -EINVAL;
 163 exit:
 164         mutex_unlock(&pdata->lock);
 165         return ret;
 166 }

/* [<][>][^][v][top][bottom][index][help] */