linux/drivers/pci/endpoint/pci-ep-cfs.c
<<
>>
Prefs
   1/**
   2 * configfs to configure the PCI endpoint
   3 *
   4 * Copyright (C) 2017 Texas Instruments
   5 * Author: Kishon Vijay Abraham I <kishon@ti.com>
   6 *
   7 * This program is free software: you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 of
   9 * the License as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/slab.h>
  22
  23#include <linux/pci-epc.h>
  24#include <linux/pci-epf.h>
  25#include <linux/pci-ep-cfs.h>
  26
  27static struct config_group *functions_group;
  28static struct config_group *controllers_group;
  29
  30struct pci_epf_group {
  31        struct config_group group;
  32        struct pci_epf *epf;
  33};
  34
  35struct pci_epc_group {
  36        struct config_group group;
  37        struct pci_epc *epc;
  38        bool start;
  39        unsigned long function_num_map;
  40};
  41
  42static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
  43{
  44        return container_of(to_config_group(item), struct pci_epf_group, group);
  45}
  46
  47static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
  48{
  49        return container_of(to_config_group(item), struct pci_epc_group, group);
  50}
  51
  52static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
  53                                   size_t len)
  54{
  55        int ret;
  56        bool start;
  57        struct pci_epc *epc;
  58        struct pci_epc_group *epc_group = to_pci_epc_group(item);
  59
  60        epc = epc_group->epc;
  61
  62        ret = kstrtobool(page, &start);
  63        if (ret)
  64                return ret;
  65
  66        if (!start) {
  67                pci_epc_stop(epc);
  68                return len;
  69        }
  70
  71        ret = pci_epc_start(epc);
  72        if (ret) {
  73                dev_err(&epc->dev, "failed to start endpoint controller\n");
  74                return -EINVAL;
  75        }
  76
  77        epc_group->start = start;
  78
  79        return len;
  80}
  81
  82static ssize_t pci_epc_start_show(struct config_item *item, char *page)
  83{
  84        return sprintf(page, "%d\n",
  85                       to_pci_epc_group(item)->start);
  86}
  87
  88CONFIGFS_ATTR(pci_epc_, start);
  89
  90static struct configfs_attribute *pci_epc_attrs[] = {
  91        &pci_epc_attr_start,
  92        NULL,
  93};
  94
  95static int pci_epc_epf_link(struct config_item *epc_item,
  96                            struct config_item *epf_item)
  97{
  98        int ret;
  99        u32 func_no = 0;
 100        struct pci_epc *epc;
 101        struct pci_epf *epf;
 102        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
 103        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 104
 105        epc = epc_group->epc;
 106        epf = epf_group->epf;
 107        ret = pci_epc_add_epf(epc, epf);
 108        if (ret)
 109                goto err_add_epf;
 110
 111        func_no = find_first_zero_bit(&epc_group->function_num_map,
 112                                      sizeof(epc_group->function_num_map));
 113        set_bit(func_no, &epc_group->function_num_map);
 114        epf->func_no = func_no;
 115
 116        ret = pci_epf_bind(epf);
 117        if (ret)
 118                goto err_epf_bind;
 119
 120        return 0;
 121
 122err_epf_bind:
 123        pci_epc_remove_epf(epc, epf);
 124
 125err_add_epf:
 126        clear_bit(func_no, &epc_group->function_num_map);
 127
 128        return ret;
 129}
 130
 131static void pci_epc_epf_unlink(struct config_item *epc_item,
 132                               struct config_item *epf_item)
 133{
 134        struct pci_epc *epc;
 135        struct pci_epf *epf;
 136        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
 137        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
 138
 139        WARN_ON_ONCE(epc_group->start);
 140
 141        epc = epc_group->epc;
 142        epf = epf_group->epf;
 143        clear_bit(epf->func_no, &epc_group->function_num_map);
 144        pci_epf_unbind(epf);
 145        pci_epc_remove_epf(epc, epf);
 146}
 147
 148static struct configfs_item_operations pci_epc_item_ops = {
 149        .allow_link     = pci_epc_epf_link,
 150        .drop_link      = pci_epc_epf_unlink,
 151};
 152
 153static struct config_item_type pci_epc_type = {
 154        .ct_item_ops    = &pci_epc_item_ops,
 155        .ct_attrs       = pci_epc_attrs,
 156        .ct_owner       = THIS_MODULE,
 157};
 158
 159struct config_group *pci_ep_cfs_add_epc_group(const char *name)
 160{
 161        int ret;
 162        struct pci_epc *epc;
 163        struct config_group *group;
 164        struct pci_epc_group *epc_group;
 165
 166        epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
 167        if (!epc_group) {
 168                ret = -ENOMEM;
 169                goto err;
 170        }
 171
 172        group = &epc_group->group;
 173
 174        config_group_init_type_name(group, name, &pci_epc_type);
 175        ret = configfs_register_group(controllers_group, group);
 176        if (ret) {
 177                pr_err("failed to register configfs group for %s\n", name);
 178                goto err_register_group;
 179        }
 180
 181        epc = pci_epc_get(name);
 182        if (IS_ERR(epc)) {
 183                ret = PTR_ERR(epc);
 184                goto err_epc_get;
 185        }
 186
 187        epc_group->epc = epc;
 188
 189        return group;
 190
 191err_epc_get:
 192        configfs_unregister_group(group);
 193
 194err_register_group:
 195        kfree(epc_group);
 196
 197err:
 198        return ERR_PTR(ret);
 199}
 200EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
 201
 202void pci_ep_cfs_remove_epc_group(struct config_group *group)
 203{
 204        struct pci_epc_group *epc_group;
 205
 206        if (!group)
 207                return;
 208
 209        epc_group = container_of(group, struct pci_epc_group, group);
 210        pci_epc_put(epc_group->epc);
 211        configfs_unregister_group(&epc_group->group);
 212        kfree(epc_group);
 213}
 214EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
 215
 216#define PCI_EPF_HEADER_R(_name)                                                \
 217static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page)    \
 218{                                                                              \
 219        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 220        if (WARN_ON_ONCE(!epf->header))                                        \
 221                return -EINVAL;                                                \
 222        return sprintf(page, "0x%04x\n", epf->header->_name);                  \
 223}
 224
 225#define PCI_EPF_HEADER_W_u32(_name)                                            \
 226static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 227                                       const char *page, size_t len)           \
 228{                                                                              \
 229        u32 val;                                                               \
 230        int ret;                                                               \
 231        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 232        if (WARN_ON_ONCE(!epf->header))                                        \
 233                return -EINVAL;                                                \
 234        ret = kstrtou32(page, 0, &val);                                        \
 235        if (ret)                                                               \
 236                return ret;                                                    \
 237        epf->header->_name = val;                                              \
 238        return len;                                                            \
 239}
 240
 241#define PCI_EPF_HEADER_W_u16(_name)                                            \
 242static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 243                                       const char *page, size_t len)           \
 244{                                                                              \
 245        u16 val;                                                               \
 246        int ret;                                                               \
 247        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 248        if (WARN_ON_ONCE(!epf->header))                                        \
 249                return -EINVAL;                                                \
 250        ret = kstrtou16(page, 0, &val);                                        \
 251        if (ret)                                                               \
 252                return ret;                                                    \
 253        epf->header->_name = val;                                              \
 254        return len;                                                            \
 255}
 256
 257#define PCI_EPF_HEADER_W_u8(_name)                                             \
 258static ssize_t pci_epf_##_name##_store(struct config_item *item,               \
 259                                       const char *page, size_t len)           \
 260{                                                                              \
 261        u8 val;                                                                \
 262        int ret;                                                               \
 263        struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
 264        if (WARN_ON_ONCE(!epf->header))                                        \
 265                return -EINVAL;                                                \
 266        ret = kstrtou8(page, 0, &val);                                         \
 267        if (ret)                                                               \
 268                return ret;                                                    \
 269        epf->header->_name = val;                                              \
 270        return len;                                                            \
 271}
 272
 273static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
 274                                            const char *page, size_t len)
 275{
 276        u8 val;
 277        int ret;
 278
 279        ret = kstrtou8(page, 0, &val);
 280        if (ret)
 281                return ret;
 282
 283        to_pci_epf_group(item)->epf->msi_interrupts = val;
 284
 285        return len;
 286}
 287
 288static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
 289                                           char *page)
 290{
 291        return sprintf(page, "%d\n",
 292                       to_pci_epf_group(item)->epf->msi_interrupts);
 293}
 294
 295PCI_EPF_HEADER_R(vendorid)
 296PCI_EPF_HEADER_W_u16(vendorid)
 297
 298PCI_EPF_HEADER_R(deviceid)
 299PCI_EPF_HEADER_W_u16(deviceid)
 300
 301PCI_EPF_HEADER_R(revid)
 302PCI_EPF_HEADER_W_u8(revid)
 303
 304PCI_EPF_HEADER_R(progif_code)
 305PCI_EPF_HEADER_W_u8(progif_code)
 306
 307PCI_EPF_HEADER_R(subclass_code)
 308PCI_EPF_HEADER_W_u8(subclass_code)
 309
 310PCI_EPF_HEADER_R(baseclass_code)
 311PCI_EPF_HEADER_W_u8(baseclass_code)
 312
 313PCI_EPF_HEADER_R(cache_line_size)
 314PCI_EPF_HEADER_W_u8(cache_line_size)
 315
 316PCI_EPF_HEADER_R(subsys_vendor_id)
 317PCI_EPF_HEADER_W_u16(subsys_vendor_id)
 318
 319PCI_EPF_HEADER_R(subsys_id)
 320PCI_EPF_HEADER_W_u16(subsys_id)
 321
 322PCI_EPF_HEADER_R(interrupt_pin)
 323PCI_EPF_HEADER_W_u8(interrupt_pin)
 324
 325CONFIGFS_ATTR(pci_epf_, vendorid);
 326CONFIGFS_ATTR(pci_epf_, deviceid);
 327CONFIGFS_ATTR(pci_epf_, revid);
 328CONFIGFS_ATTR(pci_epf_, progif_code);
 329CONFIGFS_ATTR(pci_epf_, subclass_code);
 330CONFIGFS_ATTR(pci_epf_, baseclass_code);
 331CONFIGFS_ATTR(pci_epf_, cache_line_size);
 332CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
 333CONFIGFS_ATTR(pci_epf_, subsys_id);
 334CONFIGFS_ATTR(pci_epf_, interrupt_pin);
 335CONFIGFS_ATTR(pci_epf_, msi_interrupts);
 336
 337static struct configfs_attribute *pci_epf_attrs[] = {
 338        &pci_epf_attr_vendorid,
 339        &pci_epf_attr_deviceid,
 340        &pci_epf_attr_revid,
 341        &pci_epf_attr_progif_code,
 342        &pci_epf_attr_subclass_code,
 343        &pci_epf_attr_baseclass_code,
 344        &pci_epf_attr_cache_line_size,
 345        &pci_epf_attr_subsys_vendor_id,
 346        &pci_epf_attr_subsys_id,
 347        &pci_epf_attr_interrupt_pin,
 348        &pci_epf_attr_msi_interrupts,
 349        NULL,
 350};
 351
 352static void pci_epf_release(struct config_item *item)
 353{
 354        struct pci_epf_group *epf_group = to_pci_epf_group(item);
 355
 356        pci_epf_destroy(epf_group->epf);
 357        kfree(epf_group);
 358}
 359
 360static struct configfs_item_operations pci_epf_ops = {
 361        .release                = pci_epf_release,
 362};
 363
 364static struct config_item_type pci_epf_type = {
 365        .ct_item_ops    = &pci_epf_ops,
 366        .ct_attrs       = pci_epf_attrs,
 367        .ct_owner       = THIS_MODULE,
 368};
 369
 370static struct config_group *pci_epf_make(struct config_group *group,
 371                                         const char *name)
 372{
 373        struct pci_epf_group *epf_group;
 374        struct pci_epf *epf;
 375
 376        epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
 377        if (!epf_group)
 378                return ERR_PTR(-ENOMEM);
 379
 380        config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
 381
 382        epf = pci_epf_create(group->cg_item.ci_name);
 383        if (IS_ERR(epf)) {
 384                pr_err("failed to create endpoint function device\n");
 385                return ERR_PTR(-EINVAL);
 386        }
 387
 388        epf_group->epf = epf;
 389
 390        return &epf_group->group;
 391}
 392
 393static void pci_epf_drop(struct config_group *group, struct config_item *item)
 394{
 395        config_item_put(item);
 396}
 397
 398static struct configfs_group_operations pci_epf_group_ops = {
 399        .make_group     = &pci_epf_make,
 400        .drop_item      = &pci_epf_drop,
 401};
 402
 403static struct config_item_type pci_epf_group_type = {
 404        .ct_group_ops   = &pci_epf_group_ops,
 405        .ct_owner       = THIS_MODULE,
 406};
 407
 408struct config_group *pci_ep_cfs_add_epf_group(const char *name)
 409{
 410        struct config_group *group;
 411
 412        group = configfs_register_default_group(functions_group, name,
 413                                                &pci_epf_group_type);
 414        if (IS_ERR(group))
 415                pr_err("failed to register configfs group for %s function\n",
 416                       name);
 417
 418        return group;
 419}
 420EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
 421
 422void pci_ep_cfs_remove_epf_group(struct config_group *group)
 423{
 424        if (IS_ERR_OR_NULL(group))
 425                return;
 426
 427        configfs_unregister_default_group(group);
 428}
 429EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
 430
 431static struct config_item_type pci_functions_type = {
 432        .ct_owner       = THIS_MODULE,
 433};
 434
 435static struct config_item_type pci_controllers_type = {
 436        .ct_owner       = THIS_MODULE,
 437};
 438
 439static struct config_item_type pci_ep_type = {
 440        .ct_owner       = THIS_MODULE,
 441};
 442
 443static struct configfs_subsystem pci_ep_cfs_subsys = {
 444        .su_group = {
 445                .cg_item = {
 446                        .ci_namebuf = "pci_ep",
 447                        .ci_type = &pci_ep_type,
 448                },
 449        },
 450        .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
 451};
 452
 453static int __init pci_ep_cfs_init(void)
 454{
 455        int ret;
 456        struct config_group *root = &pci_ep_cfs_subsys.su_group;
 457
 458        config_group_init(root);
 459
 460        ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
 461        if (ret) {
 462                pr_err("Error %d while registering subsystem %s\n",
 463                       ret, root->cg_item.ci_namebuf);
 464                goto err;
 465        }
 466
 467        functions_group = configfs_register_default_group(root, "functions",
 468                                                          &pci_functions_type);
 469        if (IS_ERR(functions_group)) {
 470                ret = PTR_ERR(functions_group);
 471                pr_err("Error %d while registering functions group\n",
 472                       ret);
 473                goto err_functions_group;
 474        }
 475
 476        controllers_group =
 477                configfs_register_default_group(root, "controllers",
 478                                                &pci_controllers_type);
 479        if (IS_ERR(controllers_group)) {
 480                ret = PTR_ERR(controllers_group);
 481                pr_err("Error %d while registering controllers group\n",
 482                       ret);
 483                goto err_controllers_group;
 484        }
 485
 486        return 0;
 487
 488err_controllers_group:
 489        configfs_unregister_default_group(functions_group);
 490
 491err_functions_group:
 492        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 493
 494err:
 495        return ret;
 496}
 497module_init(pci_ep_cfs_init);
 498
 499static void __exit pci_ep_cfs_exit(void)
 500{
 501        configfs_unregister_default_group(controllers_group);
 502        configfs_unregister_default_group(functions_group);
 503        configfs_unregister_subsystem(&pci_ep_cfs_subsys);
 504}
 505module_exit(pci_ep_cfs_exit);
 506
 507MODULE_DESCRIPTION("PCI EP CONFIGFS");
 508MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
 509MODULE_LICENSE("GPL v2");
 510