All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Jingoo Han <jingoohan1@gmail.com>,
	Joao Pinto <Joao.Pinto@synopsys.com>,
	Arnd Bergmann <arnd@arndb.de>
Cc: linux-pci@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-samsung-soc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	linux-arm-kernel@axis.com, linux-arm-msm@vger.kernel.org,
	nsekhar@ti.com, kishon@ti.com
Subject: [PATCH 16/37] PCI: endpoint: Introduce configfs entry for configuring EP functions
Date: Thu, 12 Jan 2017 15:56:05 +0530	[thread overview]
Message-ID: <1484216786-17292-17-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1484216786-17292-1-git-send-email-kishon@ti.com>

Introduce a new configfs entry to configure the EP function (like
configuring the standard configuration header entries) and to
bind the EP function with EP controller.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/Kconfig      |    4 +-
 drivers/pci/endpoint/Makefile     |    2 +-
 drivers/pci/endpoint/pci-ep-cfs.c |  427 +++++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pci/endpoint/pci-ep-cfs.c

diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index 7eb1c79..930e87a 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -14,7 +14,9 @@ config PCI_ENDPOINT
 
 	   Enabling this option will build the endpoint library, which
 	   includes endpoint controller library and endpoint function
-	   library.
+	   library. This will also enable the configfs entry required to
+	   configure the endpoint function and used to bind the
+	   function with a endpoint controller.
 
 	   If in doubt, say "N" to disable Endpoint support.
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index eeef1b7..a599c18 100644
--- a/drivers/pci/endpoint/Makefile
+++ b/drivers/pci/endpoint/Makefile
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_PCI_ENDPOINT)		:= pci-epc-core.o pci-epf-core.o\
-					   pci-epc-mem.o
+					   pci-epc-mem.o pci-ep-cfs.o
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
new file mode 100644
index 0000000..ed0f8c2
--- /dev/null
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -0,0 +1,427 @@
+/**
+ * configfs to configure the PCI endpoint
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+struct pci_epf_info {
+	struct config_group group;
+	struct list_head list;
+	struct pci_epf *epf;
+};
+
+struct pci_ep_info {
+	struct config_group group;
+	struct config_group pci_epf_group;
+	/* mutex to protect pci_epf list */
+	struct mutex lock;
+	struct list_head pci_epf;
+	const char *epc_name;
+	struct pci_epc *epc;
+};
+
+static inline struct pci_epf_info *to_pci_epf_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_epf_info, group);
+}
+
+static inline struct pci_ep_info *to_pci_ep_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_ep_info, group);
+}
+
+#define PCI_EPF_HEADER_R(_name)						       \
+static ssize_t pci_epf_##_name##_show(struct config_item *item,	char *page)    \
+{									       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	return sprintf(page, "0x%04x\n", epf->header->_name);		       \
+}
+
+#define PCI_EPF_HEADER_W_u32(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u32 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou32(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u16(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u16 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou16(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u8(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u8 val;								       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou8(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
+					    const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+
+	to_pci_epf_info(item)->epf->msi_interrupts = val;
+
+	return len;
+}
+
+static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
+					   char *page)
+{
+	return sprintf(page, "%d\n",
+		       to_pci_epf_info(item)->epf->msi_interrupts);
+}
+
+static ssize_t pci_epf_function_show(struct config_item *item,
+				     char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_epf_info(item)->epf->name);
+}
+
+PCI_EPF_HEADER_R(vendorid)
+PCI_EPF_HEADER_W_u16(vendorid)
+
+PCI_EPF_HEADER_R(deviceid)
+PCI_EPF_HEADER_W_u16(deviceid)
+
+PCI_EPF_HEADER_R(revid)
+PCI_EPF_HEADER_W_u8(revid)
+
+PCI_EPF_HEADER_R(progif_code)
+PCI_EPF_HEADER_W_u8(progif_code)
+
+PCI_EPF_HEADER_R(subclass_code)
+PCI_EPF_HEADER_W_u8(subclass_code)
+
+PCI_EPF_HEADER_R(baseclass_code)
+PCI_EPF_HEADER_W_u8(baseclass_code)
+
+PCI_EPF_HEADER_R(cache_line_size)
+PCI_EPF_HEADER_W_u8(cache_line_size)
+
+PCI_EPF_HEADER_R(subsys_vendor_id)
+PCI_EPF_HEADER_W_u16(subsys_vendor_id)
+
+PCI_EPF_HEADER_R(subsys_id)
+PCI_EPF_HEADER_W_u16(subsys_id)
+
+PCI_EPF_HEADER_R(interrupt_pin)
+PCI_EPF_HEADER_W_u8(interrupt_pin)
+
+CONFIGFS_ATTR(pci_epf_, vendorid);
+CONFIGFS_ATTR(pci_epf_, deviceid);
+CONFIGFS_ATTR(pci_epf_, revid);
+CONFIGFS_ATTR(pci_epf_, progif_code);
+CONFIGFS_ATTR(pci_epf_, subclass_code);
+CONFIGFS_ATTR(pci_epf_, baseclass_code);
+CONFIGFS_ATTR(pci_epf_, cache_line_size);
+CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
+CONFIGFS_ATTR(pci_epf_, subsys_id);
+CONFIGFS_ATTR(pci_epf_, interrupt_pin);
+CONFIGFS_ATTR(pci_epf_, msi_interrupts);
+CONFIGFS_ATTR_RO(pci_epf_, function);
+
+static struct configfs_attribute *pci_epf_attrs[] = {
+	&pci_epf_attr_vendorid,
+	&pci_epf_attr_deviceid,
+	&pci_epf_attr_revid,
+	&pci_epf_attr_progif_code,
+	&pci_epf_attr_subclass_code,
+	&pci_epf_attr_baseclass_code,
+	&pci_epf_attr_cache_line_size,
+	&pci_epf_attr_subsys_vendor_id,
+	&pci_epf_attr_subsys_id,
+	&pci_epf_attr_interrupt_pin,
+	&pci_epf_attr_msi_interrupts,
+	&pci_epf_attr_function,
+	NULL,
+};
+
+static void pci_epf_release(struct config_item *item)
+{
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	pci_epf_destroy(epf_info->epf);
+	kfree(epf_info);
+}
+
+static struct configfs_item_operations pci_epf_ops = {
+	.release		= pci_epf_release,
+};
+
+static struct config_item_type pci_epf_type = {
+	.ct_item_ops	= &pci_epf_ops,
+	.ct_attrs	= pci_epf_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_epf_make(struct config_group *group,
+					 const char *name)
+{
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info;
+	struct pci_epf *epf;
+
+	epf_info = kzalloc(sizeof(*epf_info), GFP_KERNEL);
+	if (!epf_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&epf_info->group, name, &pci_epf_type);
+
+	epf = pci_epf_create(name);
+	if (IS_ERR(epf)) {
+		pr_err("failed to create endpoint function device\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	epf_info->epf = epf;
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	mutex_lock(&ep_info->lock);
+	list_add_tail(&epf_info->list, &ep_info->pci_epf);
+	mutex_unlock(&ep_info->lock);
+
+	return &epf_info->group;
+}
+
+static void pci_epf_drop(struct config_group *group, struct config_item *item)
+{
+	struct pci_ep_info *ep_info;
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	pci_epf_unbind(epf_info->epf);
+	pci_epc_remove_epf(ep_info->epc, epf_info->epf);
+
+	mutex_lock(&ep_info->lock);
+	list_del(&epf_info->list);
+	mutex_unlock(&ep_info->lock);
+
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_epfs_ops = {
+	.make_group	= &pci_epf_make,
+	.drop_item	= &pci_epf_drop,
+};
+
+static struct config_item_type pci_epfs_type = {
+	.ct_group_ops	= &pci_epfs_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static ssize_t pci_ep_epc_store(struct config_item *item, const char *page,
+				size_t len)
+{
+	int ret;
+	u8 func_no = 0;
+	char *epc_name;
+	struct pci_epc *epc;
+	struct pci_epf *epf;
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	epc_name = kstrdup(page, GFP_KERNEL);
+	if (!epc_name)
+		return -ENOMEM;
+	if (epc_name[len - 1] == '\n')
+		epc_name[len - 1] = '\0';
+
+	if (ep_info->epc) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	epc = pci_epc_get(epc_name);
+	if (IS_ERR(epc)) {
+		ret = PTR_ERR(epc);
+		goto err;
+	}
+
+	ep_info->epc = epc;
+	ep_info->epc_name = epc_name;
+
+	list_for_each_entry(epf_info, &ep_info->pci_epf, list) {
+		epf = epf_info->epf;
+		epf->func_no = func_no;
+		epf->epc = epc;
+		pci_epc_add_epf(epc, epf);
+		pci_epf_bind(epf);
+		func_no++;
+	}
+
+	return len;
+
+err:
+	kfree(epc_name);
+	return ret;
+}
+
+static ssize_t pci_ep_epc_show(struct config_item *item, char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_ep_info(item)->epc_name);
+}
+
+CONFIGFS_ATTR(pci_ep_, epc);
+
+static struct configfs_attribute *pci_ep_attrs[] = {
+	&pci_ep_attr_epc,
+	NULL,
+};
+
+static void pci_ep_attr_release(struct config_item *item)
+{
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	pci_epc_put(ep_info->epc);
+	kfree(ep_info->epc_name);
+	kfree(ep_info);
+}
+
+static struct configfs_item_operations pci_ep_device_ops = {
+	.release	= pci_ep_attr_release,
+};
+
+static struct config_item_type pci_ep_device_type = {
+	.ct_item_ops	= &pci_ep_device_ops,
+	.ct_attrs	= pci_ep_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_ep_make(struct config_group *group,
+					const char *name)
+{
+	struct pci_ep_info *ep_info;
+
+	ep_info = kzalloc(sizeof(*ep_info), GFP_KERNEL);
+	if (!ep_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&ep_info->group, name, &pci_ep_device_type);
+	config_group_init_type_name(&ep_info->pci_epf_group,
+				    "epf", &pci_epfs_type);
+	configfs_add_default_group(&ep_info->pci_epf_group, &ep_info->group);
+
+	mutex_init(&ep_info->lock);
+	INIT_LIST_HEAD(&ep_info->pci_epf);
+
+	return &ep_info->group;
+}
+
+static void pci_ep_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_ep_ops = {
+	.make_group	= &pci_ep_make,
+	.drop_item	= &pci_ep_drop,
+};
+
+static struct config_item_type pci_ep_type = {
+	.ct_group_ops	= &pci_ep_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct configfs_subsystem pci_ep_cfs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "pci_ep",
+			.ci_type = &pci_ep_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
+};
+
+static int __init pci_ep_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&pci_ep_cfs_subsys.su_group);
+
+	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
+	if (ret)
+		pr_err("Error %d while registering subsystem %s\n",
+		       ret, pci_ep_cfs_subsys.su_group.cg_item.ci_namebuf);
+
+	return ret;
+}
+module_init(pci_ep_cfs_init);
+
+static void __exit pci_ep_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+}
+module_exit(pci_ep_cfs_exit);
+
+MODULE_DESCRIPTION("PCI EP CONFIGFS");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

WARNING: multiple messages have this Message-ID (diff)
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Jingoo Han <jingoohan1@gmail.com>,
	Joao Pinto <Joao.Pinto@synopsys.com>,
	Arnd Bergmann <arnd@arndb.de>
Cc: <linux-pci@vger.kernel.org>, <linux-doc@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<linux-omap@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-samsung-soc@vger.kernel.org>,
	<linuxppc-dev@lists.ozlabs.org>, <linux-arm-kernel@axis.com>,
	<linux-arm-msm@vger.kernel.org>, <nsekhar@ti.com>,
	<kishon@ti.com>
Subject: [PATCH 16/37] PCI: endpoint: Introduce configfs entry for configuring EP functions
Date: Thu, 12 Jan 2017 15:56:05 +0530	[thread overview]
Message-ID: <1484216786-17292-17-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1484216786-17292-1-git-send-email-kishon@ti.com>

Introduce a new configfs entry to configure the EP function (like
configuring the standard configuration header entries) and to
bind the EP function with EP controller.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/Kconfig      |    4 +-
 drivers/pci/endpoint/Makefile     |    2 +-
 drivers/pci/endpoint/pci-ep-cfs.c |  427 +++++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pci/endpoint/pci-ep-cfs.c

diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index 7eb1c79..930e87a 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -14,7 +14,9 @@ config PCI_ENDPOINT
 
 	   Enabling this option will build the endpoint library, which
 	   includes endpoint controller library and endpoint function
-	   library.
+	   library. This will also enable the configfs entry required to
+	   configure the endpoint function and used to bind the
+	   function with a endpoint controller.
 
 	   If in doubt, say "N" to disable Endpoint support.
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index eeef1b7..a599c18 100644
--- a/drivers/pci/endpoint/Makefile
+++ b/drivers/pci/endpoint/Makefile
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_PCI_ENDPOINT)		:= pci-epc-core.o pci-epf-core.o\
-					   pci-epc-mem.o
+					   pci-epc-mem.o pci-ep-cfs.o
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
new file mode 100644
index 0000000..ed0f8c2
--- /dev/null
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -0,0 +1,427 @@
+/**
+ * configfs to configure the PCI endpoint
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+struct pci_epf_info {
+	struct config_group group;
+	struct list_head list;
+	struct pci_epf *epf;
+};
+
+struct pci_ep_info {
+	struct config_group group;
+	struct config_group pci_epf_group;
+	/* mutex to protect pci_epf list */
+	struct mutex lock;
+	struct list_head pci_epf;
+	const char *epc_name;
+	struct pci_epc *epc;
+};
+
+static inline struct pci_epf_info *to_pci_epf_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_epf_info, group);
+}
+
+static inline struct pci_ep_info *to_pci_ep_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_ep_info, group);
+}
+
+#define PCI_EPF_HEADER_R(_name)						       \
+static ssize_t pci_epf_##_name##_show(struct config_item *item,	char *page)    \
+{									       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	return sprintf(page, "0x%04x\n", epf->header->_name);		       \
+}
+
+#define PCI_EPF_HEADER_W_u32(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u32 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou32(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u16(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u16 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou16(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u8(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u8 val;								       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou8(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
+					    const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+
+	to_pci_epf_info(item)->epf->msi_interrupts = val;
+
+	return len;
+}
+
+static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
+					   char *page)
+{
+	return sprintf(page, "%d\n",
+		       to_pci_epf_info(item)->epf->msi_interrupts);
+}
+
+static ssize_t pci_epf_function_show(struct config_item *item,
+				     char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_epf_info(item)->epf->name);
+}
+
+PCI_EPF_HEADER_R(vendorid)
+PCI_EPF_HEADER_W_u16(vendorid)
+
+PCI_EPF_HEADER_R(deviceid)
+PCI_EPF_HEADER_W_u16(deviceid)
+
+PCI_EPF_HEADER_R(revid)
+PCI_EPF_HEADER_W_u8(revid)
+
+PCI_EPF_HEADER_R(progif_code)
+PCI_EPF_HEADER_W_u8(progif_code)
+
+PCI_EPF_HEADER_R(subclass_code)
+PCI_EPF_HEADER_W_u8(subclass_code)
+
+PCI_EPF_HEADER_R(baseclass_code)
+PCI_EPF_HEADER_W_u8(baseclass_code)
+
+PCI_EPF_HEADER_R(cache_line_size)
+PCI_EPF_HEADER_W_u8(cache_line_size)
+
+PCI_EPF_HEADER_R(subsys_vendor_id)
+PCI_EPF_HEADER_W_u16(subsys_vendor_id)
+
+PCI_EPF_HEADER_R(subsys_id)
+PCI_EPF_HEADER_W_u16(subsys_id)
+
+PCI_EPF_HEADER_R(interrupt_pin)
+PCI_EPF_HEADER_W_u8(interrupt_pin)
+
+CONFIGFS_ATTR(pci_epf_, vendorid);
+CONFIGFS_ATTR(pci_epf_, deviceid);
+CONFIGFS_ATTR(pci_epf_, revid);
+CONFIGFS_ATTR(pci_epf_, progif_code);
+CONFIGFS_ATTR(pci_epf_, subclass_code);
+CONFIGFS_ATTR(pci_epf_, baseclass_code);
+CONFIGFS_ATTR(pci_epf_, cache_line_size);
+CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
+CONFIGFS_ATTR(pci_epf_, subsys_id);
+CONFIGFS_ATTR(pci_epf_, interrupt_pin);
+CONFIGFS_ATTR(pci_epf_, msi_interrupts);
+CONFIGFS_ATTR_RO(pci_epf_, function);
+
+static struct configfs_attribute *pci_epf_attrs[] = {
+	&pci_epf_attr_vendorid,
+	&pci_epf_attr_deviceid,
+	&pci_epf_attr_revid,
+	&pci_epf_attr_progif_code,
+	&pci_epf_attr_subclass_code,
+	&pci_epf_attr_baseclass_code,
+	&pci_epf_attr_cache_line_size,
+	&pci_epf_attr_subsys_vendor_id,
+	&pci_epf_attr_subsys_id,
+	&pci_epf_attr_interrupt_pin,
+	&pci_epf_attr_msi_interrupts,
+	&pci_epf_attr_function,
+	NULL,
+};
+
+static void pci_epf_release(struct config_item *item)
+{
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	pci_epf_destroy(epf_info->epf);
+	kfree(epf_info);
+}
+
+static struct configfs_item_operations pci_epf_ops = {
+	.release		= pci_epf_release,
+};
+
+static struct config_item_type pci_epf_type = {
+	.ct_item_ops	= &pci_epf_ops,
+	.ct_attrs	= pci_epf_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_epf_make(struct config_group *group,
+					 const char *name)
+{
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info;
+	struct pci_epf *epf;
+
+	epf_info = kzalloc(sizeof(*epf_info), GFP_KERNEL);
+	if (!epf_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&epf_info->group, name, &pci_epf_type);
+
+	epf = pci_epf_create(name);
+	if (IS_ERR(epf)) {
+		pr_err("failed to create endpoint function device\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	epf_info->epf = epf;
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	mutex_lock(&ep_info->lock);
+	list_add_tail(&epf_info->list, &ep_info->pci_epf);
+	mutex_unlock(&ep_info->lock);
+
+	return &epf_info->group;
+}
+
+static void pci_epf_drop(struct config_group *group, struct config_item *item)
+{
+	struct pci_ep_info *ep_info;
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	pci_epf_unbind(epf_info->epf);
+	pci_epc_remove_epf(ep_info->epc, epf_info->epf);
+
+	mutex_lock(&ep_info->lock);
+	list_del(&epf_info->list);
+	mutex_unlock(&ep_info->lock);
+
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_epfs_ops = {
+	.make_group	= &pci_epf_make,
+	.drop_item	= &pci_epf_drop,
+};
+
+static struct config_item_type pci_epfs_type = {
+	.ct_group_ops	= &pci_epfs_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static ssize_t pci_ep_epc_store(struct config_item *item, const char *page,
+				size_t len)
+{
+	int ret;
+	u8 func_no = 0;
+	char *epc_name;
+	struct pci_epc *epc;
+	struct pci_epf *epf;
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	epc_name = kstrdup(page, GFP_KERNEL);
+	if (!epc_name)
+		return -ENOMEM;
+	if (epc_name[len - 1] == '\n')
+		epc_name[len - 1] = '\0';
+
+	if (ep_info->epc) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	epc = pci_epc_get(epc_name);
+	if (IS_ERR(epc)) {
+		ret = PTR_ERR(epc);
+		goto err;
+	}
+
+	ep_info->epc = epc;
+	ep_info->epc_name = epc_name;
+
+	list_for_each_entry(epf_info, &ep_info->pci_epf, list) {
+		epf = epf_info->epf;
+		epf->func_no = func_no;
+		epf->epc = epc;
+		pci_epc_add_epf(epc, epf);
+		pci_epf_bind(epf);
+		func_no++;
+	}
+
+	return len;
+
+err:
+	kfree(epc_name);
+	return ret;
+}
+
+static ssize_t pci_ep_epc_show(struct config_item *item, char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_ep_info(item)->epc_name);
+}
+
+CONFIGFS_ATTR(pci_ep_, epc);
+
+static struct configfs_attribute *pci_ep_attrs[] = {
+	&pci_ep_attr_epc,
+	NULL,
+};
+
+static void pci_ep_attr_release(struct config_item *item)
+{
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	pci_epc_put(ep_info->epc);
+	kfree(ep_info->epc_name);
+	kfree(ep_info);
+}
+
+static struct configfs_item_operations pci_ep_device_ops = {
+	.release	= pci_ep_attr_release,
+};
+
+static struct config_item_type pci_ep_device_type = {
+	.ct_item_ops	= &pci_ep_device_ops,
+	.ct_attrs	= pci_ep_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_ep_make(struct config_group *group,
+					const char *name)
+{
+	struct pci_ep_info *ep_info;
+
+	ep_info = kzalloc(sizeof(*ep_info), GFP_KERNEL);
+	if (!ep_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&ep_info->group, name, &pci_ep_device_type);
+	config_group_init_type_name(&ep_info->pci_epf_group,
+				    "epf", &pci_epfs_type);
+	configfs_add_default_group(&ep_info->pci_epf_group, &ep_info->group);
+
+	mutex_init(&ep_info->lock);
+	INIT_LIST_HEAD(&ep_info->pci_epf);
+
+	return &ep_info->group;
+}
+
+static void pci_ep_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_ep_ops = {
+	.make_group	= &pci_ep_make,
+	.drop_item	= &pci_ep_drop,
+};
+
+static struct config_item_type pci_ep_type = {
+	.ct_group_ops	= &pci_ep_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct configfs_subsystem pci_ep_cfs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "pci_ep",
+			.ci_type = &pci_ep_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
+};
+
+static int __init pci_ep_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&pci_ep_cfs_subsys.su_group);
+
+	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
+	if (ret)
+		pr_err("Error %d while registering subsystem %s\n",
+		       ret, pci_ep_cfs_subsys.su_group.cg_item.ci_namebuf);
+
+	return ret;
+}
+module_init(pci_ep_cfs_init);
+
+static void __exit pci_ep_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+}
+module_exit(pci_ep_cfs_exit);
+
+MODULE_DESCRIPTION("PCI EP CONFIGFS");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

WARNING: multiple messages have this Message-ID (diff)
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Jingoo Han <jingoohan1@gmail.com>,
	Joao Pinto <Joao.Pinto@synopsys.com>,
	Arnd Bergmann <arnd@arndb.de>
Cc: devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-pci@vger.kernel.org,
	nsekhar@ti.com, linux-kernel@vger.kernel.org,
	linux-arm-kernel@axis.com, kishon@ti.com,
	linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH 16/37] PCI: endpoint: Introduce configfs entry for configuring EP functions
Date: Thu, 12 Jan 2017 15:56:05 +0530	[thread overview]
Message-ID: <1484216786-17292-17-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1484216786-17292-1-git-send-email-kishon@ti.com>

Introduce a new configfs entry to configure the EP function (like
configuring the standard configuration header entries) and to
bind the EP function with EP controller.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/Kconfig      |    4 +-
 drivers/pci/endpoint/Makefile     |    2 +-
 drivers/pci/endpoint/pci-ep-cfs.c |  427 +++++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pci/endpoint/pci-ep-cfs.c

diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index 7eb1c79..930e87a 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -14,7 +14,9 @@ config PCI_ENDPOINT
 
 	   Enabling this option will build the endpoint library, which
 	   includes endpoint controller library and endpoint function
-	   library.
+	   library. This will also enable the configfs entry required to
+	   configure the endpoint function and used to bind the
+	   function with a endpoint controller.
 
 	   If in doubt, say "N" to disable Endpoint support.
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index eeef1b7..a599c18 100644
--- a/drivers/pci/endpoint/Makefile
+++ b/drivers/pci/endpoint/Makefile
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_PCI_ENDPOINT)		:= pci-epc-core.o pci-epf-core.o\
-					   pci-epc-mem.o
+					   pci-epc-mem.o pci-ep-cfs.o
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
new file mode 100644
index 0000000..ed0f8c2
--- /dev/null
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -0,0 +1,427 @@
+/**
+ * configfs to configure the PCI endpoint
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+struct pci_epf_info {
+	struct config_group group;
+	struct list_head list;
+	struct pci_epf *epf;
+};
+
+struct pci_ep_info {
+	struct config_group group;
+	struct config_group pci_epf_group;
+	/* mutex to protect pci_epf list */
+	struct mutex lock;
+	struct list_head pci_epf;
+	const char *epc_name;
+	struct pci_epc *epc;
+};
+
+static inline struct pci_epf_info *to_pci_epf_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_epf_info, group);
+}
+
+static inline struct pci_ep_info *to_pci_ep_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_ep_info, group);
+}
+
+#define PCI_EPF_HEADER_R(_name)						       \
+static ssize_t pci_epf_##_name##_show(struct config_item *item,	char *page)    \
+{									       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	return sprintf(page, "0x%04x\n", epf->header->_name);		       \
+}
+
+#define PCI_EPF_HEADER_W_u32(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u32 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou32(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u16(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u16 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou16(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u8(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u8 val;								       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou8(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
+					    const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+
+	to_pci_epf_info(item)->epf->msi_interrupts = val;
+
+	return len;
+}
+
+static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
+					   char *page)
+{
+	return sprintf(page, "%d\n",
+		       to_pci_epf_info(item)->epf->msi_interrupts);
+}
+
+static ssize_t pci_epf_function_show(struct config_item *item,
+				     char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_epf_info(item)->epf->name);
+}
+
+PCI_EPF_HEADER_R(vendorid)
+PCI_EPF_HEADER_W_u16(vendorid)
+
+PCI_EPF_HEADER_R(deviceid)
+PCI_EPF_HEADER_W_u16(deviceid)
+
+PCI_EPF_HEADER_R(revid)
+PCI_EPF_HEADER_W_u8(revid)
+
+PCI_EPF_HEADER_R(progif_code)
+PCI_EPF_HEADER_W_u8(progif_code)
+
+PCI_EPF_HEADER_R(subclass_code)
+PCI_EPF_HEADER_W_u8(subclass_code)
+
+PCI_EPF_HEADER_R(baseclass_code)
+PCI_EPF_HEADER_W_u8(baseclass_code)
+
+PCI_EPF_HEADER_R(cache_line_size)
+PCI_EPF_HEADER_W_u8(cache_line_size)
+
+PCI_EPF_HEADER_R(subsys_vendor_id)
+PCI_EPF_HEADER_W_u16(subsys_vendor_id)
+
+PCI_EPF_HEADER_R(subsys_id)
+PCI_EPF_HEADER_W_u16(subsys_id)
+
+PCI_EPF_HEADER_R(interrupt_pin)
+PCI_EPF_HEADER_W_u8(interrupt_pin)
+
+CONFIGFS_ATTR(pci_epf_, vendorid);
+CONFIGFS_ATTR(pci_epf_, deviceid);
+CONFIGFS_ATTR(pci_epf_, revid);
+CONFIGFS_ATTR(pci_epf_, progif_code);
+CONFIGFS_ATTR(pci_epf_, subclass_code);
+CONFIGFS_ATTR(pci_epf_, baseclass_code);
+CONFIGFS_ATTR(pci_epf_, cache_line_size);
+CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
+CONFIGFS_ATTR(pci_epf_, subsys_id);
+CONFIGFS_ATTR(pci_epf_, interrupt_pin);
+CONFIGFS_ATTR(pci_epf_, msi_interrupts);
+CONFIGFS_ATTR_RO(pci_epf_, function);
+
+static struct configfs_attribute *pci_epf_attrs[] = {
+	&pci_epf_attr_vendorid,
+	&pci_epf_attr_deviceid,
+	&pci_epf_attr_revid,
+	&pci_epf_attr_progif_code,
+	&pci_epf_attr_subclass_code,
+	&pci_epf_attr_baseclass_code,
+	&pci_epf_attr_cache_line_size,
+	&pci_epf_attr_subsys_vendor_id,
+	&pci_epf_attr_subsys_id,
+	&pci_epf_attr_interrupt_pin,
+	&pci_epf_attr_msi_interrupts,
+	&pci_epf_attr_function,
+	NULL,
+};
+
+static void pci_epf_release(struct config_item *item)
+{
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	pci_epf_destroy(epf_info->epf);
+	kfree(epf_info);
+}
+
+static struct configfs_item_operations pci_epf_ops = {
+	.release		= pci_epf_release,
+};
+
+static struct config_item_type pci_epf_type = {
+	.ct_item_ops	= &pci_epf_ops,
+	.ct_attrs	= pci_epf_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_epf_make(struct config_group *group,
+					 const char *name)
+{
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info;
+	struct pci_epf *epf;
+
+	epf_info = kzalloc(sizeof(*epf_info), GFP_KERNEL);
+	if (!epf_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&epf_info->group, name, &pci_epf_type);
+
+	epf = pci_epf_create(name);
+	if (IS_ERR(epf)) {
+		pr_err("failed to create endpoint function device\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	epf_info->epf = epf;
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	mutex_lock(&ep_info->lock);
+	list_add_tail(&epf_info->list, &ep_info->pci_epf);
+	mutex_unlock(&ep_info->lock);
+
+	return &epf_info->group;
+}
+
+static void pci_epf_drop(struct config_group *group, struct config_item *item)
+{
+	struct pci_ep_info *ep_info;
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	pci_epf_unbind(epf_info->epf);
+	pci_epc_remove_epf(ep_info->epc, epf_info->epf);
+
+	mutex_lock(&ep_info->lock);
+	list_del(&epf_info->list);
+	mutex_unlock(&ep_info->lock);
+
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_epfs_ops = {
+	.make_group	= &pci_epf_make,
+	.drop_item	= &pci_epf_drop,
+};
+
+static struct config_item_type pci_epfs_type = {
+	.ct_group_ops	= &pci_epfs_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static ssize_t pci_ep_epc_store(struct config_item *item, const char *page,
+				size_t len)
+{
+	int ret;
+	u8 func_no = 0;
+	char *epc_name;
+	struct pci_epc *epc;
+	struct pci_epf *epf;
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	epc_name = kstrdup(page, GFP_KERNEL);
+	if (!epc_name)
+		return -ENOMEM;
+	if (epc_name[len - 1] == '\n')
+		epc_name[len - 1] = '\0';
+
+	if (ep_info->epc) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	epc = pci_epc_get(epc_name);
+	if (IS_ERR(epc)) {
+		ret = PTR_ERR(epc);
+		goto err;
+	}
+
+	ep_info->epc = epc;
+	ep_info->epc_name = epc_name;
+
+	list_for_each_entry(epf_info, &ep_info->pci_epf, list) {
+		epf = epf_info->epf;
+		epf->func_no = func_no;
+		epf->epc = epc;
+		pci_epc_add_epf(epc, epf);
+		pci_epf_bind(epf);
+		func_no++;
+	}
+
+	return len;
+
+err:
+	kfree(epc_name);
+	return ret;
+}
+
+static ssize_t pci_ep_epc_show(struct config_item *item, char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_ep_info(item)->epc_name);
+}
+
+CONFIGFS_ATTR(pci_ep_, epc);
+
+static struct configfs_attribute *pci_ep_attrs[] = {
+	&pci_ep_attr_epc,
+	NULL,
+};
+
+static void pci_ep_attr_release(struct config_item *item)
+{
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	pci_epc_put(ep_info->epc);
+	kfree(ep_info->epc_name);
+	kfree(ep_info);
+}
+
+static struct configfs_item_operations pci_ep_device_ops = {
+	.release	= pci_ep_attr_release,
+};
+
+static struct config_item_type pci_ep_device_type = {
+	.ct_item_ops	= &pci_ep_device_ops,
+	.ct_attrs	= pci_ep_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_ep_make(struct config_group *group,
+					const char *name)
+{
+	struct pci_ep_info *ep_info;
+
+	ep_info = kzalloc(sizeof(*ep_info), GFP_KERNEL);
+	if (!ep_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&ep_info->group, name, &pci_ep_device_type);
+	config_group_init_type_name(&ep_info->pci_epf_group,
+				    "epf", &pci_epfs_type);
+	configfs_add_default_group(&ep_info->pci_epf_group, &ep_info->group);
+
+	mutex_init(&ep_info->lock);
+	INIT_LIST_HEAD(&ep_info->pci_epf);
+
+	return &ep_info->group;
+}
+
+static void pci_ep_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_ep_ops = {
+	.make_group	= &pci_ep_make,
+	.drop_item	= &pci_ep_drop,
+};
+
+static struct config_item_type pci_ep_type = {
+	.ct_group_ops	= &pci_ep_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct configfs_subsystem pci_ep_cfs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "pci_ep",
+			.ci_type = &pci_ep_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
+};
+
+static int __init pci_ep_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&pci_ep_cfs_subsys.su_group);
+
+	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
+	if (ret)
+		pr_err("Error %d while registering subsystem %s\n",
+		       ret, pci_ep_cfs_subsys.su_group.cg_item.ci_namebuf);
+
+	return ret;
+}
+module_init(pci_ep_cfs_init);
+
+static void __exit pci_ep_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+}
+module_exit(pci_ep_cfs_exit);
+
+MODULE_DESCRIPTION("PCI EP CONFIGFS");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: kishon@ti.com (Kishon Vijay Abraham I)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 16/37] PCI: endpoint: Introduce configfs entry for configuring EP functions
Date: Thu, 12 Jan 2017 15:56:05 +0530	[thread overview]
Message-ID: <1484216786-17292-17-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1484216786-17292-1-git-send-email-kishon@ti.com>

Introduce a new configfs entry to configure the EP function (like
configuring the standard configuration header entries) and to
bind the EP function with EP controller.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/Kconfig      |    4 +-
 drivers/pci/endpoint/Makefile     |    2 +-
 drivers/pci/endpoint/pci-ep-cfs.c |  427 +++++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pci/endpoint/pci-ep-cfs.c

diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index 7eb1c79..930e87a 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -14,7 +14,9 @@ config PCI_ENDPOINT
 
 	   Enabling this option will build the endpoint library, which
 	   includes endpoint controller library and endpoint function
-	   library.
+	   library. This will also enable the configfs entry required to
+	   configure the endpoint function and used to bind the
+	   function with a endpoint controller.
 
 	   If in doubt, say "N" to disable Endpoint support.
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index eeef1b7..a599c18 100644
--- a/drivers/pci/endpoint/Makefile
+++ b/drivers/pci/endpoint/Makefile
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_PCI_ENDPOINT)		:= pci-epc-core.o pci-epf-core.o\
-					   pci-epc-mem.o
+					   pci-epc-mem.o pci-ep-cfs.o
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
new file mode 100644
index 0000000..ed0f8c2
--- /dev/null
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -0,0 +1,427 @@
+/**
+ * configfs to configure the PCI endpoint
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+struct pci_epf_info {
+	struct config_group group;
+	struct list_head list;
+	struct pci_epf *epf;
+};
+
+struct pci_ep_info {
+	struct config_group group;
+	struct config_group pci_epf_group;
+	/* mutex to protect pci_epf list */
+	struct mutex lock;
+	struct list_head pci_epf;
+	const char *epc_name;
+	struct pci_epc *epc;
+};
+
+static inline struct pci_epf_info *to_pci_epf_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_epf_info, group);
+}
+
+static inline struct pci_ep_info *to_pci_ep_info(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct pci_ep_info, group);
+}
+
+#define PCI_EPF_HEADER_R(_name)						       \
+static ssize_t pci_epf_##_name##_show(struct config_item *item,	char *page)    \
+{									       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	return sprintf(page, "0x%04x\n", epf->header->_name);		       \
+}
+
+#define PCI_EPF_HEADER_W_u32(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u32 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou32(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u16(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u16 val;							       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou16(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+#define PCI_EPF_HEADER_W_u8(_name)					       \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
+				       const char *page, size_t len)	       \
+{									       \
+	u8 val;								       \
+	int ret;							       \
+	struct pci_epf *epf = to_pci_epf_info(item)->epf;		       \
+	if (!epf->header) {						       \
+		WARN_ON_ONCE("epf device not bound to function driver\n");     \
+		return 0;						       \
+	}								       \
+	ret = kstrtou8(page, 0, &val);					       \
+	if (ret)							       \
+		return ret;						       \
+	epf->header->_name = val;					       \
+	return len;							       \
+}
+
+static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
+					    const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+
+	to_pci_epf_info(item)->epf->msi_interrupts = val;
+
+	return len;
+}
+
+static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
+					   char *page)
+{
+	return sprintf(page, "%d\n",
+		       to_pci_epf_info(item)->epf->msi_interrupts);
+}
+
+static ssize_t pci_epf_function_show(struct config_item *item,
+				     char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_epf_info(item)->epf->name);
+}
+
+PCI_EPF_HEADER_R(vendorid)
+PCI_EPF_HEADER_W_u16(vendorid)
+
+PCI_EPF_HEADER_R(deviceid)
+PCI_EPF_HEADER_W_u16(deviceid)
+
+PCI_EPF_HEADER_R(revid)
+PCI_EPF_HEADER_W_u8(revid)
+
+PCI_EPF_HEADER_R(progif_code)
+PCI_EPF_HEADER_W_u8(progif_code)
+
+PCI_EPF_HEADER_R(subclass_code)
+PCI_EPF_HEADER_W_u8(subclass_code)
+
+PCI_EPF_HEADER_R(baseclass_code)
+PCI_EPF_HEADER_W_u8(baseclass_code)
+
+PCI_EPF_HEADER_R(cache_line_size)
+PCI_EPF_HEADER_W_u8(cache_line_size)
+
+PCI_EPF_HEADER_R(subsys_vendor_id)
+PCI_EPF_HEADER_W_u16(subsys_vendor_id)
+
+PCI_EPF_HEADER_R(subsys_id)
+PCI_EPF_HEADER_W_u16(subsys_id)
+
+PCI_EPF_HEADER_R(interrupt_pin)
+PCI_EPF_HEADER_W_u8(interrupt_pin)
+
+CONFIGFS_ATTR(pci_epf_, vendorid);
+CONFIGFS_ATTR(pci_epf_, deviceid);
+CONFIGFS_ATTR(pci_epf_, revid);
+CONFIGFS_ATTR(pci_epf_, progif_code);
+CONFIGFS_ATTR(pci_epf_, subclass_code);
+CONFIGFS_ATTR(pci_epf_, baseclass_code);
+CONFIGFS_ATTR(pci_epf_, cache_line_size);
+CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
+CONFIGFS_ATTR(pci_epf_, subsys_id);
+CONFIGFS_ATTR(pci_epf_, interrupt_pin);
+CONFIGFS_ATTR(pci_epf_, msi_interrupts);
+CONFIGFS_ATTR_RO(pci_epf_, function);
+
+static struct configfs_attribute *pci_epf_attrs[] = {
+	&pci_epf_attr_vendorid,
+	&pci_epf_attr_deviceid,
+	&pci_epf_attr_revid,
+	&pci_epf_attr_progif_code,
+	&pci_epf_attr_subclass_code,
+	&pci_epf_attr_baseclass_code,
+	&pci_epf_attr_cache_line_size,
+	&pci_epf_attr_subsys_vendor_id,
+	&pci_epf_attr_subsys_id,
+	&pci_epf_attr_interrupt_pin,
+	&pci_epf_attr_msi_interrupts,
+	&pci_epf_attr_function,
+	NULL,
+};
+
+static void pci_epf_release(struct config_item *item)
+{
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	pci_epf_destroy(epf_info->epf);
+	kfree(epf_info);
+}
+
+static struct configfs_item_operations pci_epf_ops = {
+	.release		= pci_epf_release,
+};
+
+static struct config_item_type pci_epf_type = {
+	.ct_item_ops	= &pci_epf_ops,
+	.ct_attrs	= pci_epf_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_epf_make(struct config_group *group,
+					 const char *name)
+{
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info;
+	struct pci_epf *epf;
+
+	epf_info = kzalloc(sizeof(*epf_info), GFP_KERNEL);
+	if (!epf_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&epf_info->group, name, &pci_epf_type);
+
+	epf = pci_epf_create(name);
+	if (IS_ERR(epf)) {
+		pr_err("failed to create endpoint function device\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	epf_info->epf = epf;
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	mutex_lock(&ep_info->lock);
+	list_add_tail(&epf_info->list, &ep_info->pci_epf);
+	mutex_unlock(&ep_info->lock);
+
+	return &epf_info->group;
+}
+
+static void pci_epf_drop(struct config_group *group, struct config_item *item)
+{
+	struct pci_ep_info *ep_info;
+	struct pci_epf_info *epf_info = to_pci_epf_info(item);
+
+	ep_info = container_of(group, struct pci_ep_info, pci_epf_group);
+
+	pci_epf_unbind(epf_info->epf);
+	pci_epc_remove_epf(ep_info->epc, epf_info->epf);
+
+	mutex_lock(&ep_info->lock);
+	list_del(&epf_info->list);
+	mutex_unlock(&ep_info->lock);
+
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_epfs_ops = {
+	.make_group	= &pci_epf_make,
+	.drop_item	= &pci_epf_drop,
+};
+
+static struct config_item_type pci_epfs_type = {
+	.ct_group_ops	= &pci_epfs_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static ssize_t pci_ep_epc_store(struct config_item *item, const char *page,
+				size_t len)
+{
+	int ret;
+	u8 func_no = 0;
+	char *epc_name;
+	struct pci_epc *epc;
+	struct pci_epf *epf;
+	struct pci_epf_info *epf_info;
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	epc_name = kstrdup(page, GFP_KERNEL);
+	if (!epc_name)
+		return -ENOMEM;
+	if (epc_name[len - 1] == '\n')
+		epc_name[len - 1] = '\0';
+
+	if (ep_info->epc) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	epc = pci_epc_get(epc_name);
+	if (IS_ERR(epc)) {
+		ret = PTR_ERR(epc);
+		goto err;
+	}
+
+	ep_info->epc = epc;
+	ep_info->epc_name = epc_name;
+
+	list_for_each_entry(epf_info, &ep_info->pci_epf, list) {
+		epf = epf_info->epf;
+		epf->func_no = func_no;
+		epf->epc = epc;
+		pci_epc_add_epf(epc, epf);
+		pci_epf_bind(epf);
+		func_no++;
+	}
+
+	return len;
+
+err:
+	kfree(epc_name);
+	return ret;
+}
+
+static ssize_t pci_ep_epc_show(struct config_item *item, char *page)
+{
+	return sprintf(page, "%s\n",
+		       to_pci_ep_info(item)->epc_name);
+}
+
+CONFIGFS_ATTR(pci_ep_, epc);
+
+static struct configfs_attribute *pci_ep_attrs[] = {
+	&pci_ep_attr_epc,
+	NULL,
+};
+
+static void pci_ep_attr_release(struct config_item *item)
+{
+	struct pci_ep_info *ep_info = to_pci_ep_info(item);
+
+	pci_epc_put(ep_info->epc);
+	kfree(ep_info->epc_name);
+	kfree(ep_info);
+}
+
+static struct configfs_item_operations pci_ep_device_ops = {
+	.release	= pci_ep_attr_release,
+};
+
+static struct config_item_type pci_ep_device_type = {
+	.ct_item_ops	= &pci_ep_device_ops,
+	.ct_attrs	= pci_ep_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *pci_ep_make(struct config_group *group,
+					const char *name)
+{
+	struct pci_ep_info *ep_info;
+
+	ep_info = kzalloc(sizeof(*ep_info), GFP_KERNEL);
+	if (!ep_info)
+		return ERR_PTR(-ENOMEM);
+
+	config_group_init_type_name(&ep_info->group, name, &pci_ep_device_type);
+	config_group_init_type_name(&ep_info->pci_epf_group,
+				    "epf", &pci_epfs_type);
+	configfs_add_default_group(&ep_info->pci_epf_group, &ep_info->group);
+
+	mutex_init(&ep_info->lock);
+	INIT_LIST_HEAD(&ep_info->pci_epf);
+
+	return &ep_info->group;
+}
+
+static void pci_ep_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations pci_ep_ops = {
+	.make_group	= &pci_ep_make,
+	.drop_item	= &pci_ep_drop,
+};
+
+static struct config_item_type pci_ep_type = {
+	.ct_group_ops	= &pci_ep_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct configfs_subsystem pci_ep_cfs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "pci_ep",
+			.ci_type = &pci_ep_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
+};
+
+static int __init pci_ep_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&pci_ep_cfs_subsys.su_group);
+
+	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
+	if (ret)
+		pr_err("Error %d while registering subsystem %s\n",
+		       ret, pci_ep_cfs_subsys.su_group.cg_item.ci_namebuf);
+
+	return ret;
+}
+module_init(pci_ep_cfs_init);
+
+static void __exit pci_ep_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+}
+module_exit(pci_ep_cfs_exit);
+
+MODULE_DESCRIPTION("PCI EP CONFIGFS");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

  parent reply	other threads:[~2017-01-12 10:26 UTC|newest]

Thread overview: 252+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-12 10:25 [PATCH 00/37] PCI: Support for configurable PCI endpoint Kishon Vijay Abraham I
2017-01-12 10:25 ` Kishon Vijay Abraham I
2017-01-12 10:25 ` Kishon Vijay Abraham I
2017-01-12 10:25 ` Kishon Vijay Abraham I
2017-01-12 10:25 ` [PATCH 02/37] PCI: dwc: designware: Add new *ops* for cpu addr fixup Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 16:34   ` Joao Pinto
2017-01-13 16:34     ` Joao Pinto
2017-01-13 16:34     ` Joao Pinto
2017-01-13 16:34     ` Joao Pinto
2017-01-12 10:25 ` [PATCH 03/37] PCI: dwc: dra7xx: Populate cpu_addr_fixup ops Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25 ` [PATCH 04/37] PCI: dwc: designware: Move the register defines to designware header file Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 16:35   ` Joao Pinto
2017-01-13 16:35     ` Joao Pinto
2017-01-13 16:35     ` Joao Pinto
2017-01-13 16:35     ` Joao Pinto
2017-01-12 10:25 ` [PATCH 05/37] PCI: dwc: Add platform_set_drvdata Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 17:16   ` Joao Pinto
2017-01-13 17:16     ` Joao Pinto
2017-01-13 17:16     ` Joao Pinto
2017-01-13 17:16     ` Joao Pinto
2017-01-12 10:25 ` [PATCH 06/37] PCI: dwc: Rename cfg_read/cfg_write to read/write Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 16:36   ` Joao Pinto
2017-01-13 16:36     ` Joao Pinto
2017-01-13 16:36     ` Joao Pinto
2017-01-13 16:36     ` Joao Pinto
2017-01-12 10:25 ` [PATCH 07/37] PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 17:22   ` Joao Pinto
2017-01-13 17:22     ` Joao Pinto
2017-01-13 17:22     ` Joao Pinto
2017-01-13 17:22     ` Joao Pinto
2017-01-12 10:25 ` [RFT PATCH 08/37] PCI: dwc: Split *struct pcie_port* into host only and core structures Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25 ` [PATCH 09/37] PCI: dwc: designware: Parse *num-lanes* property in dw_pcie_setup_rc Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 17:13   ` Joao Pinto
2017-01-13 17:13     ` Joao Pinto
2017-01-13 17:13     ` Joao Pinto
2017-01-13 17:13     ` Joao Pinto
2017-01-16  5:19     ` Kishon Vijay Abraham I
2017-01-16  5:19       ` Kishon Vijay Abraham I
2017-01-16  5:19       ` Kishon Vijay Abraham I
2017-01-16  5:19       ` Kishon Vijay Abraham I
     [not found]       ` <587C57FD.7050601-l0cyMroinI0@public.gmane.org>
2017-01-16 10:23         ` Joao Pinto
2017-01-16 10:23           ` Joao Pinto
2017-01-16 10:23           ` Joao Pinto
2017-01-16 10:23           ` Joao Pinto
2017-01-12 10:25 ` [PATCH 10/37] PCI: dwc: designware: Fix style errors in pcie-designware.c Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-12 10:25   ` Kishon Vijay Abraham I
2017-01-13 16:38   ` Joao Pinto
2017-01-13 16:38     ` Joao Pinto
2017-01-13 16:38     ` Joao Pinto
2017-01-13 16:38     ` Joao Pinto
2017-01-12 10:26 ` [PATCH 11/37] PCI: dwc: Split pcie-designware.c into host and core files Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-13 16:49   ` Joao Pinto
2017-01-13 16:49     ` Joao Pinto
2017-01-13 16:49     ` Joao Pinto
2017-01-13 16:49     ` Joao Pinto
2017-01-16  5:21     ` Kishon Vijay Abraham I
2017-01-16  5:21       ` Kishon Vijay Abraham I
2017-01-16  5:21       ` Kishon Vijay Abraham I
2017-01-16  5:21       ` Kishon Vijay Abraham I
     [not found]       ` <587C586C.6070003-l0cyMroinI0@public.gmane.org>
2017-01-16 10:27         ` Joao Pinto
2017-01-16 10:27           ` Joao Pinto
2017-01-16 10:27           ` Joao Pinto
2017-01-16 10:27           ` Joao Pinto
2017-01-16 11:30           ` Kishon Vijay Abraham I
2017-01-16 11:30             ` Kishon Vijay Abraham I
2017-01-16 11:30             ` Kishon Vijay Abraham I
2017-01-16 11:30             ` Kishon Vijay Abraham I
     [not found]             ` <587CAEBD.1010803-l0cyMroinI0@public.gmane.org>
2017-01-16 13:38               ` Joao Pinto
2017-01-16 13:38                 ` Joao Pinto
2017-01-16 13:38                 ` Joao Pinto
2017-01-16 13:38                 ` Joao Pinto
2017-01-12 10:26 ` [PATCH 12/37] PCI: dwc: Create a new config symbol to enable pci dwc host Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-13 17:50   ` Joao Pinto
2017-01-13 17:50     ` Joao Pinto
2017-01-13 17:50     ` Joao Pinto
2017-01-13 17:50     ` Joao Pinto
2017-01-16  5:22     ` Kishon Vijay Abraham I
2017-01-16  5:22       ` Kishon Vijay Abraham I
2017-01-16  5:22       ` Kishon Vijay Abraham I
2017-01-16  5:22       ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 13/37] PCI: dwc: Remove dependency of designware to CONFIG_PCI Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 14/37] PCI: endpoint: Add EP core layer to enable EP controller and EP functions Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 15/37] Documentation: PCI: Guide to use PCI Endpoint Core Layer Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` Kishon Vijay Abraham I [this message]
2017-01-12 10:26   ` [PATCH 16/37] PCI: endpoint: Introduce configfs entry for configuring EP functions Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-13 18:06   ` Christoph Hellwig
2017-01-13 18:06     ` Christoph Hellwig
2017-01-13 18:06     ` Christoph Hellwig
2017-01-13 18:06     ` Christoph Hellwig
2017-01-16  6:01     ` Kishon Vijay Abraham I
2017-01-16  6:01       ` Kishon Vijay Abraham I
2017-01-16  6:01       ` Kishon Vijay Abraham I
2017-01-16  6:01       ` Kishon Vijay Abraham I
2017-01-16 15:51       ` Christoph Hellwig
2017-01-16 15:51         ` Christoph Hellwig
2017-01-16 15:51         ` Christoph Hellwig
2017-01-16 15:51         ` Christoph Hellwig
2017-01-12 10:26 ` [PATCH 17/37] Documentation: PCI: Guide to use pci endpoint configfs Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 18/37] Documentation: PCI: Add specification for the *pci test* function device Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 19/37] PCI: endpoint: functions: Add an EP function to test PCI Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 20/37] Documentation: PCI: Add binding documentation for pci-test endpoint function Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 21/37] PCI: dwc: Modify dbi accessors to take dbi_base as argument Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 22/37] PCI: dwc: Modify dbi accessors to access data of 4/2/1 bytes Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 23/37] PCI: dwc: Add *ops* to start and stop pcie link Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 24/37] PCI: dwc: designware: Add EP mode support Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 25/37] dt-bindings: PCI: Add dt bindings for pci designware EP mode Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-18 21:36   ` Rob Herring
2017-01-18 21:36     ` Rob Herring
2017-01-18 21:36     ` Rob Herring
2017-01-18 21:36     ` Rob Herring
2017-01-12 10:26 ` [PATCH 26/37] PCI: dwc: dra7xx: Facilitate wrapper and msi interrupts to be enabled independently Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 27/37] PCI: dwc: dra7xx: Add EP mode support Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 28/37] dt-bindings: PCI: dra7xx: Add dt bindings for pci dra7xx EP mode Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-18 21:45   ` Rob Herring
2017-01-18 21:45     ` Rob Herring
2017-01-18 21:45     ` Rob Herring
2017-01-12 10:26 ` [PATCH 29/37] PCI: dwc: dra7xx: Workaround for errata id i870 Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 30/37] dt-bindings: PCI: dra7xx: Add dt bindings to enable legacy mode Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-18 21:46   ` Rob Herring
2017-01-18 21:46     ` Rob Herring
2017-01-18 21:46     ` Rob Herring
2017-01-18 21:46     ` Rob Herring
2017-02-16  8:33     ` Kishon Vijay Abraham I
2017-02-16  8:33       ` Kishon Vijay Abraham I
2017-02-16  8:33       ` Kishon Vijay Abraham I
2017-02-16  8:33       ` Kishon Vijay Abraham I
     [not found] ` <1484216786-17292-1-git-send-email-kishon-l0cyMroinI0@public.gmane.org>
2017-01-12 10:25   ` [PATCH 01/37] PCI: dwc: dra7xx: Group all host related setup in add_pcie_port Kishon Vijay Abraham I
2017-01-12 10:25     ` Kishon Vijay Abraham I
2017-01-12 10:25     ` Kishon Vijay Abraham I
2017-01-12 10:25     ` Kishon Vijay Abraham I
2017-01-12 10:26   ` [PATCH 31/37] misc: Add host side pci driver for pci test function device Kishon Vijay Abraham I
2017-01-12 10:26     ` Kishon Vijay Abraham I
2017-01-12 10:26     ` Kishon Vijay Abraham I
2017-01-24 16:02     ` Christoph Hellwig
2017-01-24 16:02       ` Christoph Hellwig
     [not found]       ` <20170124160224.GA23528-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
2017-01-25  5:40         ` Kishon Vijay Abraham I
2017-01-25  5:40           ` Kishon Vijay Abraham I
2017-01-25  5:40           ` Kishon Vijay Abraham I
2017-01-25  5:40           ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 32/37] Documentation: misc-devices: Add Documentation for pci-endpoint-test driver Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 33/37] tools: PCI: Add a userspace tool to test PCI endpoint Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 34/37] tools: PCI: Add sample test script to invoke pcitest Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 35/37] MAINTAINERS: add PCI EP maintainer Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26 ` [PATCH 36/37] ARM: DRA7: clockdomain: Change the CLKTRCTRL of CM_PCIE_CLKSTCTRL to SW_WKUP Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-13 17:15   ` Tony Lindgren
2017-01-13 17:15     ` Tony Lindgren
2017-01-13 17:15     ` Tony Lindgren
2017-01-16  6:05     ` Kishon Vijay Abraham I
2017-01-16  6:05       ` Kishon Vijay Abraham I
2017-01-16  6:05       ` Kishon Vijay Abraham I
2017-01-16  6:05       ` Kishon Vijay Abraham I
2017-01-20 18:28       ` Tony Lindgren
2017-01-20 18:28         ` Tony Lindgren
2017-01-20 18:28         ` Tony Lindgren
2017-01-12 10:26 ` [PATCH 37/37] ARM: dts: DRA7: Add pcie1 dt node for EP mode Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-12 10:26   ` Kishon Vijay Abraham I
2017-01-20 18:30   ` Tony Lindgren
2017-01-20 18:30     ` Tony Lindgren
2017-01-20 18:30     ` Tony Lindgren
     [not found]     ` <20170120183000.GF7403-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
2017-02-16 10:00       ` Kishon Vijay Abraham I
2017-02-16 10:00         ` Kishon Vijay Abraham I
2017-02-16 10:00         ` Kishon Vijay Abraham I
2017-02-16 10:00         ` Kishon Vijay Abraham I
2017-02-01 12:31 ` [PATCH 00/37] PCI: Support for configurable PCI endpoint Kishon Vijay Abraham I
2017-02-01 12:31   ` Kishon Vijay Abraham I
2017-02-14 23:55   ` Bjorn Helgaas
2017-02-14 23:55     ` Bjorn Helgaas
2017-02-15 13:30     ` Kishon Vijay Abraham I
2017-02-15 13:30       ` Kishon Vijay Abraham I

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1484216786-17292-17-git-send-email-kishon@ti.com \
    --to=kishon@ti.com \
    --cc=Joao.Pinto@synopsys.com \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=devicetree@vger.kernel.org \
    --cc=jingoohan1@gmail.com \
    --cc=linux-arm-kernel@axis.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=nsekhar@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.