brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · 2e7b416 Raw
168 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for FPGA Accelerated Function Unit (AFU) MMIO Region Management4 *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 support15 * @pdata: afu platform device's pdata.16 */17void 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 27static 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 * @pdata: afu platform device's pdata.43 * @region_index: region index.44 * @region_size: region size.45 * @phys: region's physical address of this region.46 * @flags: region flags (access permission).47 *48 * Return: 0 on success, negative error code otherwise.49 */50int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,51			u32 region_index, u64 region_size, u64 phys, u32 flags)52{53	struct dfl_afu_mmio_region *region;54	struct dfl_afu *afu;55	int ret = 0;56 57	region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);58	if (!region)59		return -ENOMEM;60 61	region->index = region_index;62	region->size = region_size;63	region->phys = phys;64	region->flags = flags;65 66	mutex_lock(&pdata->lock);67 68	afu = dfl_fpga_pdata_get_private(pdata);69 70	/* check if @index already exists */71	if (get_region_by_index(afu, region_index)) {72		mutex_unlock(&pdata->lock);73		ret = -EEXIST;74		goto exit;75	}76 77	region_size = PAGE_ALIGN(region_size);78	region->offset = afu->region_cur_offset;79	list_add(&region->node, &afu->regions);80 81	afu->region_cur_offset += region_size;82	afu->num_regions++;83	mutex_unlock(&pdata->lock);84 85	return 0;86 87exit:88	devm_kfree(&pdata->dev->dev, region);89	return ret;90}91 92/**93 * afu_mmio_region_destroy - destroy all mmio regions under given feature dev.94 * @pdata: afu platform device's pdata.95 */96void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)97{98	struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);99	struct dfl_afu_mmio_region *tmp, *region;100 101	list_for_each_entry_safe(region, tmp, &afu->regions, node)102		devm_kfree(&pdata->dev->dev, region);103}104 105/**106 * afu_mmio_region_get_by_index - find an afu region by index.107 * @pdata: afu platform device's pdata.108 * @region_index: region index.109 * @pregion: ptr to region for result.110 *111 * Return: 0 on success, negative error code otherwise.112 */113int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,114				 u32 region_index,115				 struct dfl_afu_mmio_region *pregion)116{117	struct dfl_afu_mmio_region *region;118	struct dfl_afu *afu;119	int ret = 0;120 121	mutex_lock(&pdata->lock);122	afu = dfl_fpga_pdata_get_private(pdata);123	region = get_region_by_index(afu, region_index);124	if (!region) {125		ret = -EINVAL;126		goto exit;127	}128	*pregion = *region;129exit:130	mutex_unlock(&pdata->lock);131	return ret;132}133 134/**135 * afu_mmio_region_get_by_offset - find an afu mmio region by offset and size136 *137 * @pdata: afu platform device's pdata.138 * @offset: region offset from start of the device fd.139 * @size: region size.140 * @pregion: ptr to region for result.141 *142 * Find the region which fully contains the region described by input143 * parameters (offset and size) from the feature dev's region linked list.144 *145 * Return: 0 on success, negative error code otherwise.146 */147int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,148				  u64 offset, u64 size,149				  struct dfl_afu_mmio_region *pregion)150{151	struct dfl_afu_mmio_region *region;152	struct dfl_afu *afu;153	int ret = 0;154 155	mutex_lock(&pdata->lock);156	afu = dfl_fpga_pdata_get_private(pdata);157	for_each_region(region, afu)158		if (region->offset <= offset &&159		    region->offset + region->size >= offset + size) {160			*pregion = *region;161			goto exit;162		}163	ret = -EINVAL;164exit:165	mutex_unlock(&pdata->lock);166	return ret;167}168