at v5.2-rc7 1056 lines 27 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Driver for FPGA Device Feature List (DFL) Support 4 * 5 * Copyright (C) 2017-2018 Intel Corporation, Inc. 6 * 7 * Authors: 8 * Kang Luwei <luwei.kang@intel.com> 9 * Zhang Yi <yi.z.zhang@intel.com> 10 * Wu Hao <hao.wu@intel.com> 11 * Xiao Guangrong <guangrong.xiao@linux.intel.com> 12 */ 13#include <linux/module.h> 14 15#include "dfl.h" 16 17static DEFINE_MUTEX(dfl_id_mutex); 18 19/* 20 * when adding a new feature dev support in DFL framework, it's required to 21 * add a new item in enum dfl_id_type and provide related information in below 22 * dfl_devs table which is indexed by dfl_id_type, e.g. name string used for 23 * platform device creation (define name strings in dfl.h, as they could be 24 * reused by platform device drivers). 25 * 26 * if the new feature dev needs chardev support, then it's required to add 27 * a new item in dfl_chardevs table and configure dfl_devs[i].devt_type as 28 * index to dfl_chardevs table. If no chardev support just set devt_type 29 * as one invalid index (DFL_FPGA_DEVT_MAX). 30 */ 31enum dfl_id_type { 32 FME_ID, /* fme id allocation and mapping */ 33 PORT_ID, /* port id allocation and mapping */ 34 DFL_ID_MAX, 35}; 36 37enum dfl_fpga_devt_type { 38 DFL_FPGA_DEVT_FME, 39 DFL_FPGA_DEVT_PORT, 40 DFL_FPGA_DEVT_MAX, 41}; 42 43static struct lock_class_key dfl_pdata_keys[DFL_ID_MAX]; 44 45static const char *dfl_pdata_key_strings[DFL_ID_MAX] = { 46 "dfl-fme-pdata", 47 "dfl-port-pdata", 48}; 49 50/** 51 * dfl_dev_info - dfl feature device information. 52 * @name: name string of the feature platform device. 53 * @dfh_id: id value in Device Feature Header (DFH) register by DFL spec. 54 * @id: idr id of the feature dev. 55 * @devt_type: index to dfl_chrdevs[]. 56 */ 57struct dfl_dev_info { 58 const char *name; 59 u32 dfh_id; 60 struct idr id; 61 enum dfl_fpga_devt_type devt_type; 62}; 63 64/* it is indexed by dfl_id_type */ 65static struct dfl_dev_info dfl_devs[] = { 66 {.name = DFL_FPGA_FEATURE_DEV_FME, .dfh_id = DFH_ID_FIU_FME, 67 .devt_type = DFL_FPGA_DEVT_FME}, 68 {.name = DFL_FPGA_FEATURE_DEV_PORT, .dfh_id = DFH_ID_FIU_PORT, 69 .devt_type = DFL_FPGA_DEVT_PORT}, 70}; 71 72/** 73 * dfl_chardev_info - chardev information of dfl feature device 74 * @name: nmae string of the char device. 75 * @devt: devt of the char device. 76 */ 77struct dfl_chardev_info { 78 const char *name; 79 dev_t devt; 80}; 81 82/* indexed by enum dfl_fpga_devt_type */ 83static struct dfl_chardev_info dfl_chrdevs[] = { 84 {.name = DFL_FPGA_FEATURE_DEV_FME}, 85 {.name = DFL_FPGA_FEATURE_DEV_PORT}, 86}; 87 88static void dfl_ids_init(void) 89{ 90 int i; 91 92 for (i = 0; i < ARRAY_SIZE(dfl_devs); i++) 93 idr_init(&dfl_devs[i].id); 94} 95 96static void dfl_ids_destroy(void) 97{ 98 int i; 99 100 for (i = 0; i < ARRAY_SIZE(dfl_devs); i++) 101 idr_destroy(&dfl_devs[i].id); 102} 103 104static int dfl_id_alloc(enum dfl_id_type type, struct device *dev) 105{ 106 int id; 107 108 WARN_ON(type >= DFL_ID_MAX); 109 mutex_lock(&dfl_id_mutex); 110 id = idr_alloc(&dfl_devs[type].id, dev, 0, 0, GFP_KERNEL); 111 mutex_unlock(&dfl_id_mutex); 112 113 return id; 114} 115 116static void dfl_id_free(enum dfl_id_type type, int id) 117{ 118 WARN_ON(type >= DFL_ID_MAX); 119 mutex_lock(&dfl_id_mutex); 120 idr_remove(&dfl_devs[type].id, id); 121 mutex_unlock(&dfl_id_mutex); 122} 123 124static enum dfl_id_type feature_dev_id_type(struct platform_device *pdev) 125{ 126 int i; 127 128 for (i = 0; i < ARRAY_SIZE(dfl_devs); i++) 129 if (!strcmp(dfl_devs[i].name, pdev->name)) 130 return i; 131 132 return DFL_ID_MAX; 133} 134 135static enum dfl_id_type dfh_id_to_type(u32 id) 136{ 137 int i; 138 139 for (i = 0; i < ARRAY_SIZE(dfl_devs); i++) 140 if (dfl_devs[i].dfh_id == id) 141 return i; 142 143 return DFL_ID_MAX; 144} 145 146/* 147 * introduce a global port_ops list, it allows port drivers to register ops 148 * in such list, then other feature devices (e.g. FME), could use the port 149 * functions even related port platform device is hidden. Below is one example, 150 * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is 151 * enabled, port (and it's AFU) is turned into VF and port platform device 152 * is hidden from system but it's still required to access port to finish FPGA 153 * reconfiguration function in FME. 154 */ 155 156static DEFINE_MUTEX(dfl_port_ops_mutex); 157static LIST_HEAD(dfl_port_ops_list); 158 159/** 160 * dfl_fpga_port_ops_get - get matched port ops from the global list 161 * @pdev: platform device to match with associated port ops. 162 * Return: matched port ops on success, NULL otherwise. 163 * 164 * Please note that must dfl_fpga_port_ops_put after use the port_ops. 165 */ 166struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev) 167{ 168 struct dfl_fpga_port_ops *ops = NULL; 169 170 mutex_lock(&dfl_port_ops_mutex); 171 if (list_empty(&dfl_port_ops_list)) 172 goto done; 173 174 list_for_each_entry(ops, &dfl_port_ops_list, node) { 175 /* match port_ops using the name of platform device */ 176 if (!strcmp(pdev->name, ops->name)) { 177 if (!try_module_get(ops->owner)) 178 ops = NULL; 179 goto done; 180 } 181 } 182 183 ops = NULL; 184done: 185 mutex_unlock(&dfl_port_ops_mutex); 186 return ops; 187} 188EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_get); 189 190/** 191 * dfl_fpga_port_ops_put - put port ops 192 * @ops: port ops. 193 */ 194void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops) 195{ 196 if (ops && ops->owner) 197 module_put(ops->owner); 198} 199EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_put); 200 201/** 202 * dfl_fpga_port_ops_add - add port_ops to global list 203 * @ops: port ops to add. 204 */ 205void dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops) 206{ 207 mutex_lock(&dfl_port_ops_mutex); 208 list_add_tail(&ops->node, &dfl_port_ops_list); 209 mutex_unlock(&dfl_port_ops_mutex); 210} 211EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_add); 212 213/** 214 * dfl_fpga_port_ops_del - remove port_ops from global list 215 * @ops: port ops to del. 216 */ 217void dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops) 218{ 219 mutex_lock(&dfl_port_ops_mutex); 220 list_del(&ops->node); 221 mutex_unlock(&dfl_port_ops_mutex); 222} 223EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del); 224 225/** 226 * dfl_fpga_check_port_id - check the port id 227 * @pdev: port platform device. 228 * @pport_id: port id to compare. 229 * 230 * Return: 1 if port device matches with given port id, otherwise 0. 231 */ 232int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id) 233{ 234 struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev); 235 int port_id; 236 237 if (!port_ops || !port_ops->get_id) 238 return 0; 239 240 port_id = port_ops->get_id(pdev); 241 dfl_fpga_port_ops_put(port_ops); 242 243 return port_id == *(int *)pport_id; 244} 245EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id); 246 247/** 248 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device 249 * @pdev: feature device. 250 */ 251void dfl_fpga_dev_feature_uinit(struct platform_device *pdev) 252{ 253 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 254 struct dfl_feature *feature; 255 256 dfl_fpga_dev_for_each_feature(pdata, feature) 257 if (feature->ops) { 258 feature->ops->uinit(pdev, feature); 259 feature->ops = NULL; 260 } 261} 262EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit); 263 264static int dfl_feature_instance_init(struct platform_device *pdev, 265 struct dfl_feature_platform_data *pdata, 266 struct dfl_feature *feature, 267 struct dfl_feature_driver *drv) 268{ 269 int ret; 270 271 ret = drv->ops->init(pdev, feature); 272 if (ret) 273 return ret; 274 275 feature->ops = drv->ops; 276 277 return ret; 278} 279 280/** 281 * dfl_fpga_dev_feature_init - init for sub features of dfl feature device 282 * @pdev: feature device. 283 * @feature_drvs: drvs for sub features. 284 * 285 * This function will match sub features with given feature drvs list and 286 * use matched drv to init related sub feature. 287 * 288 * Return: 0 on success, negative error code otherwise. 289 */ 290int dfl_fpga_dev_feature_init(struct platform_device *pdev, 291 struct dfl_feature_driver *feature_drvs) 292{ 293 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 294 struct dfl_feature_driver *drv = feature_drvs; 295 struct dfl_feature *feature; 296 int ret; 297 298 while (drv->ops) { 299 dfl_fpga_dev_for_each_feature(pdata, feature) { 300 /* match feature and drv using id */ 301 if (feature->id == drv->id) { 302 ret = dfl_feature_instance_init(pdev, pdata, 303 feature, drv); 304 if (ret) 305 goto exit; 306 } 307 } 308 drv++; 309 } 310 311 return 0; 312exit: 313 dfl_fpga_dev_feature_uinit(pdev); 314 return ret; 315} 316EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_init); 317 318static void dfl_chardev_uinit(void) 319{ 320 int i; 321 322 for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) 323 if (MAJOR(dfl_chrdevs[i].devt)) { 324 unregister_chrdev_region(dfl_chrdevs[i].devt, 325 MINORMASK + 1); 326 dfl_chrdevs[i].devt = MKDEV(0, 0); 327 } 328} 329 330static int dfl_chardev_init(void) 331{ 332 int i, ret; 333 334 for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) { 335 ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0, 336 MINORMASK + 1, dfl_chrdevs[i].name); 337 if (ret) 338 goto exit; 339 } 340 341 return 0; 342 343exit: 344 dfl_chardev_uinit(); 345 return ret; 346} 347 348static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id) 349{ 350 if (type >= DFL_FPGA_DEVT_MAX) 351 return 0; 352 353 return MKDEV(MAJOR(dfl_chrdevs[type].devt), id); 354} 355 356/** 357 * dfl_fpga_dev_ops_register - register cdev ops for feature dev 358 * 359 * @pdev: feature dev. 360 * @fops: file operations for feature dev's cdev. 361 * @owner: owning module/driver. 362 * 363 * Return: 0 on success, negative error code otherwise. 364 */ 365int dfl_fpga_dev_ops_register(struct platform_device *pdev, 366 const struct file_operations *fops, 367 struct module *owner) 368{ 369 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 370 371 cdev_init(&pdata->cdev, fops); 372 pdata->cdev.owner = owner; 373 374 /* 375 * set parent to the feature device so that its refcount is 376 * decreased after the last refcount of cdev is gone, that 377 * makes sure the feature device is valid during device 378 * file's life-cycle. 379 */ 380 pdata->cdev.kobj.parent = &pdev->dev.kobj; 381 382 return cdev_add(&pdata->cdev, pdev->dev.devt, 1); 383} 384EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_register); 385 386/** 387 * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev 388 * @pdev: feature dev. 389 */ 390void dfl_fpga_dev_ops_unregister(struct platform_device *pdev) 391{ 392 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 393 394 cdev_del(&pdata->cdev); 395} 396EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister); 397 398/** 399 * struct build_feature_devs_info - info collected during feature dev build. 400 * 401 * @dev: device to enumerate. 402 * @cdev: the container device for all feature devices. 403 * @feature_dev: current feature device. 404 * @ioaddr: header register region address of feature device in enumeration. 405 * @sub_features: a sub features linked list for feature device in enumeration. 406 * @feature_num: number of sub features for feature device in enumeration. 407 */ 408struct build_feature_devs_info { 409 struct device *dev; 410 struct dfl_fpga_cdev *cdev; 411 struct platform_device *feature_dev; 412 void __iomem *ioaddr; 413 struct list_head sub_features; 414 int feature_num; 415}; 416 417/** 418 * struct dfl_feature_info - sub feature info collected during feature dev build 419 * 420 * @fid: id of this sub feature. 421 * @mmio_res: mmio resource of this sub feature. 422 * @ioaddr: mapped base address of mmio resource. 423 * @node: node in sub_features linked list. 424 */ 425struct dfl_feature_info { 426 u64 fid; 427 struct resource mmio_res; 428 void __iomem *ioaddr; 429 struct list_head node; 430}; 431 432static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev, 433 struct platform_device *port) 434{ 435 struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev); 436 437 mutex_lock(&cdev->lock); 438 list_add(&pdata->node, &cdev->port_dev_list); 439 get_device(&pdata->dev->dev); 440 mutex_unlock(&cdev->lock); 441} 442 443/* 444 * register current feature device, it is called when we need to switch to 445 * another feature parsing or we have parsed all features on given device 446 * feature list. 447 */ 448static int build_info_commit_dev(struct build_feature_devs_info *binfo) 449{ 450 struct platform_device *fdev = binfo->feature_dev; 451 struct dfl_feature_platform_data *pdata; 452 struct dfl_feature_info *finfo, *p; 453 enum dfl_id_type type; 454 int ret, index = 0; 455 456 if (!fdev) 457 return 0; 458 459 type = feature_dev_id_type(fdev); 460 if (WARN_ON_ONCE(type >= DFL_ID_MAX)) 461 return -EINVAL; 462 463 /* 464 * we do not need to care for the memory which is associated with 465 * the platform device. After calling platform_device_unregister(), 466 * it will be automatically freed by device's release() callback, 467 * platform_device_release(). 468 */ 469 pdata = kzalloc(dfl_feature_platform_data_size(binfo->feature_num), 470 GFP_KERNEL); 471 if (!pdata) 472 return -ENOMEM; 473 474 pdata->dev = fdev; 475 pdata->num = binfo->feature_num; 476 pdata->dfl_cdev = binfo->cdev; 477 mutex_init(&pdata->lock); 478 lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type], 479 dfl_pdata_key_strings[type]); 480 481 /* 482 * the count should be initialized to 0 to make sure 483 *__fpga_port_enable() following __fpga_port_disable() 484 * works properly for port device. 485 * and it should always be 0 for fme device. 486 */ 487 WARN_ON(pdata->disable_count); 488 489 fdev->dev.platform_data = pdata; 490 491 /* each sub feature has one MMIO resource */ 492 fdev->num_resources = binfo->feature_num; 493 fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource), 494 GFP_KERNEL); 495 if (!fdev->resource) 496 return -ENOMEM; 497 498 /* fill features and resource information for feature dev */ 499 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { 500 struct dfl_feature *feature = &pdata->features[index]; 501 502 /* save resource information for each feature */ 503 feature->id = finfo->fid; 504 feature->resource_index = index; 505 feature->ioaddr = finfo->ioaddr; 506 fdev->resource[index++] = finfo->mmio_res; 507 508 list_del(&finfo->node); 509 kfree(finfo); 510 } 511 512 ret = platform_device_add(binfo->feature_dev); 513 if (!ret) { 514 if (type == PORT_ID) 515 dfl_fpga_cdev_add_port_dev(binfo->cdev, 516 binfo->feature_dev); 517 else 518 binfo->cdev->fme_dev = 519 get_device(&binfo->feature_dev->dev); 520 /* 521 * reset it to avoid build_info_free() freeing their resource. 522 * 523 * The resource of successfully registered feature devices 524 * will be freed by platform_device_unregister(). See the 525 * comments in build_info_create_dev(). 526 */ 527 binfo->feature_dev = NULL; 528 } 529 530 return ret; 531} 532 533static int 534build_info_create_dev(struct build_feature_devs_info *binfo, 535 enum dfl_id_type type, void __iomem *ioaddr) 536{ 537 struct platform_device *fdev; 538 int ret; 539 540 if (type >= DFL_ID_MAX) 541 return -EINVAL; 542 543 /* we will create a new device, commit current device first */ 544 ret = build_info_commit_dev(binfo); 545 if (ret) 546 return ret; 547 548 /* 549 * we use -ENODEV as the initialization indicator which indicates 550 * whether the id need to be reclaimed 551 */ 552 fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV); 553 if (!fdev) 554 return -ENOMEM; 555 556 binfo->feature_dev = fdev; 557 binfo->feature_num = 0; 558 binfo->ioaddr = ioaddr; 559 INIT_LIST_HEAD(&binfo->sub_features); 560 561 fdev->id = dfl_id_alloc(type, &fdev->dev); 562 if (fdev->id < 0) 563 return fdev->id; 564 565 fdev->dev.parent = &binfo->cdev->region->dev; 566 fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id); 567 568 return 0; 569} 570 571static void build_info_free(struct build_feature_devs_info *binfo) 572{ 573 struct dfl_feature_info *finfo, *p; 574 575 /* 576 * it is a valid id, free it. See comments in 577 * build_info_create_dev() 578 */ 579 if (binfo->feature_dev && binfo->feature_dev->id >= 0) { 580 dfl_id_free(feature_dev_id_type(binfo->feature_dev), 581 binfo->feature_dev->id); 582 583 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { 584 list_del(&finfo->node); 585 kfree(finfo); 586 } 587 } 588 589 platform_device_put(binfo->feature_dev); 590 591 devm_kfree(binfo->dev, binfo); 592} 593 594static inline u32 feature_size(void __iomem *start) 595{ 596 u64 v = readq(start + DFH); 597 u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v); 598 /* workaround for private features with invalid size, use 4K instead */ 599 return ofst ? ofst : 4096; 600} 601 602static u64 feature_id(void __iomem *start) 603{ 604 u64 v = readq(start + DFH); 605 u16 id = FIELD_GET(DFH_ID, v); 606 u8 type = FIELD_GET(DFH_TYPE, v); 607 608 if (type == DFH_TYPE_FIU) 609 return FEATURE_ID_FIU_HEADER; 610 else if (type == DFH_TYPE_PRIVATE) 611 return id; 612 else if (type == DFH_TYPE_AFU) 613 return FEATURE_ID_AFU; 614 615 WARN_ON(1); 616 return 0; 617} 618 619/* 620 * when create sub feature instances, for private features, it doesn't need 621 * to provide resource size and feature id as they could be read from DFH 622 * register. For afu sub feature, its register region only contains user 623 * defined registers, so never trust any information from it, just use the 624 * resource size information provided by its parent FIU. 625 */ 626static int 627create_feature_instance(struct build_feature_devs_info *binfo, 628 struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst, 629 resource_size_t size, u64 fid) 630{ 631 struct dfl_feature_info *finfo; 632 633 /* read feature size and id if inputs are invalid */ 634 size = size ? size : feature_size(dfl->ioaddr + ofst); 635 fid = fid ? fid : feature_id(dfl->ioaddr + ofst); 636 637 if (dfl->len - ofst < size) 638 return -EINVAL; 639 640 finfo = kzalloc(sizeof(*finfo), GFP_KERNEL); 641 if (!finfo) 642 return -ENOMEM; 643 644 finfo->fid = fid; 645 finfo->mmio_res.start = dfl->start + ofst; 646 finfo->mmio_res.end = finfo->mmio_res.start + size - 1; 647 finfo->mmio_res.flags = IORESOURCE_MEM; 648 finfo->ioaddr = dfl->ioaddr + ofst; 649 650 list_add_tail(&finfo->node, &binfo->sub_features); 651 binfo->feature_num++; 652 653 return 0; 654} 655 656static int parse_feature_port_afu(struct build_feature_devs_info *binfo, 657 struct dfl_fpga_enum_dfl *dfl, 658 resource_size_t ofst) 659{ 660 u64 v = readq(binfo->ioaddr + PORT_HDR_CAP); 661 u32 size = FIELD_GET(PORT_CAP_MMIO_SIZE, v) << 10; 662 663 WARN_ON(!size); 664 665 return create_feature_instance(binfo, dfl, ofst, size, FEATURE_ID_AFU); 666} 667 668static int parse_feature_afu(struct build_feature_devs_info *binfo, 669 struct dfl_fpga_enum_dfl *dfl, 670 resource_size_t ofst) 671{ 672 if (!binfo->feature_dev) { 673 dev_err(binfo->dev, "this AFU does not belong to any FIU.\n"); 674 return -EINVAL; 675 } 676 677 switch (feature_dev_id_type(binfo->feature_dev)) { 678 case PORT_ID: 679 return parse_feature_port_afu(binfo, dfl, ofst); 680 default: 681 dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n", 682 binfo->feature_dev->name); 683 } 684 685 return 0; 686} 687 688static int parse_feature_fiu(struct build_feature_devs_info *binfo, 689 struct dfl_fpga_enum_dfl *dfl, 690 resource_size_t ofst) 691{ 692 u32 id, offset; 693 u64 v; 694 int ret = 0; 695 696 v = readq(dfl->ioaddr + ofst + DFH); 697 id = FIELD_GET(DFH_ID, v); 698 699 /* create platform device for dfl feature dev */ 700 ret = build_info_create_dev(binfo, dfh_id_to_type(id), 701 dfl->ioaddr + ofst); 702 if (ret) 703 return ret; 704 705 ret = create_feature_instance(binfo, dfl, ofst, 0, 0); 706 if (ret) 707 return ret; 708 /* 709 * find and parse FIU's child AFU via its NEXT_AFU register. 710 * please note that only Port has valid NEXT_AFU pointer per spec. 711 */ 712 v = readq(dfl->ioaddr + ofst + NEXT_AFU); 713 714 offset = FIELD_GET(NEXT_AFU_NEXT_DFH_OFST, v); 715 if (offset) 716 return parse_feature_afu(binfo, dfl, ofst + offset); 717 718 dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id); 719 720 return ret; 721} 722 723static int parse_feature_private(struct build_feature_devs_info *binfo, 724 struct dfl_fpga_enum_dfl *dfl, 725 resource_size_t ofst) 726{ 727 if (!binfo->feature_dev) { 728 dev_err(binfo->dev, "the private feature %llx does not belong to any AFU.\n", 729 (unsigned long long)feature_id(dfl->ioaddr + ofst)); 730 return -EINVAL; 731 } 732 733 return create_feature_instance(binfo, dfl, ofst, 0, 0); 734} 735 736/** 737 * parse_feature - parse a feature on given device feature list 738 * 739 * @binfo: build feature devices information. 740 * @dfl: device feature list to parse 741 * @ofst: offset to feature header on this device feature list 742 */ 743static int parse_feature(struct build_feature_devs_info *binfo, 744 struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst) 745{ 746 u64 v; 747 u32 type; 748 749 v = readq(dfl->ioaddr + ofst + DFH); 750 type = FIELD_GET(DFH_TYPE, v); 751 752 switch (type) { 753 case DFH_TYPE_AFU: 754 return parse_feature_afu(binfo, dfl, ofst); 755 case DFH_TYPE_PRIVATE: 756 return parse_feature_private(binfo, dfl, ofst); 757 case DFH_TYPE_FIU: 758 return parse_feature_fiu(binfo, dfl, ofst); 759 default: 760 dev_info(binfo->dev, 761 "Feature Type %x is not supported.\n", type); 762 } 763 764 return 0; 765} 766 767static int parse_feature_list(struct build_feature_devs_info *binfo, 768 struct dfl_fpga_enum_dfl *dfl) 769{ 770 void __iomem *start = dfl->ioaddr; 771 void __iomem *end = dfl->ioaddr + dfl->len; 772 int ret = 0; 773 u32 ofst = 0; 774 u64 v; 775 776 /* walk through the device feature list via DFH's next DFH pointer. */ 777 for (; start < end; start += ofst) { 778 if (end - start < DFH_SIZE) { 779 dev_err(binfo->dev, "The region is too small to contain a feature.\n"); 780 return -EINVAL; 781 } 782 783 ret = parse_feature(binfo, dfl, start - dfl->ioaddr); 784 if (ret) 785 return ret; 786 787 v = readq(start + DFH); 788 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v); 789 790 /* stop parsing if EOL(End of List) is set or offset is 0 */ 791 if ((v & DFH_EOL) || !ofst) 792 break; 793 } 794 795 /* commit current feature device when reach the end of list */ 796 return build_info_commit_dev(binfo); 797} 798 799struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev) 800{ 801 struct dfl_fpga_enum_info *info; 802 803 get_device(dev); 804 805 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 806 if (!info) { 807 put_device(dev); 808 return NULL; 809 } 810 811 info->dev = dev; 812 INIT_LIST_HEAD(&info->dfls); 813 814 return info; 815} 816EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_alloc); 817 818void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info) 819{ 820 struct dfl_fpga_enum_dfl *tmp, *dfl; 821 struct device *dev; 822 823 if (!info) 824 return; 825 826 dev = info->dev; 827 828 /* remove all device feature lists in the list. */ 829 list_for_each_entry_safe(dfl, tmp, &info->dfls, node) { 830 list_del(&dfl->node); 831 devm_kfree(dev, dfl); 832 } 833 834 devm_kfree(dev, info); 835 put_device(dev); 836} 837EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_free); 838 839/** 840 * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info 841 * 842 * @info: ptr to dfl_fpga_enum_info 843 * @start: mmio resource address of the device feature list. 844 * @len: mmio resource length of the device feature list. 845 * @ioaddr: mapped mmio resource address of the device feature list. 846 * 847 * One FPGA device may have one or more Device Feature Lists (DFLs), use this 848 * function to add information of each DFL to common data structure for next 849 * step enumeration. 850 * 851 * Return: 0 on success, negative error code otherwise. 852 */ 853int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info, 854 resource_size_t start, resource_size_t len, 855 void __iomem *ioaddr) 856{ 857 struct dfl_fpga_enum_dfl *dfl; 858 859 dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL); 860 if (!dfl) 861 return -ENOMEM; 862 863 dfl->start = start; 864 dfl->len = len; 865 dfl->ioaddr = ioaddr; 866 867 list_add_tail(&dfl->node, &info->dfls); 868 869 return 0; 870} 871EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_dfl); 872 873static int remove_feature_dev(struct device *dev, void *data) 874{ 875 struct platform_device *pdev = to_platform_device(dev); 876 enum dfl_id_type type = feature_dev_id_type(pdev); 877 int id = pdev->id; 878 879 platform_device_unregister(pdev); 880 881 dfl_id_free(type, id); 882 883 return 0; 884} 885 886static void remove_feature_devs(struct dfl_fpga_cdev *cdev) 887{ 888 device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev); 889} 890 891/** 892 * dfl_fpga_feature_devs_enumerate - enumerate feature devices 893 * @info: information for enumeration. 894 * 895 * This function creates a container device (base FPGA region), enumerates 896 * feature devices based on the enumeration info and creates platform devices 897 * under the container device. 898 * 899 * Return: dfl_fpga_cdev struct on success, -errno on failure 900 */ 901struct dfl_fpga_cdev * 902dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info) 903{ 904 struct build_feature_devs_info *binfo; 905 struct dfl_fpga_enum_dfl *dfl; 906 struct dfl_fpga_cdev *cdev; 907 int ret = 0; 908 909 if (!info->dev) 910 return ERR_PTR(-ENODEV); 911 912 cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL); 913 if (!cdev) 914 return ERR_PTR(-ENOMEM); 915 916 cdev->region = devm_fpga_region_create(info->dev, NULL, NULL); 917 if (!cdev->region) { 918 ret = -ENOMEM; 919 goto free_cdev_exit; 920 } 921 922 cdev->parent = info->dev; 923 mutex_init(&cdev->lock); 924 INIT_LIST_HEAD(&cdev->port_dev_list); 925 926 ret = fpga_region_register(cdev->region); 927 if (ret) 928 goto free_cdev_exit; 929 930 /* create and init build info for enumeration */ 931 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL); 932 if (!binfo) { 933 ret = -ENOMEM; 934 goto unregister_region_exit; 935 } 936 937 binfo->dev = info->dev; 938 binfo->cdev = cdev; 939 940 /* 941 * start enumeration for all feature devices based on Device Feature 942 * Lists. 943 */ 944 list_for_each_entry(dfl, &info->dfls, node) { 945 ret = parse_feature_list(binfo, dfl); 946 if (ret) { 947 remove_feature_devs(cdev); 948 build_info_free(binfo); 949 goto unregister_region_exit; 950 } 951 } 952 953 build_info_free(binfo); 954 955 return cdev; 956 957unregister_region_exit: 958 fpga_region_unregister(cdev->region); 959free_cdev_exit: 960 devm_kfree(info->dev, cdev); 961 return ERR_PTR(ret); 962} 963EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_enumerate); 964 965/** 966 * dfl_fpga_feature_devs_remove - remove all feature devices 967 * @cdev: fpga container device. 968 * 969 * Remove the container device and all feature devices under given container 970 * devices. 971 */ 972void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev) 973{ 974 struct dfl_feature_platform_data *pdata, *ptmp; 975 976 remove_feature_devs(cdev); 977 978 mutex_lock(&cdev->lock); 979 if (cdev->fme_dev) { 980 /* the fme should be unregistered. */ 981 WARN_ON(device_is_registered(cdev->fme_dev)); 982 put_device(cdev->fme_dev); 983 } 984 985 list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { 986 struct platform_device *port_dev = pdata->dev; 987 988 /* the port should be unregistered. */ 989 WARN_ON(device_is_registered(&port_dev->dev)); 990 list_del(&pdata->node); 991 put_device(&port_dev->dev); 992 } 993 mutex_unlock(&cdev->lock); 994 995 fpga_region_unregister(cdev->region); 996 devm_kfree(cdev->parent, cdev); 997} 998EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove); 999 1000/** 1001 * __dfl_fpga_cdev_find_port - find a port under given container device 1002 * 1003 * @cdev: container device 1004 * @data: data passed to match function 1005 * @match: match function used to find specific port from the port device list 1006 * 1007 * Find a port device under container device. This function needs to be 1008 * invoked with lock held. 1009 * 1010 * Return: pointer to port's platform device if successful, NULL otherwise. 1011 * 1012 * NOTE: you will need to drop the device reference with put_device() after use. 1013 */ 1014struct platform_device * 1015__dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data, 1016 int (*match)(struct platform_device *, void *)) 1017{ 1018 struct dfl_feature_platform_data *pdata; 1019 struct platform_device *port_dev; 1020 1021 list_for_each_entry(pdata, &cdev->port_dev_list, node) { 1022 port_dev = pdata->dev; 1023 1024 if (match(port_dev, data) && get_device(&port_dev->dev)) 1025 return port_dev; 1026 } 1027 1028 return NULL; 1029} 1030EXPORT_SYMBOL_GPL(__dfl_fpga_cdev_find_port); 1031 1032static int __init dfl_fpga_init(void) 1033{ 1034 int ret; 1035 1036 dfl_ids_init(); 1037 1038 ret = dfl_chardev_init(); 1039 if (ret) 1040 dfl_ids_destroy(); 1041 1042 return ret; 1043} 1044 1045static void __exit dfl_fpga_exit(void) 1046{ 1047 dfl_chardev_uinit(); 1048 dfl_ids_destroy(); 1049} 1050 1051module_init(dfl_fpga_init); 1052module_exit(dfl_fpga_exit); 1053 1054MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support"); 1055MODULE_AUTHOR("Intel Corporation"); 1056MODULE_LICENSE("GPL v2");