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 int pci_epf_vepf_link(struct config_item *epf_pf_item,
 479                             struct config_item *epf_vf_item)
 480{
 481        struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
 482        struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
 483        struct pci_epf *epf_pf = epf_pf_group->epf;
 484        struct pci_epf *epf_vf = epf_vf_group->epf;
 485
 486        return pci_epf_add_vepf(epf_pf, epf_vf);
 487}
 488
 489static void pci_epf_vepf_unlink(struct config_item *epf_pf_item,
 490                                struct config_item *epf_vf_item)
 491{
 492        struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
 493        struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
 494        struct pci_epf *epf_pf = epf_pf_group->epf;
 495        struct pci_epf *epf_vf = epf_vf_group->epf;
 496
 497        pci_epf_remove_vepf(epf_pf, epf_vf);
 498}
 499
 500static void pci_epf_release(struct config_item *item)
 501{
 502        struct pci_epf_group *epf_group = to_pci_epf_group(item);
 503
 504        mutex_lock(&functions_mutex);
 505        idr_remove(&functions_idr, epf_group->index);
 506        mutex_unlock(&functions_mutex);
 507        pci_epf_destroy(epf_group->epf);
 508        kfree(epf_group);
 509}
 510
 511static struct configfs_item_operations pci_epf_ops = {
 512        .allow_link             = pci_epf_vepf_link,
 513        .drop_link              = pci_epf_vepf_unlink,
 514        .release                = pci_epf_release,
 515};
 516
 517static struct config_group *pci_epf_type_make(struct config_group *group,
 518                                              const char *name)
 519{
 520        struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item);
 521        struct config_group *epf_type_group;
 522
 523        epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group);
 524        return epf_type_group;
 525}
 526
 527static void pci_epf_type_drop(struct config_group *group,
 528                              struct config_item *item)
 529{
 530        config_item_put(item);
 531}
 532
 533static struct configfs_group_operations pci_epf_type_group_ops = {
 534        .make_group     = &pci_epf_type_make,
 535        .drop_item      = &pci_epf_type_drop,
 536};
 537
 538static const struct config_item_type pci_epf_type = {
 539        .ct_group_ops   = &pci_epf_type_group_ops,
 540        .ct_item_ops    = &pci_epf_ops,
 541        .ct_attrs       = pci_epf_attrs,
 542        .ct_owner       = THIS_MODULE,
 543};
 544
 545static void pci_epf_cfs_work(struct work_struct *work)
 546{
 547        struct pci_epf_group *epf_group;
 548        struct config_group *group;
 549
 550        epf_group = container_of(work, struct pci_epf_group, cfs_work.work);
 551        group = pci_ep_cfs_add_primary_group(epf_group);
 552        if (IS_ERR(group)) {
 553                pr_err("failed to create 'primary' EPC interface\n");
 554                return;
 555        }
 556
 557        group = pci_ep_cfs_add_secondary_group(epf_group);
 558        if (IS_ERR(group)) {
 559                pr_err("failed to create 'secondary' EPC interface\n");
 560                return;
 561        }
 562}
 563
 564static struct config_group *pci_epf_make(struct config_group *group,
 565                                         const char *name)
 566{
 567        struct pci_epf_group *epf_group;
 568        struct pci_epf *epf;
 569        char *epf_name;
 570        int index, err;
 571
 572        epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
 573        if (!epf_group)
 574                return ERR_PTR(-ENOMEM);
 575
 576        mutex_lock(&functions_mutex);
 577        index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
 578        mutex_unlock(&functions_mutex);
 579        if (index < 0) {
 580                err = index;
 581                goto free_group;
 582        }
 583
 584        epf_group->index = index;
 585
 586        config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
 587
 588        epf_name = kasprintf(GFP_KERNEL, "%s.%d",
 589                             group->cg_item.ci_name, epf_group->index);
 590        if (!epf_name) {
 591                err = -ENOMEM;
 592                goto remove_idr;
 593        }
 594
 595        epf = pci_epf_create(epf_name);
 596        if (IS_ERR(epf)) {
 597                pr_err("failed to create endpoint function device\n");
 598                err = -EINVAL;
 599                goto free_name;
 600        }
 601
 602        epf->group = &epf_group->group;
 603        epf_group->epf = epf;
 604
 605        kfree(epf_name);
 606
 607        INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work);
 608        queue_delayed_work(system_wq, &epf_group->cfs_work,
 609                           msecs_to_jiffies(1));
 610
 611        return &epf_group->group;
 612
 613free_name:
 614        kfree(epf_name);
 615
 616remove_idr:
 617        mutex_lock(&functions_mutex);
 618        idr_remove(&functions_idr, epf_group->index);
 619        mutex_unlock(&functions_mutex);
 620
 621free_group:
 622        kfree(epf_group);
 623
 624        return ERR_PTR(err);
 625}
 626
 627static void pci_epf_drop(struct config_group *group, struct config_item *item)
 628{
 629        config_item_put(item);
 630}
 631
 632static struct configfs_group_operations pci_epf_group_ops = {
 633        .make_group     = &pci_epf_make,
 634        .drop_item      = &pci_epf_drop,
 635};
 636
 637static const struct config_item_type pci_epf_group_type = {
 638        .ct_group_ops   = &pci_epf_group_ops,
 639        .ct_owner       = THIS_MODULE,
 640};
 641
 642struct config_group *pci_ep_cfs_add_epf_group(const char *name)
 643{
 644        struct config_group *group;
 645
 646        group = configfs_register_default_group(functions_group, name,
 647                                                &pci_epf_group_type);
 648        if (IS_ERR(group))
 649                pr_err("failed to register configfs group for %s function\n",
 650                       name);
 651
 652        return group;
 653}
 654EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
 655
 656void pci_ep_cfs_remove_epf_group(struct config_group *group)
 657{
 658        if (IS_ERR_OR_NULL(group))
 659                return;
 660
 661        configfs_unregister_default_group(group);
 662}
 663EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
 664
 665static const struct config_item_type pci_functions_type = {
 666        .ct_owner       = THIS_MODULE,
 667};
 668
 669static const struct config_item_type pci_controllers_type = {
 670        .ct_owner       = THIS_MODULE,
 671};
 672
 673static const struct config_item_type pci_ep_type = {
 674        .ct_owner       = THIS_MODULE,
 675};
 676
 677static struct configfs_subsystem pci_ep_cfs_subsys = {
 678        .su_group = {
 679                .cg_item = {
 680                        .ci_namebuf = "pci_ep",
 681                        .ci_type = &pci_ep_type,
 682                },
 683        },
 684        .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
 685};
 686
 687static int __init pci_ep_cfs_init(void)
 688{
 689        int ret;
 690        struct config_group *root = &pci_ep_cfs_subsys.su_group;
 691
 692        config_group_init(root);
 693
 694        ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
 695        if (ret) {
 696                pr_err("Error %d while registering subsystem %s\n",
 697                       ret, root->cg_item.ci_namebuf);
 698                goto err;
 699        }
 700
 701        functions_group = configfs_register_default_group(root, "functions",
 702                                                          &pci_functions_type);
 703        if (IS_ERR(functions_group)) {
 704                ret = PTR_ERR(functions_group);
 705                pr_err("Error %d while registering functions group\n",
 706                       ret);
 707                goto err_functions_group;
 708        }
 709
 710        controllers_group =
 711                configfs_register_default_group(root, "controllers",
 712                                                &pci_controllers_type);
 713        if (IS_ERR(controllers_group)) {
 714                ret = PTR_ERR(controllers_group);
 715                pr_err("Error %d while registering controllers group\n",
 716                       ret);
 717                goto err_controllers_group;
 718        }
 719
 720        return 0;
 721
 722err_controllers_group:
 723        configfs_unregister_default_group(functions_group);
 724
 725err_functions_group:
 726        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 727
 728err:
 729        return ret;
 730}
 731module_init(pci_ep_cfs_init);
 732
 733static void __exit pci_ep_cfs_exit(void)
 734{
 735        configfs_unregister_default_group(controllers_group);
 736        configfs_unregister_default_group(functions_group);
 737        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 738}
 739module_exit(pci_ep_cfs_exit);
 740
 741MODULE_DESCRIPTION("PCI EP CONFIGFS");
 742MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
 743MODULE_LICENSE("GPL v2");
 744