Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc41df28 authored by Cyrille Pitchen's avatar Cyrille Pitchen Committed by Lorenzo Pieralisi
Browse files

PCI: endpoint: Fix EPF device name to support multi-function devices



Fix the pci_epf_make() function so it can now bind many EPF devices to the
same EPF driver.

Signed-off-by: default avatarCyrille Pitchen <cyrille.pitchen@free-electrons.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
parent 4494738d
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
@@ -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 {
@@ -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);
}
@@ -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)