Skip to content

Commit

Permalink
PCI: endpoint: Fix EPF device name to support multi-function devices
Browse files Browse the repository at this point in the history
Fix the pci_epf_make() function so it can now bind many EPF devices to the
same EPF driver.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
  • Loading branch information
Cyrille Pitchen authored and Lorenzo Pieralisi committed Jan 31, 2018
1 parent 4494738 commit fc41df2
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions drivers/pci/endpoint/pci-ep-cfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@
*/

#include <linux/module.h>
#include <linux/idr.h>
#include <linux/slab.h>

#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
#include <linux/pci-ep-cfs.h>

static DEFINE_IDR(functions_idr);
static DEFINE_MUTEX(functions_mutex);
static struct config_group *functions_group;
static struct config_group *controllers_group;

struct pci_epf_group {
struct config_group group;
struct pci_epf *epf;
int index;
};

struct pci_epc_group {
Expand Down Expand Up @@ -353,6 +357,9 @@ static void pci_epf_release(struct config_item *item)
{
struct pci_epf_group *epf_group = to_pci_epf_group(item);

mutex_lock(&functions_mutex);
idr_remove(&functions_idr, epf_group->index);
mutex_unlock(&functions_mutex);
pci_epf_destroy(epf_group->epf);
kfree(epf_group);
}
Expand All @@ -372,22 +379,57 @@ static struct config_group *pci_epf_make(struct config_group *group,
{
struct pci_epf_group *epf_group;
struct pci_epf *epf;
char *epf_name;
int index, err;

epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
if (!epf_group)
return ERR_PTR(-ENOMEM);

mutex_lock(&functions_mutex);
index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
mutex_unlock(&functions_mutex);
if (index < 0) {
err = index;
goto free_group;
}

epf_group->index = index;

config_group_init_type_name(&epf_group->group, name, &pci_epf_type);

epf = pci_epf_create(group->cg_item.ci_name);
epf_name = kasprintf(GFP_KERNEL, "%s.%d",
group->cg_item.ci_name, epf_group->index);
if (!epf_name) {
err = -ENOMEM;
goto remove_idr;
}

epf = pci_epf_create(epf_name);
if (IS_ERR(epf)) {
pr_err("failed to create endpoint function device\n");
return ERR_PTR(-EINVAL);
err = -EINVAL;
goto free_name;
}

epf_group->epf = epf;

kfree(epf_name);

return &epf_group->group;

free_name:
kfree(epf_name);

remove_idr:
mutex_lock(&functions_mutex);
idr_remove(&functions_idr, epf_group->index);
mutex_unlock(&functions_mutex);

free_group:
kfree(epf_group);

return ERR_PTR(err);
}

static void pci_epf_drop(struct config_group *group, struct config_item *item)
Expand Down

0 comments on commit fc41df2

Please sign in to comment.