linux/drivers/pci/endpoint/pci-ep-cfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * configfs to configure the PCI endpoint
   4 *
   5 * Copyright (C) 2017 Texas Instruments
   6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/idr.h>
  11#include <linux/slab.h>
  12
  13#include <linux/pci-epc.h>
  14#include <linux/pci-epf.h>
  15#include <linux/pci-ep-cfs.h>
  16
  17static DEFINE_IDR(functions_idr);
  18static DEFINE_MUTEX(functions_mutex);
  19static struct config_group *functions_group;
  20static struct config_group *controllers_group;
  21
  22struct pci_epf_group {
  23        struct config_group group;
  24        struct config_group primary_epc_group;
  25        struct config_group secondary_epc_group;
  26        struct delayed_work cfs_work;
  27        struct pci_epf *epf;
  28        int index;
  29};
  30
  31struct pci_epc_group {
  32        struct config_group group;
  33        struct pci_epc *epc;
  34        bool start;
  35};
  36
  37static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
  38{
  39        return container_of(to_config_group(item), struct pci_epf_group, group);
  40}
  41
  42static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
  43{
  44        return container_of(to_config_group(item), struct pci_epc_group, group);
  45}
  46
  47static int pci_secondary_epc_epf_link(struct config_item *epf_item,
  48                                      struct config_item *epc_item)
  49{
  50        int ret;
  51        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
  52        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
  53        struct pci_epc *epc = epc_group->epc;
  54        struct pci_epf *epf = epf_group->epf;
  55
  56        ret = pci_epc_add_epf(epc, epf, SECONDARY_INTERFACE);
  57        if (ret)
  58                return ret;
  59
  60        ret = pci_epf_bind(epf);
  61        if (ret) {
  62                pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
  63                return ret;
  64        }
  65
  66        return 0;
  67}
  68
  69static void pci_secondary_epc_epf_unlink(struct config_item *epc_item,
  70                                         struct config_item *epf_item)
  71{
  72        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
  73        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
  74        struct pci_epc *epc;
  75        struct pci_epf *epf;
  76
  77        WARN_ON_ONCE(epc_group->start);
  78
  79        epc = epc_group->epc;
  80        epf = epf_group->epf;
  81        pci_epf_unbind(epf);
  82        pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
  83}
  84
  85static struct configfs_item_operations pci_secondary_epc_item_ops = {
  86        .allow_link     = pci_secondary_epc_epf_link,
  87        .drop_link      = pci_secondary_epc_epf_unlink,
  88};
  89
  90static const struct config_item_type pci_secondary_epc_type = {
  91        .ct_item_ops    = &pci_secondary_epc_item_ops,
  92        .ct_owner       = THIS_MODULE,
  93};
  94
  95static struct config_group
  96*pci_ep_cfs_add_secondary_group(struct pci_epf_group *epf_group)
  97{
  98        struct config_group *secondary_epc_group;
  99
 100        secondary_epc_group = &epf_group->secondary_epc_group;
 101        config_group_init_type_name(secondary_epc_group, "secondary",
 102                                    &pci_secondary_epc_type);
 103        configfs_register_group(&epf_group->group, secondary_epc_group);
 104
 105        return secondary_epc_group;
 106}
 107
 108static int pci_primary_epc_epf_link(struct config_item *epf_item,
 109                                    struct config_item *epc_item)
 110{
 111        int ret;
 112        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
 113        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 114        struct pci_epc *epc = epc_group->epc;
 115        struct pci_epf *epf = epf_group->epf;
 116
 117        ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
 118        if (ret)
 119                return ret;
 120
 121        ret = pci_epf_bind(epf);
 122        if (ret) {
 123                pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
 124                return ret;
 125        }
 126
 127        return 0;
 128}
 129
 130static void pci_primary_epc_epf_unlink(struct config_item *epc_item,
 131                                       struct config_item *epf_item)
 132{
 133        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
 134        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 135        struct pci_epc *epc;
 136        struct pci_epf *epf;
 137
 138        WARN_ON_ONCE(epc_group->start);
 139
 140        epc = epc_group->epc;
 141        epf = epf_group->epf;
 142        pci_epf_unbind(epf);
 143        pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
 144}
 145
 146static struct configfs_item_operations pci_primary_epc_item_ops = {
 147        .allow_link     = pci_primary_epc_epf_link,
 148        .drop_link      = pci_primary_epc_epf_unlink,
 149};
 150
 151static const struct config_item_type pci_primary_epc_type = {
 152        .ct_item_ops    = &pci_primary_epc_item_ops,
 153        .ct_owner       = THIS_MODULE,
 154};
 155
 156static struct config_group
 157*pci_ep_cfs_add_primary_group(struct pci_epf_group *epf_group)
 158{
 159        struct config_group *primary_epc_group = &epf_group->primary_epc_group;
 160
 161        config_group_init_type_name(primary_epc_group, "primary",
 162                                    &pci_primary_epc_type);
 163        configfs_register_group(&epf_group->group, primary_epc_group);
 164
 165        return primary_epc_group;
 166}
 167
 168static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
 169                                   size_t len)
 170{
 171        int ret;
 172        bool start;
 173        struct pci_epc *epc;
 174        struct pci_epc_group *epc_group = to_pci_epc_group(item);
 175
 176        epc = epc_group->epc;
 177
 178        ret = kstrtobool(page, &start);
 179        if (ret)
 180                return ret;
 181
 182        if (!start) {
 183                pci_epc_stop(epc);
 184                epc_group->start = 0;
 185                return len;
 186        }
 187
 188        ret = pci_epc_start(epc);
 189        if (ret) {
 190                dev_err(&epc->dev, "failed to start endpoint controller\n");
 191                return -EINVAL;
 192        }
 193
 194        epc_group->start = start;
 195
 196        return len;
 197}
 198
 199static ssize_t pci_epc_start_show(struct config_item *item, char *page)
 200{
 201        return sprintf(page, "%d\n",
 202                       to_pci_epc_group(item)->start);
 203}
 204
 205CONFIGFS_ATTR(pci_epc_, start);
 206
 207static struct configfs_attribute *pci_epc_attrs[] = {
 208        &pci_epc_attr_start,
 209        NULL,
 210};
 211
 212static int pci_epc_epf_link(struct config_item *epc_item,
 213                            struct config_item *epf_item)
 214{
 215        int ret;
 216        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
 217        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 218        struct pci_epc *epc = epc_group->epc;
 219        struct pci_epf *epf = epf_group->epf;
 220
 221        ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
 222        if (ret)
 223                return ret;
 224
 225        ret = pci_epf_bind(epf);
 226        if (ret) {
 227                pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
 228                return ret;
 229        }
 230
 231        return 0;
 232}
 233
 234static void pci_epc_epf_unlink(struct config_item *epc_item,
 235                               struct config_item *epf_item)
 236{
 237        struct pci_epc *epc;
 238        struct pci_epf *epf;
 239        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
 240        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 241
 242        WARN_ON_ONCE(epc_group->start);
 243
 244        epc = epc_group->epc;
 245        epf = epf_group->epf;
 246        pci_epf_unbind(epf);
 247        pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
 248}
 249
 250static struct configfs_item_operations pci_epc_item_ops = {
 251        .allow_link     = pci_epc_epf_link,
 252        .drop_link      = pci_epc_epf_unlink,
 253};
 254
 255static const struct config_item_type pci_epc_type = {
 256        .ct_item_ops    = &pci_epc_item_ops,
 257        .ct_attrs       = pci_epc_attrs,
 258        .ct_owner       = THIS_MODULE,
 259};
 260
 261struct config_group *pci_ep_cfs_add_epc_group(const char *name)
 262{
 263        int ret;
 264        struct pci_epc *epc;
 265        struct config_group *group;
 266        struct pci_epc_group *epc_group;
 267
 268        epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
 269        if (!epc_group) {
 270                ret = -ENOMEM;
 271                goto err;
 272        }
 273
 274        group = &epc_group->group;
 275
 276        config_group_init_type_name(group, name, &pci_epc_type);
 277        ret = configfs_register_group(controllers_group, group);
 278        if (ret) {
 279                pr_err("failed to register configfs group for %s\n", name);
 280                goto err_register_group;
 281        }
 282
 283        epc = pci_epc_get(name);
 284        if (IS_ERR(epc)) {
 285                ret = PTR_ERR(epc);
 286                goto err_epc_get;
 287        }
 288
 289        epc_group->epc = epc;
 290
 291        return group;
 292
 293err_epc_get:
 294        configfs_unregister_group(group);
 295
 296err_register_group:
 297        kfree(epc_group);
 298
 299err:
 300        return ERR_PTR(ret);
 301}
 302EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
 303
 304void pci_ep_cfs_remove_epc_group(struct config_group *group)
 305{
 306        struct pci_epc_group *epc_group;
 307
 308        if (!group)
 309                return;
 310
 311        epc_group = container_of(group, struct pci_epc_group, group);
 312        pci_epc_put(epc_group->epc);
 313        configfs_unregister_group(&epc_group->group);
 314        kfree(epc_group);
 315}
 316EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
 317
 318#define PCI_EPF_HEADER_R(_name)                                                \
 319static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page)    \
 320{                                                                              \
 321        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 322        if (WARN_ON_ONCE(!epf->header))                                        \
 323                return -EINVAL;                                                \
 324        return sprintf(page, "0x%04x\n", epf->header->_name);                  \
 325}
 326
 327#define PCI_EPF_HEADER_W_u32(_name)                                            \
 328static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 329                                       const char *page, size_t len)           \
 330{                                                                              \
 331        u32 val;                                                               \
 332        int ret;                                                               \
 333        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 334        if (WARN_ON_ONCE(!epf->header))                                        \
 335                return -EINVAL;                                                \
 336        ret = kstrtou32(page, 0, &val);                                        \
 337        if (ret)                                                               \
 338                return ret;                                                    \
 339        epf->header->_name = val;                                              \
 340        return len;                                                            \
 341}
 342
 343#define PCI_EPF_HEADER_W_u16(_name)                                            \
 344static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 345                                       const char *page, size_t len)           \
 346{                                                                              \
 347        u16 val;                                                               \
 348        int ret;                                                               \
 349        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 350        if (WARN_ON_ONCE(!epf->header))                                        \
 351                return -EINVAL;                                                \
 352        ret = kstrtou16(page, 0, &val);                                        \
 353        if (ret)                                                               \
 354                return ret;                                                    \
 355        epf->header->_name = val;                                              \
 356        return len;                                                            \
 357}
 358
 359#define PCI_EPF_HEADER_W_u8(_name)                                             \
 360static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 361                                       const char *page, size_t len)           \
 362{                                                                              \
 363        u8 val;                                                                \
 364        int ret;                                                               \
 365        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 366        if (WARN_ON_ONCE(!epf->header))                                        \
 367                return -EINVAL;                                                \
 368        ret = kstrtou8(page, 0, &val);                                         \
 369        if (ret)                                                               \
 370                return ret;                                                    \
 371        epf->header->_name = val;                                              \
 372        return len;                                                            \
 373}
 374
 375static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
 376                                            const char *page, size_t len)
 377{
 378        u8 val;
 379        int ret;
 380
 381        ret = kstrtou8(page, 0, &val);
 382        if (ret)
 383                return ret;
 384
 385        to_pci_epf_group(item)->epf->msi_interrupts = val;
 386
 387        return len;
 388}
 389
 390static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
 391                                           char *page)
 392{
 393        return sprintf(page, "%d\n",
 394                       to_pci_epf_group(item)->epf->msi_interrupts);
 395}
 396
 397static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
 398                                             const char *page, size_t len)
 399{
 400        u16 val;
 401        int ret;
 402
 403        ret = kstrtou16(page, 0, &val);
 404        if (ret)
 405                return ret;
 406
 407        to_pci_epf_group(item)->epf->msix_interrupts = val;
 408
 409        return len;
 410}
 411
 412static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
 413                                            char *page)
 414{
 415        return sprintf(page, "%d\n",
 416                       to_pci_epf_group(item)->epf->msix_interrupts);
 417}
 418
 419PCI_EPF_HEADER_R(vendorid)
 420PCI_EPF_HEADER_W_u16(vendorid)
 421
 422PCI_EPF_HEADER_R(deviceid)
 423PCI_EPF_HEADER_W_u16(deviceid)
 424
 425PCI_EPF_HEADER_R(revid)
 426PCI_EPF_HEADER_W_u8(revid)
 427
 428PCI_EPF_HEADER_R(progif_code)
 429PCI_EPF_HEADER_W_u8(progif_code)
 430
 431PCI_EPF_HEADER_R(subclass_code)
 432PCI_EPF_HEADER_W_u8(subclass_code)
 433
 434PCI_EPF_HEADER_R(baseclass_code)
 435PCI_EPF_HEADER_W_u8(baseclass_code)
 436
 437PCI_EPF_HEADER_R(cache_line_size)
 438PCI_EPF_HEADER_W_u8(cache_line_size)
 439
 440PCI_EPF_HEADER_R(subsys_vendor_id)
 441PCI_EPF_HEADER_W_u16(subsys_vendor_id)
 442
 443PCI_EPF_HEADER_R(subsys_id)
 444PCI_EPF_HEADER_W_u16(subsys_id)
 445
 446PCI_EPF_HEADER_R(interrupt_pin)
 447PCI_EPF_HEADER_W_u8(interrupt_pin)
 448
 449CONFIGFS_ATTR(pci_epf_, vendorid);
 450CONFIGFS_ATTR(pci_epf_, deviceid);
 451CONFIGFS_ATTR(pci_epf_, revid);
 452CONFIGFS_ATTR(pci_epf_, progif_code);
 453CONFIGFS_ATTR(pci_epf_, subclass_code);
 454CONFIGFS_ATTR(pci_epf_, baseclass_code);
 455CONFIGFS_ATTR(pci_epf_, cache_line_size);
 456CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
 457CONFIGFS_ATTR(pci_epf_, subsys_id);
 458CONFIGFS_ATTR(pci_epf_, interrupt_pin);
 459CONFIGFS_ATTR(pci_epf_, msi_interrupts);
 460CONFIGFS_ATTR(pci_epf_, msix_interrupts);
 461
 462static struct configfs_attribute *pci_epf_attrs[] = {
 463        &pci_epf_attr_vendorid,
 464        &pci_epf_attr_deviceid,
 465        &pci_epf_attr_revid,
 466        &pci_epf_attr_progif_code,
 467        &pci_epf_attr_subclass_code,
 468        &pci_epf_attr_baseclass_code,
 469        &pci_epf_attr_cache_line_size,
 470        &pci_epf_attr_subsys_vendor_id,
 471        &pci_epf_attr_subsys_id,
 472        &pci_epf_attr_interrupt_pin,
 473        &pci_epf_attr_msi_interrupts,
 474        &pci_epf_attr_msix_interrupts,
 475        NULL,
 476};
 477
 478static void pci_epf_release(struct config_item *item)
 479{
 480        struct pci_epf_group *epf_group = to_pci_epf_group(item);
 481
 482        mutex_lock(&functions_mutex);
 483        idr_remove(&functions_idr, epf_group->index);
 484        mutex_unlock(&functions_mutex);
 485        pci_epf_destroy(epf_group->epf);
 486        kfree(epf_group);
 487}
 488
 489static struct configfs_item_operations pci_epf_ops = {
 490        .release                = pci_epf_release,
 491};
 492
 493static struct config_group *pci_epf_type_make(struct config_group *group,
 494                                              const char *name)
 495{
 496        struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item);
 497        struct config_group *epf_type_group;
 498
 499        epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group);
 500        return epf_type_group;
 501}
 502
 503static void pci_epf_type_drop(struct config_group *group,
 504                              struct config_item *item)
 505{
 506        config_item_put(item);
 507}
 508
 509static struct configfs_group_operations pci_epf_type_group_ops = {
 510        .make_group     = &pci_epf_type_make,
 511        .drop_item      = &pci_epf_type_drop,
 512};
 513
 514static const struct config_item_type pci_epf_type = {
 515        .ct_group_ops   = &pci_epf_type_group_ops,
 516        .ct_item_ops    = &pci_epf_ops,
 517        .ct_attrs       = pci_epf_attrs,
 518        .ct_owner       = THIS_MODULE,
 519};
 520
 521static void pci_epf_cfs_work(struct work_struct *work)
 522{
 523        struct pci_epf_group *epf_group;
 524        struct config_group *group;
 525
 526        epf_group = container_of(work, struct pci_epf_group, cfs_work.work);
 527        group = pci_ep_cfs_add_primary_group(epf_group);
 528        if (IS_ERR(group)) {
 529                pr_err("failed to create 'primary' EPC interface\n");
 530                return;
 531        }
 532
 533        group = pci_ep_cfs_add_secondary_group(epf_group);
 534        if (IS_ERR(group)) {
 535                pr_err("failed to create 'secondary' EPC interface\n");
 536                return;
 537        }
 538}
 539
 540static struct config_group *pci_epf_make(struct config_group *group,
 541                                         const char *name)
 542{
 543        struct pci_epf_group *epf_group;
 544        struct pci_epf *epf;
 545        char *epf_name;
 546        int index, err;
 547
 548        epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
 549        if (!epf_group)
 550                return ERR_PTR(-ENOMEM);
 551
 552        mutex_lock(&functions_mutex);
 553        index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
 554        mutex_unlock(&functions_mutex);
 555        if (index < 0) {
 556                err = index;
 557                goto free_group;
 558        }
 559
 560        epf_group->index = index;
 561
 562        config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
 563
 564        epf_name = kasprintf(GFP_KERNEL, "%s.%d",
 565                             group->cg_item.ci_name, epf_group->index);
 566        if (!epf_name) {
 567                err = -ENOMEM;
 568                goto remove_idr;
 569        }
 570
 571        epf = pci_epf_create(epf_name);
 572        if (IS_ERR(epf)) {
 573                pr_err("failed to create endpoint function device\n");
 574                err = -EINVAL;
 575                goto free_name;
 576        }
 577
 578        epf->group = &epf_group->group;
 579        epf_group->epf = epf;
 580
 581        kfree(epf_name);
 582
 583        INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work);
 584        queue_delayed_work(system_wq, &epf_group->cfs_work,
 585                           msecs_to_jiffies(1));
 586
 587        return &epf_group->group;
 588
 589free_name:
 590        kfree(epf_name);
 591
 592remove_idr:
 593        mutex_lock(&functions_mutex);
 594        idr_remove(&functions_idr, epf_group->index);
 595        mutex_unlock(&functions_mutex);
 596
 597free_group:
 598        kfree(epf_group);
 599
 600        return ERR_PTR(err);
 601}
 602
 603static void pci_epf_drop(struct config_group *group, struct config_item *item)
 604{
 605        config_item_put(item);
 606}
 607
 608static struct configfs_group_operations pci_epf_group_ops = {
 609        .make_group     = &pci_epf_make,
 610        .drop_item      = &pci_epf_drop,
 611};
 612
 613static const struct config_item_type pci_epf_group_type = {
 614        .ct_group_ops   = &pci_epf_group_ops,
 615        .ct_owner       = THIS_MODULE,
 616};
 617
 618struct config_group *pci_ep_cfs_add_epf_group(const char *name)
 619{
 620        struct config_group *group;
 621
 622        group = configfs_register_default_group(functions_group, name,
 623                                                &pci_epf_group_type);
 624        if (IS_ERR(group))
 625                pr_err("failed to register configfs group for %s function\n",
 626                       name);
 627
 628        return group;
 629}
 630EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
 631
 632void pci_ep_cfs_remove_epf_group(struct config_group *group)
 633{
 634        if (IS_ERR_OR_NULL(group))
 635                return;
 636
 637        configfs_unregister_default_group(group);
 638}
 639EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
 640
 641static const struct config_item_type pci_functions_type = {
 642        .ct_owner       = THIS_MODULE,
 643};
 644
 645static const struct config_item_type pci_controllers_type = {
 646        .ct_owner       = THIS_MODULE,
 647};
 648
 649static const struct config_item_type pci_ep_type = {
 650        .ct_owner       = THIS_MODULE,
 651};
 652
 653static struct configfs_subsystem pci_ep_cfs_subsys = {
 654        .su_group = {
 655                .cg_item = {
 656                        .ci_namebuf = "pci_ep",
 657                        .ci_type = &pci_ep_type,
 658                },
 659        },
 660        .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
 661};
 662
 663static int __init pci_ep_cfs_init(void)
 664{
 665        int ret;
 666        struct config_group *root = &pci_ep_cfs_subsys.su_group;
 667
 668        config_group_init(root);
 669
 670        ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
 671        if (ret) {
 672                pr_err("Error %d while registering subsystem %s\n",
 673                       ret, root->cg_item.ci_namebuf);
 674                goto err;
 675        }
 676
 677        functions_group = configfs_register_default_group(root, "functions",
 678                                                          &pci_functions_type);
 679        if (IS_ERR(functions_group)) {
 680                ret = PTR_ERR(functions_group);
 681                pr_err("Error %d while registering functions group\n",
 682                       ret);
 683                goto err_functions_group;
 684        }
 685
 686        controllers_group =
 687                configfs_register_default_group(root, "controllers",
 688                                                &pci_controllers_type);
 689        if (IS_ERR(controllers_group)) {
 690                ret = PTR_ERR(controllers_group);
 691                pr_err("Error %d while registering controllers group\n",
 692                       ret);
 693                goto err_controllers_group;
 694        }
 695
 696        return 0;
 697
 698err_controllers_group:
 699        configfs_unregister_default_group(functions_group);
 700
 701err_functions_group:
 702        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 703
 704err:
 705        return ret;
 706}
 707module_init(pci_ep_cfs_init);
 708
 709static void __exit pci_ep_cfs_exit(void)
 710{
 711        configfs_unregister_default_group(controllers_group);
 712        configfs_unregister_default_group(functions_group);
 713        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 714}
 715module_exit(pci_ep_cfs_exit);
 716
 717MODULE_DESCRIPTION("PCI EP CONFIGFS");
 718MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
 719MODULE_LICENSE("GPL v2");
 720