All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Arnd Bergmann <arnd@arndb.de>, Jingoo Han <jingoohan1@gmail.com>,
	<hch@infradead.org>, <Joao.Pinto@synopsys.com>,
	<mingkai.hu@nxp.com>, <m-karicheri2@ti.com>,
	Pratyush Anand <pratyush.anand@gmail.com>
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>,
	Joao Pinto <jpinto@synopsys.com>,
	Rob Herring <robh+dt@kernel.org>, <kishon@ti.com>,
	<nsekhar@ti.com>
Subject: [RFC PATCH 04/11] pci: endpoint: functions: add an EP function to test PCI
Date: Wed, 14 Sep 2016 10:42:00 +0530	[thread overview]
Message-ID: <1473829927-20466-5-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1473829927-20466-1-git-send-email-kishon@ti.com>

This adds a new endpoint function driver (to program the virtual
test device) making use of the EP-core library. The complete
usage of the test function is described in
Documentation/PCI/pci-test.txt (included in this commit).

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/PCI/00-INDEX                    |    3 +
 Documentation/PCI/pci-test.txt                |   79 +++++++
 drivers/pci/endpoint/Kconfig                  |    2 +
 drivers/pci/endpoint/Makefile                 |    2 +-
 drivers/pci/endpoint/functions/Kconfig        |   12 ++
 drivers/pci/endpoint/functions/Makefile       |    5 +
 drivers/pci/endpoint/functions/pci-epf-test.c |  272 +++++++++++++++++++++++++
 7 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/PCI/pci-test.txt
 create mode 100644 drivers/pci/endpoint/functions/Kconfig
 create mode 100644 drivers/pci/endpoint/functions/Makefile
 create mode 100644 drivers/pci/endpoint/functions/pci-epf-test.c

diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index e422b8151..e5a583c 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -14,3 +14,6 @@ pcieaer-howto.txt
 	- the PCI Express Advanced Error Reporting Driver Guide HOWTO
 pci-endpoint.txt
 	- guide to add endpoint controller driver and endpoint function driver.
+pci-test.txt
+	- description of the PCI EP function that can be used to test PCI
+	  functionality
diff --git a/Documentation/PCI/pci-test.txt b/Documentation/PCI/pci-test.txt
new file mode 100644
index 0000000..2bc796b
--- /dev/null
+++ b/Documentation/PCI/pci-test.txt
@@ -0,0 +1,79 @@
+				PCI TEST
+		    Kishon Vijay Abraham I <kishon@ti.com>
+
+Traditionally PCI RC has always been validated by using standard
+PCI cards like ethernet PCI cards or USB PCI cards or SATA PCI cards.
+However with the addition of EP-core in linux kernel, it is possible
+to configure a PCI controller that can operate in EP mode to work as
+a test device.
+
+The PCI endpoint test device is a completely software device used to
+test the endpoint functionality and serve as a sample driver for other
+PCI endpoint devices.
+
+The PCI endpoint test device has four registers:
+
+	1) PCI_ENDPOINT_TEST_COMMAND
+	2) PCI_ENDPOINT_TEST_STATUS
+	3) PCI_ENDPOINT_TEST_SRC_ADDR
+	4) PCI_ENDPOINT_TEST_DST_ADDR
+
+Since this is a virtual device, all these registers will be present
+in RAM and will be allocated using one of the standard memory allocation
+API (in this case dma_alloc_coherent)
+
+*) PCI_ENDPOINT_TEST_COMMAND:
+
+This register will be used by the host driver to indicate the function
+that the endpoint device must perform.
+
+Bitfield Description:
+  Bit 0: reset the PCI endpoint device
+  Bit 1: raise irq
+  Bit 2: Copy the data from source addr to destination address
+
+*) PCI_ENDPOINT_TEST_STATUS
+
+This register reflects the status of the PCI endpoint device.
+
+Bitfield Description:
+  Bit 0: PCI endpoint device is in initialized state
+  Bit 1: Copy is in progress
+  Bit 2: Copy is done
+  Bit 3: IRQ is raised
+  Bit 4: Source address is invalid
+  Bit 5: Destination address is invalid
+
+*) PCI_ENDPOINT_TEST_SRC_ADDR
+
+This register contains the source address for the COPY command.
+
+*) PCI_ENDPOINT_TEST_DST_ADDR
+
+This register contains the destination address for the COPY command.
+
+PCI ENDPOINT TEST DRIVER (EP SIDE)
+==================================
+
+The Endpoint side function driver is present in
+drivers/pci/endpoint/functions/pci-epf-test.c
+
+This function driver creates the PCI endpoint test device and then
+waits for commands from the host driver. If the host driver sets
+Bit 1 (raise irq) in the COMMAND register, the endpoint driver
+will raise an irq. Similarly it resets the device if Bit 0 is set
+and starts copying the data if Bit 2 is set.
+
+The function driver is also responsible for updating the STATUS
+register.
+
+PCI ENDPOINT TEST DRIVER (HOST SIDE)
+====================================
+
+The host side PCI driver is present in
+drivers/misc/pci_endpoint_test.c
+
+The PCI driver for the test device performs 3 tests
+	*) Verifying addresses programmed in BAR
+	*) Raise legacy IRQ
+	*) Copy data from source address to destination address (TODO)
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index f1dd206..0e3dc8c 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -19,5 +19,7 @@ config PCI_ENDPOINT
 
 	   If in doubt, say "N" to disable Endpoint support.
 
+source "drivers/pci/endpoint/functions/Kconfig"
+
 endmenu
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index 67c88bf..89310d1 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-ep-cfs.o
+					   pci-ep-cfs.o functions/
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
new file mode 100644
index 0000000..175edad
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -0,0 +1,12 @@
+#
+# PCI Endpoint Functions
+#
+
+config PCI_EPF_TEST
+	tristate "PCI Endpoint Test driver"
+	depends on PCI_ENDPOINT
+	help
+	   Enable this configuration option to enable the test driver
+	   for PCI Endpoint.
+
+	   If in doubt, say "N" to disable Endpoint test driver.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
new file mode 100644
index 0000000..53c120e
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for PCI Endpoint Functions
+#
+
+obj-$(CONFIG_PCI_EPF_TEST)		:= pci-epf-test.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
new file mode 100644
index 0000000..a7585b1
--- /dev/null
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -0,0 +1,272 @@
+/**
+ * pci-epf-test.c - Test driver to test endpoint functionality
+ *
+ * Copyright (C) 2016 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/module.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci_regs.h>
+
+#define COMMAND_RESET			BIT(0)
+#define COMMAND_RAISE_IRQ		BIT(1)
+#define COMMAND_COPY			BIT(2)
+
+#define STATUS_INITIALIZED		BIT(0)
+#define STATUS_COPY_PROGRESS		BIT(1)
+#define STATUS_COPY_DONE		BIT(2)
+#define STATUS_IRQ_RAISED		BIT(3)
+#define STATUS_SOURCE_ADDR_INVALID	BIT(4)
+#define STATUS_DEST_ADDR_INVALID	BIT(5)
+
+#define TIMER_RESOLUTION		5
+
+struct pci_epf_test {
+	struct timer_list	timer;
+	void			*reg[6];
+	struct pci_epf		*epf;
+};
+
+struct pci_epf_test_reg {
+	u32	command;
+	u32	status;
+	u64	src_addr;
+	u64	dst_addr;
+};
+
+struct pci_epf_header test_header = {
+	.vendorid	= PCI_ANY_ID,
+	.deviceid	= PCI_ANY_ID,
+	.baseclass_code = PCI_CLASS_OTHERS,
+	.interrupt_pin	= PCI_INTERRUPT_INTA,
+};
+
+static int bar_size[] = { 512, 1024, 16384, 131072, 1048576};
+
+static void pci_epf_test_cmd_handler(unsigned long data)
+{
+	struct pci_epf_test *epf_test = (struct pci_epf_test *)data;
+	struct pci_epf *epf = epf_test->epf;
+	struct pci_epc *epc = epf->epc;
+	struct pci_epf_test_reg *reg = epf_test->reg[0];
+	unsigned long timer;
+
+	if (!reg->command)
+		goto reset_handler;
+
+	if (reg->command & COMMAND_RESET)
+		reg->status = STATUS_INITIALIZED;
+
+	if (reg->command & COMMAND_RAISE_IRQ) {
+		reg->status |= STATUS_IRQ_RAISED;
+		pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY);
+	}
+
+	reg->command = 0;
+
+reset_handler:
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_linkup(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	unsigned long timer;
+
+	setup_timer(&epf_test->timer, pci_epf_test_cmd_handler,
+		    (unsigned long)epf_test);
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_unbind(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct pci_epc *epc = epf->epc;
+	int bar;
+
+	del_timer(&epf_test->timer);
+	pci_epc_stop(epc);
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		if (epf_test->reg[bar]) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			pci_epc_clear_bar(epc, bar);
+		}
+	}
+
+	epf->pci_epc_name = NULL;
+}
+
+static int pci_epf_test_set_bar(struct pci_epf *epf)
+{
+	int flags;
+	int bar;
+	int ret;
+	struct pci_epf_bar *epf_bar;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
+	if (sizeof(dma_addr_t) == 0x8)
+		flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		epf_bar = &epf->bar[bar];
+		ret = pci_epc_set_bar(epc, bar, epf_bar->phys_addr,
+				      epf_bar->size, flags);
+		if (ret) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			dev_err(dev, "failed to set BAR%d\n", bar);
+			if (bar == BAR_0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_alloc_space(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct device *dev = &epf->dev;
+	void *base;
+	int bar;
+
+	base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
+				   BAR_0);
+	if (!base) {
+		dev_err(dev, "failed to allocated register space\n");
+		return -ENOMEM;
+	}
+	epf_test->reg[0] = base;
+
+	for (bar = BAR_1; bar <= BAR_5; bar++) {
+		base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar);
+		if (!base)
+			dev_err(dev, "failed to allocate space for BAR%d\n",
+				bar);
+		epf_test->reg[bar] = base;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_bind(struct pci_epf *epf)
+{
+	int ret;
+	struct pci_epf_header *header = epf->header;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+
+	ret = pci_epc_write_header(epc, header);
+	if (ret) {
+		dev_err(dev, "configuration header write failed\n");
+		return ret;
+	}
+
+	ret = pci_epf_test_alloc_space(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epf_test_set_bar(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epc_start(epc);
+	if (ret) {
+		dev_err(dev, "failed to start endpoint controller\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_probe(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test;
+	struct device *dev = &epf->dev;
+
+	epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
+	if (!epf)
+		return -ENOMEM;
+
+	epf->header = &test_header;
+	epf_test->epf = epf;
+
+	epf_set_drvdata(epf, epf_test);
+	return 0;
+}
+
+static int pci_epf_test_remove(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	pci_epc_unbind_epf(epf_test->epf);
+	kfree(epf_test);
+	return 0;
+}
+
+struct pci_epf_ops ops = {
+	.unbind	= pci_epf_test_unbind,
+	.bind	= pci_epf_test_bind,
+	.linkup = pci_epf_test_linkup,
+};
+
+static const struct pci_epf_device_id pci_epf_test_ids[] = {
+	{
+		.name = "pci_epf_test",
+	},
+	{},
+};
+
+static struct pci_epf_driver test_driver = {
+	.driver.name	= "pci_epf_test",
+	.probe		= pci_epf_test_probe,
+	.remove		= pci_epf_test_remove,
+	.id_table	= pci_epf_test_ids,
+	.ops		= &ops,
+	.owner		= THIS_MODULE,
+};
+
+static int __init pci_epf_test_init(void)
+{
+	int ret;
+
+	ret = pci_epf_register_driver(&test_driver);
+	if (ret) {
+		pr_err("failed to register pci epf test driver --> %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+module_init(pci_epf_test_init);
+
+static void __exit pci_epf_test_exit(void)
+{
+	pci_epf_unregister_driver(&test_driver);
+}
+module_exit(pci_epf_test_exit);
+
+MODULE_DESCRIPTION("PCI EPF TEST DRIVER");
+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>,
	Arnd Bergmann <arnd@arndb.de>, Jingoo Han <jingoohan1@gmail.com>,
	hch@infradead.org, Joao.Pinto@synopsys.com, mingkai.hu@nxp.com,
	m-karicheri2@ti.com, Pratyush Anand <pratyush.anand@gmail.com>
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,
	Joao Pinto <jpinto@synopsys.com>,
	Rob Herring <robh+dt@kernel.org>,
	kishon@ti.com, nsekhar@ti.com
Subject: [RFC PATCH 04/11] pci: endpoint: functions: add an EP function to test PCI
Date: Wed, 14 Sep 2016 10:42:00 +0530	[thread overview]
Message-ID: <1473829927-20466-5-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1473829927-20466-1-git-send-email-kishon@ti.com>

This adds a new endpoint function driver (to program the virtual
test device) making use of the EP-core library. The complete
usage of the test function is described in
Documentation/PCI/pci-test.txt (included in this commit).

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/PCI/00-INDEX                    |    3 +
 Documentation/PCI/pci-test.txt                |   79 +++++++
 drivers/pci/endpoint/Kconfig                  |    2 +
 drivers/pci/endpoint/Makefile                 |    2 +-
 drivers/pci/endpoint/functions/Kconfig        |   12 ++
 drivers/pci/endpoint/functions/Makefile       |    5 +
 drivers/pci/endpoint/functions/pci-epf-test.c |  272 +++++++++++++++++++++++++
 7 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/PCI/pci-test.txt
 create mode 100644 drivers/pci/endpoint/functions/Kconfig
 create mode 100644 drivers/pci/endpoint/functions/Makefile
 create mode 100644 drivers/pci/endpoint/functions/pci-epf-test.c

diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index e422b8151..e5a583c 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -14,3 +14,6 @@ pcieaer-howto.txt
 	- the PCI Express Advanced Error Reporting Driver Guide HOWTO
 pci-endpoint.txt
 	- guide to add endpoint controller driver and endpoint function driver.
+pci-test.txt
+	- description of the PCI EP function that can be used to test PCI
+	  functionality
diff --git a/Documentation/PCI/pci-test.txt b/Documentation/PCI/pci-test.txt
new file mode 100644
index 0000000..2bc796b
--- /dev/null
+++ b/Documentation/PCI/pci-test.txt
@@ -0,0 +1,79 @@
+				PCI TEST
+		    Kishon Vijay Abraham I <kishon@ti.com>
+
+Traditionally PCI RC has always been validated by using standard
+PCI cards like ethernet PCI cards or USB PCI cards or SATA PCI cards.
+However with the addition of EP-core in linux kernel, it is possible
+to configure a PCI controller that can operate in EP mode to work as
+a test device.
+
+The PCI endpoint test device is a completely software device used to
+test the endpoint functionality and serve as a sample driver for other
+PCI endpoint devices.
+
+The PCI endpoint test device has four registers:
+
+	1) PCI_ENDPOINT_TEST_COMMAND
+	2) PCI_ENDPOINT_TEST_STATUS
+	3) PCI_ENDPOINT_TEST_SRC_ADDR
+	4) PCI_ENDPOINT_TEST_DST_ADDR
+
+Since this is a virtual device, all these registers will be present
+in RAM and will be allocated using one of the standard memory allocation
+API (in this case dma_alloc_coherent)
+
+*) PCI_ENDPOINT_TEST_COMMAND:
+
+This register will be used by the host driver to indicate the function
+that the endpoint device must perform.
+
+Bitfield Description:
+  Bit 0: reset the PCI endpoint device
+  Bit 1: raise irq
+  Bit 2: Copy the data from source addr to destination address
+
+*) PCI_ENDPOINT_TEST_STATUS
+
+This register reflects the status of the PCI endpoint device.
+
+Bitfield Description:
+  Bit 0: PCI endpoint device is in initialized state
+  Bit 1: Copy is in progress
+  Bit 2: Copy is done
+  Bit 3: IRQ is raised
+  Bit 4: Source address is invalid
+  Bit 5: Destination address is invalid
+
+*) PCI_ENDPOINT_TEST_SRC_ADDR
+
+This register contains the source address for the COPY command.
+
+*) PCI_ENDPOINT_TEST_DST_ADDR
+
+This register contains the destination address for the COPY command.
+
+PCI ENDPOINT TEST DRIVER (EP SIDE)
+==================================
+
+The Endpoint side function driver is present in
+drivers/pci/endpoint/functions/pci-epf-test.c
+
+This function driver creates the PCI endpoint test device and then
+waits for commands from the host driver. If the host driver sets
+Bit 1 (raise irq) in the COMMAND register, the endpoint driver
+will raise an irq. Similarly it resets the device if Bit 0 is set
+and starts copying the data if Bit 2 is set.
+
+The function driver is also responsible for updating the STATUS
+register.
+
+PCI ENDPOINT TEST DRIVER (HOST SIDE)
+====================================
+
+The host side PCI driver is present in
+drivers/misc/pci_endpoint_test.c
+
+The PCI driver for the test device performs 3 tests
+	*) Verifying addresses programmed in BAR
+	*) Raise legacy IRQ
+	*) Copy data from source address to destination address (TODO)
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index f1dd206..0e3dc8c 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -19,5 +19,7 @@ config PCI_ENDPOINT
 
 	   If in doubt, say "N" to disable Endpoint support.
 
+source "drivers/pci/endpoint/functions/Kconfig"
+
 endmenu
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index 67c88bf..89310d1 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-ep-cfs.o
+					   pci-ep-cfs.o functions/
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
new file mode 100644
index 0000000..175edad
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -0,0 +1,12 @@
+#
+# PCI Endpoint Functions
+#
+
+config PCI_EPF_TEST
+	tristate "PCI Endpoint Test driver"
+	depends on PCI_ENDPOINT
+	help
+	   Enable this configuration option to enable the test driver
+	   for PCI Endpoint.
+
+	   If in doubt, say "N" to disable Endpoint test driver.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
new file mode 100644
index 0000000..53c120e
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for PCI Endpoint Functions
+#
+
+obj-$(CONFIG_PCI_EPF_TEST)		:= pci-epf-test.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
new file mode 100644
index 0000000..a7585b1
--- /dev/null
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -0,0 +1,272 @@
+/**
+ * pci-epf-test.c - Test driver to test endpoint functionality
+ *
+ * Copyright (C) 2016 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/module.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci_regs.h>
+
+#define COMMAND_RESET			BIT(0)
+#define COMMAND_RAISE_IRQ		BIT(1)
+#define COMMAND_COPY			BIT(2)
+
+#define STATUS_INITIALIZED		BIT(0)
+#define STATUS_COPY_PROGRESS		BIT(1)
+#define STATUS_COPY_DONE		BIT(2)
+#define STATUS_IRQ_RAISED		BIT(3)
+#define STATUS_SOURCE_ADDR_INVALID	BIT(4)
+#define STATUS_DEST_ADDR_INVALID	BIT(5)
+
+#define TIMER_RESOLUTION		5
+
+struct pci_epf_test {
+	struct timer_list	timer;
+	void			*reg[6];
+	struct pci_epf		*epf;
+};
+
+struct pci_epf_test_reg {
+	u32	command;
+	u32	status;
+	u64	src_addr;
+	u64	dst_addr;
+};
+
+struct pci_epf_header test_header = {
+	.vendorid	= PCI_ANY_ID,
+	.deviceid	= PCI_ANY_ID,
+	.baseclass_code = PCI_CLASS_OTHERS,
+	.interrupt_pin	= PCI_INTERRUPT_INTA,
+};
+
+static int bar_size[] = { 512, 1024, 16384, 131072, 1048576};
+
+static void pci_epf_test_cmd_handler(unsigned long data)
+{
+	struct pci_epf_test *epf_test = (struct pci_epf_test *)data;
+	struct pci_epf *epf = epf_test->epf;
+	struct pci_epc *epc = epf->epc;
+	struct pci_epf_test_reg *reg = epf_test->reg[0];
+	unsigned long timer;
+
+	if (!reg->command)
+		goto reset_handler;
+
+	if (reg->command & COMMAND_RESET)
+		reg->status = STATUS_INITIALIZED;
+
+	if (reg->command & COMMAND_RAISE_IRQ) {
+		reg->status |= STATUS_IRQ_RAISED;
+		pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY);
+	}
+
+	reg->command = 0;
+
+reset_handler:
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_linkup(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	unsigned long timer;
+
+	setup_timer(&epf_test->timer, pci_epf_test_cmd_handler,
+		    (unsigned long)epf_test);
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_unbind(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct pci_epc *epc = epf->epc;
+	int bar;
+
+	del_timer(&epf_test->timer);
+	pci_epc_stop(epc);
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		if (epf_test->reg[bar]) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			pci_epc_clear_bar(epc, bar);
+		}
+	}
+
+	epf->pci_epc_name = NULL;
+}
+
+static int pci_epf_test_set_bar(struct pci_epf *epf)
+{
+	int flags;
+	int bar;
+	int ret;
+	struct pci_epf_bar *epf_bar;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
+	if (sizeof(dma_addr_t) == 0x8)
+		flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		epf_bar = &epf->bar[bar];
+		ret = pci_epc_set_bar(epc, bar, epf_bar->phys_addr,
+				      epf_bar->size, flags);
+		if (ret) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			dev_err(dev, "failed to set BAR%d\n", bar);
+			if (bar == BAR_0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_alloc_space(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct device *dev = &epf->dev;
+	void *base;
+	int bar;
+
+	base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
+				   BAR_0);
+	if (!base) {
+		dev_err(dev, "failed to allocated register space\n");
+		return -ENOMEM;
+	}
+	epf_test->reg[0] = base;
+
+	for (bar = BAR_1; bar <= BAR_5; bar++) {
+		base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar);
+		if (!base)
+			dev_err(dev, "failed to allocate space for BAR%d\n",
+				bar);
+		epf_test->reg[bar] = base;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_bind(struct pci_epf *epf)
+{
+	int ret;
+	struct pci_epf_header *header = epf->header;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+
+	ret = pci_epc_write_header(epc, header);
+	if (ret) {
+		dev_err(dev, "configuration header write failed\n");
+		return ret;
+	}
+
+	ret = pci_epf_test_alloc_space(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epf_test_set_bar(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epc_start(epc);
+	if (ret) {
+		dev_err(dev, "failed to start endpoint controller\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_probe(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test;
+	struct device *dev = &epf->dev;
+
+	epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
+	if (!epf)
+		return -ENOMEM;
+
+	epf->header = &test_header;
+	epf_test->epf = epf;
+
+	epf_set_drvdata(epf, epf_test);
+	return 0;
+}
+
+static int pci_epf_test_remove(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	pci_epc_unbind_epf(epf_test->epf);
+	kfree(epf_test);
+	return 0;
+}
+
+struct pci_epf_ops ops = {
+	.unbind	= pci_epf_test_unbind,
+	.bind	= pci_epf_test_bind,
+	.linkup = pci_epf_test_linkup,
+};
+
+static const struct pci_epf_device_id pci_epf_test_ids[] = {
+	{
+		.name = "pci_epf_test",
+	},
+	{},
+};
+
+static struct pci_epf_driver test_driver = {
+	.driver.name	= "pci_epf_test",
+	.probe		= pci_epf_test_probe,
+	.remove		= pci_epf_test_remove,
+	.id_table	= pci_epf_test_ids,
+	.ops		= &ops,
+	.owner		= THIS_MODULE,
+};
+
+static int __init pci_epf_test_init(void)
+{
+	int ret;
+
+	ret = pci_epf_register_driver(&test_driver);
+	if (ret) {
+		pr_err("failed to register pci epf test driver --> %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+module_init(pci_epf_test_init);
+
+static void __exit pci_epf_test_exit(void)
+{
+	pci_epf_unregister_driver(&test_driver);
+}
+module_exit(pci_epf_test_exit);
+
+MODULE_DESCRIPTION("PCI EPF TEST DRIVER");
+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@ti.com (Kishon Vijay Abraham I)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 04/11] pci: endpoint: functions: add an EP function to test PCI
Date: Wed, 14 Sep 2016 10:42:00 +0530	[thread overview]
Message-ID: <1473829927-20466-5-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1473829927-20466-1-git-send-email-kishon@ti.com>

This adds a new endpoint function driver (to program the virtual
test device) making use of the EP-core library. The complete
usage of the test function is described in
Documentation/PCI/pci-test.txt (included in this commit).

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/PCI/00-INDEX                    |    3 +
 Documentation/PCI/pci-test.txt                |   79 +++++++
 drivers/pci/endpoint/Kconfig                  |    2 +
 drivers/pci/endpoint/Makefile                 |    2 +-
 drivers/pci/endpoint/functions/Kconfig        |   12 ++
 drivers/pci/endpoint/functions/Makefile       |    5 +
 drivers/pci/endpoint/functions/pci-epf-test.c |  272 +++++++++++++++++++++++++
 7 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/PCI/pci-test.txt
 create mode 100644 drivers/pci/endpoint/functions/Kconfig
 create mode 100644 drivers/pci/endpoint/functions/Makefile
 create mode 100644 drivers/pci/endpoint/functions/pci-epf-test.c

diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index e422b8151..e5a583c 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -14,3 +14,6 @@ pcieaer-howto.txt
 	- the PCI Express Advanced Error Reporting Driver Guide HOWTO
 pci-endpoint.txt
 	- guide to add endpoint controller driver and endpoint function driver.
+pci-test.txt
+	- description of the PCI EP function that can be used to test PCI
+	  functionality
diff --git a/Documentation/PCI/pci-test.txt b/Documentation/PCI/pci-test.txt
new file mode 100644
index 0000000..2bc796b
--- /dev/null
+++ b/Documentation/PCI/pci-test.txt
@@ -0,0 +1,79 @@
+				PCI TEST
+		    Kishon Vijay Abraham I <kishon@ti.com>
+
+Traditionally PCI RC has always been validated by using standard
+PCI cards like ethernet PCI cards or USB PCI cards or SATA PCI cards.
+However with the addition of EP-core in linux kernel, it is possible
+to configure a PCI controller that can operate in EP mode to work as
+a test device.
+
+The PCI endpoint test device is a completely software device used to
+test the endpoint functionality and serve as a sample driver for other
+PCI endpoint devices.
+
+The PCI endpoint test device has four registers:
+
+	1) PCI_ENDPOINT_TEST_COMMAND
+	2) PCI_ENDPOINT_TEST_STATUS
+	3) PCI_ENDPOINT_TEST_SRC_ADDR
+	4) PCI_ENDPOINT_TEST_DST_ADDR
+
+Since this is a virtual device, all these registers will be present
+in RAM and will be allocated using one of the standard memory allocation
+API (in this case dma_alloc_coherent)
+
+*) PCI_ENDPOINT_TEST_COMMAND:
+
+This register will be used by the host driver to indicate the function
+that the endpoint device must perform.
+
+Bitfield Description:
+  Bit 0: reset the PCI endpoint device
+  Bit 1: raise irq
+  Bit 2: Copy the data from source addr to destination address
+
+*) PCI_ENDPOINT_TEST_STATUS
+
+This register reflects the status of the PCI endpoint device.
+
+Bitfield Description:
+  Bit 0: PCI endpoint device is in initialized state
+  Bit 1: Copy is in progress
+  Bit 2: Copy is done
+  Bit 3: IRQ is raised
+  Bit 4: Source address is invalid
+  Bit 5: Destination address is invalid
+
+*) PCI_ENDPOINT_TEST_SRC_ADDR
+
+This register contains the source address for the COPY command.
+
+*) PCI_ENDPOINT_TEST_DST_ADDR
+
+This register contains the destination address for the COPY command.
+
+PCI ENDPOINT TEST DRIVER (EP SIDE)
+==================================
+
+The Endpoint side function driver is present in
+drivers/pci/endpoint/functions/pci-epf-test.c
+
+This function driver creates the PCI endpoint test device and then
+waits for commands from the host driver. If the host driver sets
+Bit 1 (raise irq) in the COMMAND register, the endpoint driver
+will raise an irq. Similarly it resets the device if Bit 0 is set
+and starts copying the data if Bit 2 is set.
+
+The function driver is also responsible for updating the STATUS
+register.
+
+PCI ENDPOINT TEST DRIVER (HOST SIDE)
+====================================
+
+The host side PCI driver is present in
+drivers/misc/pci_endpoint_test.c
+
+The PCI driver for the test device performs 3 tests
+	*) Verifying addresses programmed in BAR
+	*) Raise legacy IRQ
+	*) Copy data from source address to destination address (TODO)
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index f1dd206..0e3dc8c 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -19,5 +19,7 @@ config PCI_ENDPOINT
 
 	   If in doubt, say "N" to disable Endpoint support.
 
+source "drivers/pci/endpoint/functions/Kconfig"
+
 endmenu
 
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
index 67c88bf..89310d1 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-ep-cfs.o
+					   pci-ep-cfs.o functions/
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
new file mode 100644
index 0000000..175edad
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -0,0 +1,12 @@
+#
+# PCI Endpoint Functions
+#
+
+config PCI_EPF_TEST
+	tristate "PCI Endpoint Test driver"
+	depends on PCI_ENDPOINT
+	help
+	   Enable this configuration option to enable the test driver
+	   for PCI Endpoint.
+
+	   If in doubt, say "N" to disable Endpoint test driver.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
new file mode 100644
index 0000000..53c120e
--- /dev/null
+++ b/drivers/pci/endpoint/functions/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for PCI Endpoint Functions
+#
+
+obj-$(CONFIG_PCI_EPF_TEST)		:= pci-epf-test.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
new file mode 100644
index 0000000..a7585b1
--- /dev/null
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -0,0 +1,272 @@
+/**
+ * pci-epf-test.c - Test driver to test endpoint functionality
+ *
+ * Copyright (C) 2016 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/module.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci_regs.h>
+
+#define COMMAND_RESET			BIT(0)
+#define COMMAND_RAISE_IRQ		BIT(1)
+#define COMMAND_COPY			BIT(2)
+
+#define STATUS_INITIALIZED		BIT(0)
+#define STATUS_COPY_PROGRESS		BIT(1)
+#define STATUS_COPY_DONE		BIT(2)
+#define STATUS_IRQ_RAISED		BIT(3)
+#define STATUS_SOURCE_ADDR_INVALID	BIT(4)
+#define STATUS_DEST_ADDR_INVALID	BIT(5)
+
+#define TIMER_RESOLUTION		5
+
+struct pci_epf_test {
+	struct timer_list	timer;
+	void			*reg[6];
+	struct pci_epf		*epf;
+};
+
+struct pci_epf_test_reg {
+	u32	command;
+	u32	status;
+	u64	src_addr;
+	u64	dst_addr;
+};
+
+struct pci_epf_header test_header = {
+	.vendorid	= PCI_ANY_ID,
+	.deviceid	= PCI_ANY_ID,
+	.baseclass_code = PCI_CLASS_OTHERS,
+	.interrupt_pin	= PCI_INTERRUPT_INTA,
+};
+
+static int bar_size[] = { 512, 1024, 16384, 131072, 1048576};
+
+static void pci_epf_test_cmd_handler(unsigned long data)
+{
+	struct pci_epf_test *epf_test = (struct pci_epf_test *)data;
+	struct pci_epf *epf = epf_test->epf;
+	struct pci_epc *epc = epf->epc;
+	struct pci_epf_test_reg *reg = epf_test->reg[0];
+	unsigned long timer;
+
+	if (!reg->command)
+		goto reset_handler;
+
+	if (reg->command & COMMAND_RESET)
+		reg->status = STATUS_INITIALIZED;
+
+	if (reg->command & COMMAND_RAISE_IRQ) {
+		reg->status |= STATUS_IRQ_RAISED;
+		pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY);
+	}
+
+	reg->command = 0;
+
+reset_handler:
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_linkup(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	unsigned long timer;
+
+	setup_timer(&epf_test->timer, pci_epf_test_cmd_handler,
+		    (unsigned long)epf_test);
+	timer = jiffies + msecs_to_jiffies(TIMER_RESOLUTION);
+	mod_timer(&epf_test->timer, timer);
+}
+
+static void pci_epf_test_unbind(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct pci_epc *epc = epf->epc;
+	int bar;
+
+	del_timer(&epf_test->timer);
+	pci_epc_stop(epc);
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		if (epf_test->reg[bar]) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			pci_epc_clear_bar(epc, bar);
+		}
+	}
+
+	epf->pci_epc_name = NULL;
+}
+
+static int pci_epf_test_set_bar(struct pci_epf *epf)
+{
+	int flags;
+	int bar;
+	int ret;
+	struct pci_epf_bar *epf_bar;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
+	if (sizeof(dma_addr_t) == 0x8)
+		flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+	for (bar = BAR_0; bar <= BAR_5; bar++) {
+		epf_bar = &epf->bar[bar];
+		ret = pci_epc_set_bar(epc, bar, epf_bar->phys_addr,
+				      epf_bar->size, flags);
+		if (ret) {
+			pci_epf_free_space(epf, epf_test->reg[bar], bar);
+			dev_err(dev, "failed to set BAR%d\n", bar);
+			if (bar == BAR_0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_alloc_space(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+	struct device *dev = &epf->dev;
+	void *base;
+	int bar;
+
+	base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
+				   BAR_0);
+	if (!base) {
+		dev_err(dev, "failed to allocated register space\n");
+		return -ENOMEM;
+	}
+	epf_test->reg[0] = base;
+
+	for (bar = BAR_1; bar <= BAR_5; bar++) {
+		base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar);
+		if (!base)
+			dev_err(dev, "failed to allocate space for BAR%d\n",
+				bar);
+		epf_test->reg[bar] = base;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_bind(struct pci_epf *epf)
+{
+	int ret;
+	struct pci_epf_header *header = epf->header;
+	struct pci_epc *epc = epf->epc;
+	struct device *dev = &epf->dev;
+
+	ret = pci_epc_write_header(epc, header);
+	if (ret) {
+		dev_err(dev, "configuration header write failed\n");
+		return ret;
+	}
+
+	ret = pci_epf_test_alloc_space(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epf_test_set_bar(epf);
+	if (ret)
+		return ret;
+
+	ret = pci_epc_start(epc);
+	if (ret) {
+		dev_err(dev, "failed to start endpoint controller\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pci_epf_test_probe(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test;
+	struct device *dev = &epf->dev;
+
+	epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
+	if (!epf)
+		return -ENOMEM;
+
+	epf->header = &test_header;
+	epf_test->epf = epf;
+
+	epf_set_drvdata(epf, epf_test);
+	return 0;
+}
+
+static int pci_epf_test_remove(struct pci_epf *epf)
+{
+	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+	pci_epc_unbind_epf(epf_test->epf);
+	kfree(epf_test);
+	return 0;
+}
+
+struct pci_epf_ops ops = {
+	.unbind	= pci_epf_test_unbind,
+	.bind	= pci_epf_test_bind,
+	.linkup = pci_epf_test_linkup,
+};
+
+static const struct pci_epf_device_id pci_epf_test_ids[] = {
+	{
+		.name = "pci_epf_test",
+	},
+	{},
+};
+
+static struct pci_epf_driver test_driver = {
+	.driver.name	= "pci_epf_test",
+	.probe		= pci_epf_test_probe,
+	.remove		= pci_epf_test_remove,
+	.id_table	= pci_epf_test_ids,
+	.ops		= &ops,
+	.owner		= THIS_MODULE,
+};
+
+static int __init pci_epf_test_init(void)
+{
+	int ret;
+
+	ret = pci_epf_register_driver(&test_driver);
+	if (ret) {
+		pr_err("failed to register pci epf test driver --> %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+module_init(pci_epf_test_init);
+
+static void __exit pci_epf_test_exit(void)
+{
+	pci_epf_unregister_driver(&test_driver);
+}
+module_exit(pci_epf_test_exit);
+
+MODULE_DESCRIPTION("PCI EPF TEST DRIVER");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

  parent reply	other threads:[~2016-09-14  5:13 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-14  5:11 [RFC PATCH 00/11] pci: support for configurable PCI endpoint Kishon Vijay Abraham I
2016-09-14  5:11 ` Kishon Vijay Abraham I
2016-09-14  5:11 ` Kishon Vijay Abraham I
2016-09-14  5:11 ` [RFC PATCH 01/11] pci: endpoint: add EP core layer to enable EP controller and EP functions Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-10-12 12:38   ` Christoph Hellwig
2016-10-12 12:38     ` Christoph Hellwig
2016-10-12 12:38     ` Christoph Hellwig
2016-10-12 12:38     ` Christoph Hellwig
2016-09-14  5:11 ` [RFC PATCH 02/11] pci: endpoint: introduce configfs entry for configuring " Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-10-12 12:42   ` Christoph Hellwig
2016-10-12 12:42     ` Christoph Hellwig
2016-10-12 12:42     ` Christoph Hellwig
2016-10-12 12:42     ` Christoph Hellwig
2016-09-14  5:11 ` [RFC PATCH 03/11] Documentation: PCI: guide to use PCI Endpoint Core Layer Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-09-14  5:11   ` Kishon Vijay Abraham I
2016-09-14  5:12 ` Kishon Vijay Abraham I [this message]
2016-09-14  5:12   ` [RFC PATCH 04/11] pci: endpoint: functions: add an EP function to test PCI Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 05/11] pci: rename *host* directory to *controller* Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-10-12 12:43   ` Christoph Hellwig
2016-10-12 12:43     ` Christoph Hellwig
2016-10-12 12:43     ` Christoph Hellwig
2016-10-12 12:43     ` Christoph Hellwig
2016-09-14  5:12 ` [RFC PATCH 06/11] pci: controller: split designware into *core* and *host* Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 07/11] pci: controller: designware: Add EP mode support Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-23 14:41   ` Rob Herring
2016-09-23 14:41     ` Rob Herring
2016-09-27 11:28     ` Kishon Vijay Abraham I
2016-09-27 11:28       ` Kishon Vijay Abraham I
2016-09-27 11:28       ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 08/11] pci: controller: dra7xx: " Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-23 14:52   ` Rob Herring
2016-09-23 14:52     ` Rob Herring
2016-09-27 11:34     ` Kishon Vijay Abraham I
2016-09-27 11:34       ` Kishon Vijay Abraham I
2016-09-27 11:34       ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 09/11] misc: add a new host side PCI endpoint test driver Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 10/11] ARM: dts: DRA7: Modify pcie1 dt node for EP mode Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12 ` [RFC PATCH 11/11] HACK: pci: controller: dra7xx: disable smart idle Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14  5:12   ` Kishon Vijay Abraham I
2016-09-14 13:25 ` [RFC PATCH 00/11] pci: support for configurable PCI endpoint Arnd Bergmann
2016-09-14 13:25   ` Arnd Bergmann
2016-09-15  8:33   ` Kishon Vijay Abraham I
2016-09-15  8:33     ` Kishon Vijay Abraham I
2016-09-15  8:33     ` Kishon Vijay Abraham I
2016-09-22 13:34     ` Arnd Bergmann
2016-09-22 13:34       ` Arnd Bergmann
2016-09-22 13:34       ` Arnd Bergmann
2016-09-26  6:08       ` Kishon Vijay Abraham I
2016-09-26  6:08         ` Kishon Vijay Abraham I
2016-09-26  6:08         ` Kishon Vijay Abraham I
2016-09-29  8:31         ` Kishon Vijay Abraham I
2016-09-29  8:31           ` Kishon Vijay Abraham I
2016-09-29  8:31           ` Kishon Vijay Abraham I
2016-09-29  8:31           ` Kishon Vijay Abraham I
2016-10-12 12:21         ` Christoph Hellwig
2016-10-12 12:21           ` Christoph Hellwig
2016-10-12 12:21           ` Christoph Hellwig
2016-10-12 12:21           ` Christoph Hellwig

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=1473829927-20466-5-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=hch@infradead.org \
    --cc=jingoohan1@gmail.com \
    --cc=jpinto@synopsys.com \
    --cc=linux-arm-kernel@lists.infradead.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=m-karicheri2@ti.com \
    --cc=mingkai.hu@nxp.com \
    --cc=nsekhar@ti.com \
    --cc=pratyush.anand@gmail.com \
    --cc=robh+dt@kernel.org \
    /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.