diff options
Diffstat (limited to 'drivers/pci/endpoint/pci-ep-cfs.c')
| -rw-r--r-- | drivers/pci/endpoint/pci-ep-cfs.c | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index d4850bdd837f..ef50c82e647f 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -63,6 +63,9 @@ static int pci_secondary_epc_epf_link(struct config_item *epf_item, return ret; } + /* Send any pending EPC initialization complete to the EPF driver */ + pci_epc_notify_pending_init(epc, epf); + return 0; } @@ -124,6 +127,9 @@ static int pci_primary_epc_epf_link(struct config_item *epf_item, return ret; } + /* Send any pending EPC initialization complete to the EPF driver */ + pci_epc_notify_pending_init(epc, epf); + return 0; } @@ -178,6 +184,9 @@ static ssize_t pci_epc_start_store(struct config_item *item, const char *page, if (kstrtobool(page, &start) < 0) return -EINVAL; + if (start == epc_group->start) + return -EALREADY; + if (!start) { pci_epc_stop(epc); epc_group->start = 0; @@ -226,6 +235,9 @@ static int pci_epc_epf_link(struct config_item *epc_item, return ret; } + /* Send any pending EPC initialization complete to the EPF driver */ + pci_epc_notify_pending_init(epc, epf); + return 0; } @@ -502,33 +514,64 @@ static struct configfs_item_operations pci_epf_ops = { .release = pci_epf_release, }; -static struct config_group *pci_epf_type_make(struct config_group *group, - const char *name) +static const struct config_item_type pci_epf_type = { + .ct_item_ops = &pci_epf_ops, + .ct_attrs = pci_epf_attrs, + .ct_owner = THIS_MODULE, +}; + +/** + * pci_epf_type_add_cfs() - Help function drivers to expose function specific + * attributes in configfs + * @epf: the EPF device that has to be configured using configfs + * @group: the parent configfs group (corresponding to entries in + * pci_epf_device_id) + * + * Invoke to expose function specific attributes in configfs. + * + * Return: A pointer to a config_group structure or NULL if the function driver + * does not have anything to expose (attributes configured by user) or if + * the function driver does not implement the add_cfs() method. + * + * Returns an error pointer if this function is called for an unbound EPF device + * or if the EPF driver add_cfs() method fails. + */ +static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf, + struct config_group *group) { - struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item); struct config_group *epf_type_group; - epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group); + if (!epf->driver) { + dev_err(&epf->dev, "epf device not bound to driver\n"); + return ERR_PTR(-ENODEV); + } + + if (!epf->driver->ops->add_cfs) + return NULL; + + mutex_lock(&epf->lock); + epf_type_group = epf->driver->ops->add_cfs(epf, group); + mutex_unlock(&epf->lock); + return epf_type_group; } -static void pci_epf_type_drop(struct config_group *group, - struct config_item *item) +static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group) { - config_item_put(item); -} + struct config_group *group; -static struct configfs_group_operations pci_epf_type_group_ops = { - .make_group = &pci_epf_type_make, - .drop_item = &pci_epf_type_drop, -}; + group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group); + if (!group) + return; -static const struct config_item_type pci_epf_type = { - .ct_group_ops = &pci_epf_type_group_ops, - .ct_item_ops = &pci_epf_ops, - .ct_attrs = pci_epf_attrs, - .ct_owner = THIS_MODULE, -}; + if (IS_ERR(group)) { + dev_err(&epf_group->epf->dev, + "failed to create epf type specific attributes\n"); + return; + } + + configfs_register_group(&epf_group->group, group); +} static void pci_epf_cfs_work(struct work_struct *work) { @@ -547,6 +590,8 @@ static void pci_epf_cfs_work(struct work_struct *work) pr_err("failed to create 'secondary' EPC interface\n"); return; } + + pci_ep_cfs_add_type_group(epf_group); } static struct config_group *pci_epf_make(struct config_group *group, @@ -646,6 +691,7 @@ void pci_ep_cfs_remove_epf_group(struct config_group *group) if (IS_ERR_OR_NULL(group)) return; + list_del(&group->group_entry); configfs_unregister_default_group(group); } EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group); @@ -728,4 +774,3 @@ module_exit(pci_ep_cfs_exit); MODULE_DESCRIPTION("PCI EP CONFIGFS"); MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); -MODULE_LICENSE("GPL v2"); |
