0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "dfl-afu.h"
0012
0013
0014
0015
0016
0017 void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
0018 {
0019 struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
0020
0021 INIT_LIST_HEAD(&afu->regions);
0022 }
0023
0024 #define for_each_region(region, afu) \
0025 list_for_each_entry((region), &(afu)->regions, node)
0026
0027 static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
0028 u32 region_index)
0029 {
0030 struct dfl_afu_mmio_region *region;
0031
0032 for_each_region(region, afu)
0033 if (region->index == region_index)
0034 return region;
0035
0036 return NULL;
0037 }
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
0050 u32 region_index, u64 region_size, u64 phys, u32 flags)
0051 {
0052 struct dfl_afu_mmio_region *region;
0053 struct dfl_afu *afu;
0054 int ret = 0;
0055
0056 region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
0057 if (!region)
0058 return -ENOMEM;
0059
0060 region->index = region_index;
0061 region->size = region_size;
0062 region->phys = phys;
0063 region->flags = flags;
0064
0065 mutex_lock(&pdata->lock);
0066
0067 afu = dfl_fpga_pdata_get_private(pdata);
0068
0069
0070 if (get_region_by_index(afu, region_index)) {
0071 mutex_unlock(&pdata->lock);
0072 ret = -EEXIST;
0073 goto exit;
0074 }
0075
0076 region_size = PAGE_ALIGN(region_size);
0077 region->offset = afu->region_cur_offset;
0078 list_add(®ion->node, &afu->regions);
0079
0080 afu->region_cur_offset += region_size;
0081 afu->num_regions++;
0082 mutex_unlock(&pdata->lock);
0083
0084 return 0;
0085
0086 exit:
0087 devm_kfree(&pdata->dev->dev, region);
0088 return ret;
0089 }
0090
0091
0092
0093
0094
0095 void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
0096 {
0097 struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
0098 struct dfl_afu_mmio_region *tmp, *region;
0099
0100 list_for_each_entry_safe(region, tmp, &afu->regions, node)
0101 devm_kfree(&pdata->dev->dev, region);
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
0113 u32 region_index,
0114 struct dfl_afu_mmio_region *pregion)
0115 {
0116 struct dfl_afu_mmio_region *region;
0117 struct dfl_afu *afu;
0118 int ret = 0;
0119
0120 mutex_lock(&pdata->lock);
0121 afu = dfl_fpga_pdata_get_private(pdata);
0122 region = get_region_by_index(afu, region_index);
0123 if (!region) {
0124 ret = -EINVAL;
0125 goto exit;
0126 }
0127 *pregion = *region;
0128 exit:
0129 mutex_unlock(&pdata->lock);
0130 return ret;
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
0147 u64 offset, u64 size,
0148 struct dfl_afu_mmio_region *pregion)
0149 {
0150 struct dfl_afu_mmio_region *region;
0151 struct dfl_afu *afu;
0152 int ret = 0;
0153
0154 mutex_lock(&pdata->lock);
0155 afu = dfl_fpga_pdata_get_private(pdata);
0156 for_each_region(region, afu)
0157 if (region->offset <= offset &&
0158 region->offset + region->size >= offset + size) {
0159 *pregion = *region;
0160 goto exit;
0161 }
0162 ret = -EINVAL;
0163 exit:
0164 mutex_unlock(&pdata->lock);
0165 return ret;
0166 }