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

dfl-fme-main.c (19341B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for FPGA Management Engine (FME)
      4 *
      5 * Copyright (C) 2017-2018 Intel Corporation, Inc.
      6 *
      7 * Authors:
      8 *   Kang Luwei <luwei.kang@intel.com>
      9 *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
     10 *   Joseph Grecco <joe.grecco@intel.com>
     11 *   Enno Luebbers <enno.luebbers@intel.com>
     12 *   Tim Whisonant <tim.whisonant@intel.com>
     13 *   Ananda Ravuri <ananda.ravuri@intel.com>
     14 *   Henry Mitchel <henry.mitchel@intel.com>
     15 */
     16
     17#include <linux/hwmon.h>
     18#include <linux/hwmon-sysfs.h>
     19#include <linux/kernel.h>
     20#include <linux/module.h>
     21#include <linux/uaccess.h>
     22#include <linux/fpga-dfl.h>
     23
     24#include "dfl.h"
     25#include "dfl-fme.h"
     26
     27static ssize_t ports_num_show(struct device *dev,
     28			      struct device_attribute *attr, char *buf)
     29{
     30	void __iomem *base;
     31	u64 v;
     32
     33	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
     34
     35	v = readq(base + FME_HDR_CAP);
     36
     37	return scnprintf(buf, PAGE_SIZE, "%u\n",
     38			 (unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
     39}
     40static DEVICE_ATTR_RO(ports_num);
     41
     42/*
     43 * Bitstream (static FPGA region) identifier number. It contains the
     44 * detailed version and other information of this static FPGA region.
     45 */
     46static ssize_t bitstream_id_show(struct device *dev,
     47				 struct device_attribute *attr, char *buf)
     48{
     49	void __iomem *base;
     50	u64 v;
     51
     52	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
     53
     54	v = readq(base + FME_HDR_BITSTREAM_ID);
     55
     56	return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
     57}
     58static DEVICE_ATTR_RO(bitstream_id);
     59
     60/*
     61 * Bitstream (static FPGA region) meta data. It contains the synthesis
     62 * date, seed and other information of this static FPGA region.
     63 */
     64static ssize_t bitstream_metadata_show(struct device *dev,
     65				       struct device_attribute *attr, char *buf)
     66{
     67	void __iomem *base;
     68	u64 v;
     69
     70	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
     71
     72	v = readq(base + FME_HDR_BITSTREAM_MD);
     73
     74	return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
     75}
     76static DEVICE_ATTR_RO(bitstream_metadata);
     77
     78static ssize_t cache_size_show(struct device *dev,
     79			       struct device_attribute *attr, char *buf)
     80{
     81	void __iomem *base;
     82	u64 v;
     83
     84	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
     85
     86	v = readq(base + FME_HDR_CAP);
     87
     88	return sprintf(buf, "%u\n",
     89		       (unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v));
     90}
     91static DEVICE_ATTR_RO(cache_size);
     92
     93static ssize_t fabric_version_show(struct device *dev,
     94				   struct device_attribute *attr, char *buf)
     95{
     96	void __iomem *base;
     97	u64 v;
     98
     99	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
    100
    101	v = readq(base + FME_HDR_CAP);
    102
    103	return sprintf(buf, "%u\n",
    104		       (unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v));
    105}
    106static DEVICE_ATTR_RO(fabric_version);
    107
    108static ssize_t socket_id_show(struct device *dev,
    109			      struct device_attribute *attr, char *buf)
    110{
    111	void __iomem *base;
    112	u64 v;
    113
    114	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
    115
    116	v = readq(base + FME_HDR_CAP);
    117
    118	return sprintf(buf, "%u\n",
    119		       (unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v));
    120}
    121static DEVICE_ATTR_RO(socket_id);
    122
    123static struct attribute *fme_hdr_attrs[] = {
    124	&dev_attr_ports_num.attr,
    125	&dev_attr_bitstream_id.attr,
    126	&dev_attr_bitstream_metadata.attr,
    127	&dev_attr_cache_size.attr,
    128	&dev_attr_fabric_version.attr,
    129	&dev_attr_socket_id.attr,
    130	NULL,
    131};
    132
    133static const struct attribute_group fme_hdr_group = {
    134	.attrs = fme_hdr_attrs,
    135};
    136
    137static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
    138				       unsigned long arg)
    139{
    140	struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
    141	int port_id;
    142
    143	if (get_user(port_id, (int __user *)arg))
    144		return -EFAULT;
    145
    146	return dfl_fpga_cdev_release_port(cdev, port_id);
    147}
    148
    149static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
    150				      unsigned long arg)
    151{
    152	struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
    153	int port_id;
    154
    155	if (get_user(port_id, (int __user *)arg))
    156		return -EFAULT;
    157
    158	return dfl_fpga_cdev_assign_port(cdev, port_id);
    159}
    160
    161static long fme_hdr_ioctl(struct platform_device *pdev,
    162			  struct dfl_feature *feature,
    163			  unsigned int cmd, unsigned long arg)
    164{
    165	struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
    166
    167	switch (cmd) {
    168	case DFL_FPGA_FME_PORT_RELEASE:
    169		return fme_hdr_ioctl_release_port(pdata, arg);
    170	case DFL_FPGA_FME_PORT_ASSIGN:
    171		return fme_hdr_ioctl_assign_port(pdata, arg);
    172	}
    173
    174	return -ENODEV;
    175}
    176
    177static const struct dfl_feature_id fme_hdr_id_table[] = {
    178	{.id = FME_FEATURE_ID_HEADER,},
    179	{0,}
    180};
    181
    182static const struct dfl_feature_ops fme_hdr_ops = {
    183	.ioctl = fme_hdr_ioctl,
    184};
    185
    186#define FME_THERM_THRESHOLD	0x8
    187#define TEMP_THRESHOLD1		GENMASK_ULL(6, 0)
    188#define TEMP_THRESHOLD1_EN	BIT_ULL(7)
    189#define TEMP_THRESHOLD2		GENMASK_ULL(14, 8)
    190#define TEMP_THRESHOLD2_EN	BIT_ULL(15)
    191#define TRIP_THRESHOLD		GENMASK_ULL(30, 24)
    192#define TEMP_THRESHOLD1_STATUS	BIT_ULL(32)		/* threshold1 reached */
    193#define TEMP_THRESHOLD2_STATUS	BIT_ULL(33)		/* threshold2 reached */
    194/* threshold1 policy: 0 - AP2 (90% throttle) / 1 - AP1 (50% throttle) */
    195#define TEMP_THRESHOLD1_POLICY	BIT_ULL(44)
    196
    197#define FME_THERM_RDSENSOR_FMT1	0x10
    198#define FPGA_TEMPERATURE	GENMASK_ULL(6, 0)
    199
    200#define FME_THERM_CAP		0x20
    201#define THERM_NO_THROTTLE	BIT_ULL(0)
    202
    203#define MD_PRE_DEG
    204
    205static bool fme_thermal_throttle_support(void __iomem *base)
    206{
    207	u64 v = readq(base + FME_THERM_CAP);
    208
    209	return FIELD_GET(THERM_NO_THROTTLE, v) ? false : true;
    210}
    211
    212static umode_t thermal_hwmon_attrs_visible(const void *drvdata,
    213					   enum hwmon_sensor_types type,
    214					   u32 attr, int channel)
    215{
    216	const struct dfl_feature *feature = drvdata;
    217
    218	/* temperature is always supported, and check hardware cap for others */
    219	if (attr == hwmon_temp_input)
    220		return 0444;
    221
    222	return fme_thermal_throttle_support(feature->ioaddr) ? 0444 : 0;
    223}
    224
    225static int thermal_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
    226			      u32 attr, int channel, long *val)
    227{
    228	struct dfl_feature *feature = dev_get_drvdata(dev);
    229	u64 v;
    230
    231	switch (attr) {
    232	case hwmon_temp_input:
    233		v = readq(feature->ioaddr + FME_THERM_RDSENSOR_FMT1);
    234		*val = (long)(FIELD_GET(FPGA_TEMPERATURE, v) * 1000);
    235		break;
    236	case hwmon_temp_max:
    237		v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    238		*val = (long)(FIELD_GET(TEMP_THRESHOLD1, v) * 1000);
    239		break;
    240	case hwmon_temp_crit:
    241		v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    242		*val = (long)(FIELD_GET(TEMP_THRESHOLD2, v) * 1000);
    243		break;
    244	case hwmon_temp_emergency:
    245		v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    246		*val = (long)(FIELD_GET(TRIP_THRESHOLD, v) * 1000);
    247		break;
    248	case hwmon_temp_max_alarm:
    249		v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    250		*val = (long)FIELD_GET(TEMP_THRESHOLD1_STATUS, v);
    251		break;
    252	case hwmon_temp_crit_alarm:
    253		v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    254		*val = (long)FIELD_GET(TEMP_THRESHOLD2_STATUS, v);
    255		break;
    256	default:
    257		return -EOPNOTSUPP;
    258	}
    259
    260	return 0;
    261}
    262
    263static const struct hwmon_ops thermal_hwmon_ops = {
    264	.is_visible = thermal_hwmon_attrs_visible,
    265	.read = thermal_hwmon_read,
    266};
    267
    268static const struct hwmon_channel_info *thermal_hwmon_info[] = {
    269	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_EMERGENCY |
    270				 HWMON_T_MAX   | HWMON_T_MAX_ALARM |
    271				 HWMON_T_CRIT  | HWMON_T_CRIT_ALARM),
    272	NULL
    273};
    274
    275static const struct hwmon_chip_info thermal_hwmon_chip_info = {
    276	.ops = &thermal_hwmon_ops,
    277	.info = thermal_hwmon_info,
    278};
    279
    280static ssize_t temp1_max_policy_show(struct device *dev,
    281				     struct device_attribute *attr, char *buf)
    282{
    283	struct dfl_feature *feature = dev_get_drvdata(dev);
    284	u64 v;
    285
    286	v = readq(feature->ioaddr + FME_THERM_THRESHOLD);
    287
    288	return sprintf(buf, "%u\n",
    289		       (unsigned int)FIELD_GET(TEMP_THRESHOLD1_POLICY, v));
    290}
    291
    292static DEVICE_ATTR_RO(temp1_max_policy);
    293
    294static struct attribute *thermal_extra_attrs[] = {
    295	&dev_attr_temp1_max_policy.attr,
    296	NULL,
    297};
    298
    299static umode_t thermal_extra_attrs_visible(struct kobject *kobj,
    300					   struct attribute *attr, int index)
    301{
    302	struct device *dev = kobj_to_dev(kobj);
    303	struct dfl_feature *feature = dev_get_drvdata(dev);
    304
    305	return fme_thermal_throttle_support(feature->ioaddr) ? attr->mode : 0;
    306}
    307
    308static const struct attribute_group thermal_extra_group = {
    309	.attrs		= thermal_extra_attrs,
    310	.is_visible	= thermal_extra_attrs_visible,
    311};
    312__ATTRIBUTE_GROUPS(thermal_extra);
    313
    314static int fme_thermal_mgmt_init(struct platform_device *pdev,
    315				 struct dfl_feature *feature)
    316{
    317	struct device *hwmon;
    318
    319	/*
    320	 * create hwmon to allow userspace monitoring temperature and other
    321	 * threshold information.
    322	 *
    323	 * temp1_input      -> FPGA device temperature
    324	 * temp1_max        -> hardware threshold 1 -> 50% or 90% throttling
    325	 * temp1_crit       -> hardware threshold 2 -> 100% throttling
    326	 * temp1_emergency  -> hardware trip_threshold to shutdown FPGA
    327	 * temp1_max_alarm  -> hardware threshold 1 alarm
    328	 * temp1_crit_alarm -> hardware threshold 2 alarm
    329	 *
    330	 * create device specific sysfs interfaces, e.g. read temp1_max_policy
    331	 * to understand the actual hardware throttling action (50% vs 90%).
    332	 *
    333	 * If hardware doesn't support automatic throttling per thresholds,
    334	 * then all above sysfs interfaces are not visible except temp1_input
    335	 * for temperature.
    336	 */
    337	hwmon = devm_hwmon_device_register_with_info(&pdev->dev,
    338						     "dfl_fme_thermal", feature,
    339						     &thermal_hwmon_chip_info,
    340						     thermal_extra_groups);
    341	if (IS_ERR(hwmon)) {
    342		dev_err(&pdev->dev, "Fail to register thermal hwmon\n");
    343		return PTR_ERR(hwmon);
    344	}
    345
    346	return 0;
    347}
    348
    349static const struct dfl_feature_id fme_thermal_mgmt_id_table[] = {
    350	{.id = FME_FEATURE_ID_THERMAL_MGMT,},
    351	{0,}
    352};
    353
    354static const struct dfl_feature_ops fme_thermal_mgmt_ops = {
    355	.init = fme_thermal_mgmt_init,
    356};
    357
    358#define FME_PWR_STATUS		0x8
    359#define FME_LATENCY_TOLERANCE	BIT_ULL(18)
    360#define PWR_CONSUMED		GENMASK_ULL(17, 0)
    361
    362#define FME_PWR_THRESHOLD	0x10
    363#define PWR_THRESHOLD1		GENMASK_ULL(6, 0)	/* in Watts */
    364#define PWR_THRESHOLD2		GENMASK_ULL(14, 8)	/* in Watts */
    365#define PWR_THRESHOLD_MAX	0x7f			/* in Watts */
    366#define PWR_THRESHOLD1_STATUS	BIT_ULL(16)
    367#define PWR_THRESHOLD2_STATUS	BIT_ULL(17)
    368
    369#define FME_PWR_XEON_LIMIT	0x18
    370#define XEON_PWR_LIMIT		GENMASK_ULL(14, 0)	/* in 0.1 Watts */
    371#define XEON_PWR_EN		BIT_ULL(15)
    372#define FME_PWR_FPGA_LIMIT	0x20
    373#define FPGA_PWR_LIMIT		GENMASK_ULL(14, 0)	/* in 0.1 Watts */
    374#define FPGA_PWR_EN		BIT_ULL(15)
    375
    376static int power_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
    377			    u32 attr, int channel, long *val)
    378{
    379	struct dfl_feature *feature = dev_get_drvdata(dev);
    380	u64 v;
    381
    382	switch (attr) {
    383	case hwmon_power_input:
    384		v = readq(feature->ioaddr + FME_PWR_STATUS);
    385		*val = (long)(FIELD_GET(PWR_CONSUMED, v) * 1000000);
    386		break;
    387	case hwmon_power_max:
    388		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    389		*val = (long)(FIELD_GET(PWR_THRESHOLD1, v) * 1000000);
    390		break;
    391	case hwmon_power_crit:
    392		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    393		*val = (long)(FIELD_GET(PWR_THRESHOLD2, v) * 1000000);
    394		break;
    395	case hwmon_power_max_alarm:
    396		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    397		*val = (long)FIELD_GET(PWR_THRESHOLD1_STATUS, v);
    398		break;
    399	case hwmon_power_crit_alarm:
    400		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    401		*val = (long)FIELD_GET(PWR_THRESHOLD2_STATUS, v);
    402		break;
    403	default:
    404		return -EOPNOTSUPP;
    405	}
    406
    407	return 0;
    408}
    409
    410static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
    411			     u32 attr, int channel, long val)
    412{
    413	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev->parent);
    414	struct dfl_feature *feature = dev_get_drvdata(dev);
    415	int ret = 0;
    416	u64 v;
    417
    418	val = clamp_val(val / 1000000, 0, PWR_THRESHOLD_MAX);
    419
    420	mutex_lock(&pdata->lock);
    421
    422	switch (attr) {
    423	case hwmon_power_max:
    424		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    425		v &= ~PWR_THRESHOLD1;
    426		v |= FIELD_PREP(PWR_THRESHOLD1, val);
    427		writeq(v, feature->ioaddr + FME_PWR_THRESHOLD);
    428		break;
    429	case hwmon_power_crit:
    430		v = readq(feature->ioaddr + FME_PWR_THRESHOLD);
    431		v &= ~PWR_THRESHOLD2;
    432		v |= FIELD_PREP(PWR_THRESHOLD2, val);
    433		writeq(v, feature->ioaddr + FME_PWR_THRESHOLD);
    434		break;
    435	default:
    436		ret = -EOPNOTSUPP;
    437		break;
    438	}
    439
    440	mutex_unlock(&pdata->lock);
    441
    442	return ret;
    443}
    444
    445static umode_t power_hwmon_attrs_visible(const void *drvdata,
    446					 enum hwmon_sensor_types type,
    447					 u32 attr, int channel)
    448{
    449	switch (attr) {
    450	case hwmon_power_input:
    451	case hwmon_power_max_alarm:
    452	case hwmon_power_crit_alarm:
    453		return 0444;
    454	case hwmon_power_max:
    455	case hwmon_power_crit:
    456		return 0644;
    457	}
    458
    459	return 0;
    460}
    461
    462static const struct hwmon_ops power_hwmon_ops = {
    463	.is_visible = power_hwmon_attrs_visible,
    464	.read = power_hwmon_read,
    465	.write = power_hwmon_write,
    466};
    467
    468static const struct hwmon_channel_info *power_hwmon_info[] = {
    469	HWMON_CHANNEL_INFO(power, HWMON_P_INPUT |
    470				  HWMON_P_MAX   | HWMON_P_MAX_ALARM |
    471				  HWMON_P_CRIT  | HWMON_P_CRIT_ALARM),
    472	NULL
    473};
    474
    475static const struct hwmon_chip_info power_hwmon_chip_info = {
    476	.ops = &power_hwmon_ops,
    477	.info = power_hwmon_info,
    478};
    479
    480static ssize_t power1_xeon_limit_show(struct device *dev,
    481				      struct device_attribute *attr, char *buf)
    482{
    483	struct dfl_feature *feature = dev_get_drvdata(dev);
    484	u16 xeon_limit = 0;
    485	u64 v;
    486
    487	v = readq(feature->ioaddr + FME_PWR_XEON_LIMIT);
    488
    489	if (FIELD_GET(XEON_PWR_EN, v))
    490		xeon_limit = FIELD_GET(XEON_PWR_LIMIT, v);
    491
    492	return sprintf(buf, "%u\n", xeon_limit * 100000);
    493}
    494
    495static ssize_t power1_fpga_limit_show(struct device *dev,
    496				      struct device_attribute *attr, char *buf)
    497{
    498	struct dfl_feature *feature = dev_get_drvdata(dev);
    499	u16 fpga_limit = 0;
    500	u64 v;
    501
    502	v = readq(feature->ioaddr + FME_PWR_FPGA_LIMIT);
    503
    504	if (FIELD_GET(FPGA_PWR_EN, v))
    505		fpga_limit = FIELD_GET(FPGA_PWR_LIMIT, v);
    506
    507	return sprintf(buf, "%u\n", fpga_limit * 100000);
    508}
    509
    510static ssize_t power1_ltr_show(struct device *dev,
    511			       struct device_attribute *attr, char *buf)
    512{
    513	struct dfl_feature *feature = dev_get_drvdata(dev);
    514	u64 v;
    515
    516	v = readq(feature->ioaddr + FME_PWR_STATUS);
    517
    518	return sprintf(buf, "%u\n",
    519		       (unsigned int)FIELD_GET(FME_LATENCY_TOLERANCE, v));
    520}
    521
    522static DEVICE_ATTR_RO(power1_xeon_limit);
    523static DEVICE_ATTR_RO(power1_fpga_limit);
    524static DEVICE_ATTR_RO(power1_ltr);
    525
    526static struct attribute *power_extra_attrs[] = {
    527	&dev_attr_power1_xeon_limit.attr,
    528	&dev_attr_power1_fpga_limit.attr,
    529	&dev_attr_power1_ltr.attr,
    530	NULL
    531};
    532
    533ATTRIBUTE_GROUPS(power_extra);
    534
    535static int fme_power_mgmt_init(struct platform_device *pdev,
    536			       struct dfl_feature *feature)
    537{
    538	struct device *hwmon;
    539
    540	hwmon = devm_hwmon_device_register_with_info(&pdev->dev,
    541						     "dfl_fme_power", feature,
    542						     &power_hwmon_chip_info,
    543						     power_extra_groups);
    544	if (IS_ERR(hwmon)) {
    545		dev_err(&pdev->dev, "Fail to register power hwmon\n");
    546		return PTR_ERR(hwmon);
    547	}
    548
    549	return 0;
    550}
    551
    552static const struct dfl_feature_id fme_power_mgmt_id_table[] = {
    553	{.id = FME_FEATURE_ID_POWER_MGMT,},
    554	{0,}
    555};
    556
    557static const struct dfl_feature_ops fme_power_mgmt_ops = {
    558	.init = fme_power_mgmt_init,
    559};
    560
    561static struct dfl_feature_driver fme_feature_drvs[] = {
    562	{
    563		.id_table = fme_hdr_id_table,
    564		.ops = &fme_hdr_ops,
    565	},
    566	{
    567		.id_table = fme_pr_mgmt_id_table,
    568		.ops = &fme_pr_mgmt_ops,
    569	},
    570	{
    571		.id_table = fme_global_err_id_table,
    572		.ops = &fme_global_err_ops,
    573	},
    574	{
    575		.id_table = fme_thermal_mgmt_id_table,
    576		.ops = &fme_thermal_mgmt_ops,
    577	},
    578	{
    579		.id_table = fme_power_mgmt_id_table,
    580		.ops = &fme_power_mgmt_ops,
    581	},
    582	{
    583		.id_table = fme_perf_id_table,
    584		.ops = &fme_perf_ops,
    585	},
    586	{
    587		.ops = NULL,
    588	},
    589};
    590
    591static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
    592				      unsigned long arg)
    593{
    594	/* No extension support for now */
    595	return 0;
    596}
    597
    598static int fme_open(struct inode *inode, struct file *filp)
    599{
    600	struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
    601	struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
    602	int ret;
    603
    604	if (WARN_ON(!pdata))
    605		return -ENODEV;
    606
    607	mutex_lock(&pdata->lock);
    608	ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
    609	if (!ret) {
    610		dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
    611			dfl_feature_dev_use_count(pdata));
    612		filp->private_data = pdata;
    613	}
    614	mutex_unlock(&pdata->lock);
    615
    616	return ret;
    617}
    618
    619static int fme_release(struct inode *inode, struct file *filp)
    620{
    621	struct dfl_feature_platform_data *pdata = filp->private_data;
    622	struct platform_device *pdev = pdata->dev;
    623	struct dfl_feature *feature;
    624
    625	dev_dbg(&pdev->dev, "Device File Release\n");
    626
    627	mutex_lock(&pdata->lock);
    628	dfl_feature_dev_use_end(pdata);
    629
    630	if (!dfl_feature_dev_use_count(pdata))
    631		dfl_fpga_dev_for_each_feature(pdata, feature)
    632			dfl_fpga_set_irq_triggers(feature, 0,
    633						  feature->nr_irqs, NULL);
    634	mutex_unlock(&pdata->lock);
    635
    636	return 0;
    637}
    638
    639static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    640{
    641	struct dfl_feature_platform_data *pdata = filp->private_data;
    642	struct platform_device *pdev = pdata->dev;
    643	struct dfl_feature *f;
    644	long ret;
    645
    646	dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
    647
    648	switch (cmd) {
    649	case DFL_FPGA_GET_API_VERSION:
    650		return DFL_FPGA_API_VERSION;
    651	case DFL_FPGA_CHECK_EXTENSION:
    652		return fme_ioctl_check_extension(pdata, arg);
    653	default:
    654		/*
    655		 * Let sub-feature's ioctl function to handle the cmd.
    656		 * Sub-feature's ioctl returns -ENODEV when cmd is not
    657		 * handled in this sub feature, and returns 0 or other
    658		 * error code if cmd is handled.
    659		 */
    660		dfl_fpga_dev_for_each_feature(pdata, f) {
    661			if (f->ops && f->ops->ioctl) {
    662				ret = f->ops->ioctl(pdev, f, cmd, arg);
    663				if (ret != -ENODEV)
    664					return ret;
    665			}
    666		}
    667	}
    668
    669	return -EINVAL;
    670}
    671
    672static int fme_dev_init(struct platform_device *pdev)
    673{
    674	struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
    675	struct dfl_fme *fme;
    676
    677	fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
    678	if (!fme)
    679		return -ENOMEM;
    680
    681	fme->pdata = pdata;
    682
    683	mutex_lock(&pdata->lock);
    684	dfl_fpga_pdata_set_private(pdata, fme);
    685	mutex_unlock(&pdata->lock);
    686
    687	return 0;
    688}
    689
    690static void fme_dev_destroy(struct platform_device *pdev)
    691{
    692	struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
    693
    694	mutex_lock(&pdata->lock);
    695	dfl_fpga_pdata_set_private(pdata, NULL);
    696	mutex_unlock(&pdata->lock);
    697}
    698
    699static const struct file_operations fme_fops = {
    700	.owner		= THIS_MODULE,
    701	.open		= fme_open,
    702	.release	= fme_release,
    703	.unlocked_ioctl = fme_ioctl,
    704};
    705
    706static int fme_probe(struct platform_device *pdev)
    707{
    708	int ret;
    709
    710	ret = fme_dev_init(pdev);
    711	if (ret)
    712		goto exit;
    713
    714	ret = dfl_fpga_dev_feature_init(pdev, fme_feature_drvs);
    715	if (ret)
    716		goto dev_destroy;
    717
    718	ret = dfl_fpga_dev_ops_register(pdev, &fme_fops, THIS_MODULE);
    719	if (ret)
    720		goto feature_uinit;
    721
    722	return 0;
    723
    724feature_uinit:
    725	dfl_fpga_dev_feature_uinit(pdev);
    726dev_destroy:
    727	fme_dev_destroy(pdev);
    728exit:
    729	return ret;
    730}
    731
    732static int fme_remove(struct platform_device *pdev)
    733{
    734	dfl_fpga_dev_ops_unregister(pdev);
    735	dfl_fpga_dev_feature_uinit(pdev);
    736	fme_dev_destroy(pdev);
    737
    738	return 0;
    739}
    740
    741static const struct attribute_group *fme_dev_groups[] = {
    742	&fme_hdr_group,
    743	&fme_global_err_group,
    744	NULL
    745};
    746
    747static struct platform_driver fme_driver = {
    748	.driver	= {
    749		.name       = DFL_FPGA_FEATURE_DEV_FME,
    750		.dev_groups = fme_dev_groups,
    751	},
    752	.probe   = fme_probe,
    753	.remove  = fme_remove,
    754};
    755
    756module_platform_driver(fme_driver);
    757
    758MODULE_DESCRIPTION("FPGA Management Engine driver");
    759MODULE_AUTHOR("Intel Corporation");
    760MODULE_LICENSE("GPL v2");
    761MODULE_ALIAS("platform:dfl-fme");