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");