All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: Joao Pinto <Joao.Pinto@synopsys.com>,
	Arnd Bergmann <arnd@arndb.de>, <gregkh@linuxfoundation.org>,
	<kishon@ti.com>, <nsekhar@ti.com>, <linux-pci@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <linux-omap@vger.kernel.org>
Subject: [PATCH 04/18] PCI: endpoint: pci-epc-mem: Add support for configurable page size
Date: Fri, 18 Aug 2017 20:27:56 +0530	[thread overview]
Message-ID: <20170818145810.17649-5-kishon@ti.com> (raw)
In-Reply-To: <20170818145810.17649-1-kishon@ti.com>

pci-epc-mem uses a page size equal to *PAGE_SIZE* (usually 4KB) to
manage the address space. However certain platforms like TI's K2G
has a restriction that this address space should be either divided
into 1MB/2MB/4MB or 8MB sizes (Ref: 11.14.4.9.1 Outbound Address
Translation in K2G TRM SPRUHY8F January 2016 – Revised May 2017).
Add support to handle different page sizes here.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/pci-epc-mem.c | 59 ++++++++++++++++++++++++++++++++------
 include/linux/pci-epc.h            |  8 +++++-
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
index 3a94cc1caf22..83b7d5d3fc3e 100644
--- a/drivers/pci/endpoint/pci-epc-mem.c
+++ b/drivers/pci/endpoint/pci-epc-mem.c
@@ -24,21 +24,54 @@
 #include <linux/pci-epc.h>
 
 /**
- * pci_epc_mem_init() - initialize the pci_epc_mem structure
+ * pci_epc_mem_get_order() - determine the allocation order of a memory size
+ * @mem: address space of the endpoint controller
+ * @size: the size for which to get the order
+ *
+ * Reimplement get_order() for mem->page_size since the generic get_order
+ * always gets order with a constant PAGE_SIZE.
+ */
+static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size)
+{
+	int order;
+	unsigned int page_shift = ilog2(mem->page_size);
+
+	size--;
+	size >>= page_shift;
+#if BITS_PER_LONG == 32
+	order = fls(size);
+#else
+	order = fls64(size);
+#endif
+	return order;
+}
+
+/**
+ * __pci_epc_mem_init() - initialize the pci_epc_mem structure
  * @epc: the EPC device that invoked pci_epc_mem_init
  * @phys_base: the physical address of the base
  * @size: the size of the address space
+ * @page_size: size of each page
  *
  * Invoke to initialize the pci_epc_mem structure used by the
  * endpoint functions to allocate mapped PCI address.
  */
-int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
+int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size,
+		       size_t page_size)
 {
 	int ret;
 	struct pci_epc_mem *mem;
 	unsigned long *bitmap;
-	int pages = size >> PAGE_SHIFT;
-	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+	unsigned int page_shift;
+	int pages;
+	int bitmap_size;
+
+	if (page_size < PAGE_SIZE)
+		page_size = PAGE_SIZE;
+
+	page_shift = ilog2(page_size);
+	pages = size >> page_shift;
+	bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem) {
@@ -54,6 +87,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
 
 	mem->bitmap = bitmap;
 	mem->phys_base = phys_base;
+	mem->page_size = page_size;
 	mem->pages = pages;
 	mem->size = size;
 
@@ -67,7 +101,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
 err:
 return ret;
 }
-EXPORT_SYMBOL_GPL(pci_epc_mem_init);
+EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
 
 /**
  * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
@@ -101,13 +135,17 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
 	int pageno;
 	void __iomem *virt_addr;
 	struct pci_epc_mem *mem = epc->mem;
-	int order = get_order(size);
+	unsigned int page_shift = ilog2(mem->page_size);
+	int order;
+
+	size = ALIGN(size, mem->page_size);
+	order = pci_epc_mem_get_order(mem, size);
 
 	pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
 	if (pageno < 0)
 		return NULL;
 
-	*phys_addr = mem->phys_base + (pageno << PAGE_SHIFT);
+	*phys_addr = mem->phys_base + (pageno << page_shift);
 	virt_addr = ioremap(*phys_addr, size);
 	if (!virt_addr)
 		bitmap_release_region(mem->bitmap, pageno, order);
@@ -129,11 +167,14 @@ void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
 			   void __iomem *virt_addr, size_t size)
 {
 	int pageno;
-	int order = get_order(size);
 	struct pci_epc_mem *mem = epc->mem;
+	unsigned int page_shift = ilog2(mem->page_size);
+	int order;
 
 	iounmap(virt_addr);
-	pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT;
+	pageno = (phys_addr - mem->phys_base) >> page_shift;
+	size = ALIGN(size, mem->page_size);
+	order = pci_epc_mem_get_order(mem, size);
 	bitmap_release_region(mem->bitmap, pageno, order);
 }
 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index af5edbf3eea3..f7a04e1af112 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -62,11 +62,13 @@ struct pci_epc_ops {
  * @size: the size of the PCI address space
  * @bitmap: bitmap to manage the PCI address space
  * @pages: number of bits representing the address region
+ * @page_size: size of each page
  */
 struct pci_epc_mem {
 	phys_addr_t	phys_base;
 	size_t		size;
 	unsigned long	*bitmap;
+	size_t		page_size;
 	int		pages;
 };
 
@@ -98,6 +100,9 @@ struct pci_epc {
 #define devm_pci_epc_create(dev, ops)    \
 		__devm_pci_epc_create((dev), (ops), THIS_MODULE)
 
+#define pci_epc_mem_init(epc, phys_addr, size)	\
+		__pci_epc_mem_init((epc), (phys_addr), (size), PAGE_SIZE)
+
 static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
 {
 	dev_set_drvdata(&epc->dev, data);
@@ -135,7 +140,8 @@ void pci_epc_stop(struct pci_epc *epc);
 struct pci_epc *pci_epc_get(const char *epc_name);
 void pci_epc_put(struct pci_epc *epc);
 
-int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size);
+int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size,
+		       size_t page_size);
 void pci_epc_mem_exit(struct pci_epc *epc);
 void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
 				     phys_addr_t *phys_addr, size_t size);
-- 
2.11.0

WARNING: multiple messages have this Message-ID (diff)
From: Kishon Vijay Abraham I <kishon@ti.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: Joao Pinto <Joao.Pinto@synopsys.com>,
	Arnd Bergmann <arnd@arndb.de>,
	gregkh@linuxfoundation.org, kishon@ti.com, nsekhar@ti.com,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-omap@vger.kernel.org
Subject: [PATCH 04/18] PCI: endpoint: pci-epc-mem: Add support for configurable page size
Date: Fri, 18 Aug 2017 20:27:56 +0530	[thread overview]
Message-ID: <20170818145810.17649-5-kishon@ti.com> (raw)
In-Reply-To: <20170818145810.17649-1-kishon@ti.com>

pci-epc-mem uses a page size equal to *PAGE_SIZE* (usually 4KB) to
manage the address space. However certain platforms like TI's K2G
has a restriction that this address space should be either divided
into 1MB/2MB/4MB or 8MB sizes (Ref: 11.14.4.9.1 Outbound Address
Translation in K2G TRM SPRUHY8F January 2016 – Revised May 2017).
Add support to handle different page sizes here.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/endpoint/pci-epc-mem.c | 59 ++++++++++++++++++++++++++++++++------
 include/linux/pci-epc.h            |  8 +++++-
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
index 3a94cc1caf22..83b7d5d3fc3e 100644
--- a/drivers/pci/endpoint/pci-epc-mem.c
+++ b/drivers/pci/endpoint/pci-epc-mem.c
@@ -24,21 +24,54 @@
 #include <linux/pci-epc.h>
 
 /**
- * pci_epc_mem_init() - initialize the pci_epc_mem structure
+ * pci_epc_mem_get_order() - determine the allocation order of a memory size
+ * @mem: address space of the endpoint controller
+ * @size: the size for which to get the order
+ *
+ * Reimplement get_order() for mem->page_size since the generic get_order
+ * always gets order with a constant PAGE_SIZE.
+ */
+static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size)
+{
+	int order;
+	unsigned int page_shift = ilog2(mem->page_size);
+
+	size--;
+	size >>= page_shift;
+#if BITS_PER_LONG == 32
+	order = fls(size);
+#else
+	order = fls64(size);
+#endif
+	return order;
+}
+
+/**
+ * __pci_epc_mem_init() - initialize the pci_epc_mem structure
  * @epc: the EPC device that invoked pci_epc_mem_init
  * @phys_base: the physical address of the base
  * @size: the size of the address space
+ * @page_size: size of each page
  *
  * Invoke to initialize the pci_epc_mem structure used by the
  * endpoint functions to allocate mapped PCI address.
  */
-int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
+int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size,
+		       size_t page_size)
 {
 	int ret;
 	struct pci_epc_mem *mem;
 	unsigned long *bitmap;
-	int pages = size >> PAGE_SHIFT;
-	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+	unsigned int page_shift;
+	int pages;
+	int bitmap_size;
+
+	if (page_size < PAGE_SIZE)
+		page_size = PAGE_SIZE;
+
+	page_shift = ilog2(page_size);
+	pages = size >> page_shift;
+	bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem) {
@@ -54,6 +87,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
 
 	mem->bitmap = bitmap;
 	mem->phys_base = phys_base;
+	mem->page_size = page_size;
 	mem->pages = pages;
 	mem->size = size;
 
@@ -67,7 +101,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
 err:
 return ret;
 }
-EXPORT_SYMBOL_GPL(pci_epc_mem_init);
+EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
 
 /**
  * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
@@ -101,13 +135,17 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
 	int pageno;
 	void __iomem *virt_addr;
 	struct pci_epc_mem *mem = epc->mem;
-	int order = get_order(size);
+	unsigned int page_shift = ilog2(mem->page_size);
+	int order;
+
+	size = ALIGN(size, mem->page_size);
+	order = pci_epc_mem_get_order(mem, size);
 
 	pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
 	if (pageno < 0)
 		return NULL;
 
-	*phys_addr = mem->phys_base + (pageno << PAGE_SHIFT);
+	*phys_addr = mem->phys_base + (pageno << page_shift);
 	virt_addr = ioremap(*phys_addr, size);
 	if (!virt_addr)
 		bitmap_release_region(mem->bitmap, pageno, order);
@@ -129,11 +167,14 @@ void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
 			   void __iomem *virt_addr, size_t size)
 {
 	int pageno;
-	int order = get_order(size);
 	struct pci_epc_mem *mem = epc->mem;
+	unsigned int page_shift = ilog2(mem->page_size);
+	int order;
 
 	iounmap(virt_addr);
-	pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT;
+	pageno = (phys_addr - mem->phys_base) >> page_shift;
+	size = ALIGN(size, mem->page_size);
+	order = pci_epc_mem_get_order(mem, size);
 	bitmap_release_region(mem->bitmap, pageno, order);
 }
 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index af5edbf3eea3..f7a04e1af112 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -62,11 +62,13 @@ struct pci_epc_ops {
  * @size: the size of the PCI address space
  * @bitmap: bitmap to manage the PCI address space
  * @pages: number of bits representing the address region
+ * @page_size: size of each page
  */
 struct pci_epc_mem {
 	phys_addr_t	phys_base;
 	size_t		size;
 	unsigned long	*bitmap;
+	size_t		page_size;
 	int		pages;
 };
 
@@ -98,6 +100,9 @@ struct pci_epc {
 #define devm_pci_epc_create(dev, ops)    \
 		__devm_pci_epc_create((dev), (ops), THIS_MODULE)
 
+#define pci_epc_mem_init(epc, phys_addr, size)	\
+		__pci_epc_mem_init((epc), (phys_addr), (size), PAGE_SIZE)
+
 static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
 {
 	dev_set_drvdata(&epc->dev, data);
@@ -135,7 +140,8 @@ void pci_epc_stop(struct pci_epc *epc);
 struct pci_epc *pci_epc_get(const char *epc_name);
 void pci_epc_put(struct pci_epc *epc);
 
-int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size);
+int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size,
+		       size_t page_size);
 void pci_epc_mem_exit(struct pci_epc *epc);
 void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
 				     phys_addr_t *phys_addr, size_t size);
-- 
2.11.0

  parent reply	other threads:[~2017-08-18 14:58 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-18 14:57 [PATCH 00/18] PCI: endpoint: Make pci-epf-test more flexible Kishon Vijay Abraham I
2017-08-18 14:57 ` Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 01/18] PCI: endpoint: pci-epc-core: Use of_dma_configure() to set initial dma mask Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 02/18] PCI: endpoint: pci-epf-core: Add an API to get matching "pci_epf_device_id" Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 03/18] PCI: endpoint: pci-epf-core: Make ->remove() callback optional Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:57 ` Kishon Vijay Abraham I [this message]
2017-08-18 14:57   ` [PATCH 04/18] PCI: endpoint: pci-epc-mem: Add support for configurable page size Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 05/18] PCI: endpoint: functions/pci-epf-test: Add "volatile" to pci_epf_test_reg Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 06/18] PCI: endpoint: functions/pci-epf-test: Do not reset *command* inadvertently Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:57 ` [PATCH 07/18] PCI: endpoint: functions/pci-epf-test: Add support to use _any_ BAR's to map PCI_ENDPOINT_TEST regs Kishon Vijay Abraham I
2017-08-18 14:57   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 08/18] PCI: endpoint: functions/pci-epf-test: Add support to poll early for host commands Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 09/18] PCI: endpoint: functions/pci-epf-test: Remove the ->remove() callback Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 10/18] PCI: dwc: designware: Provide page_size to pci_epc_mem Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 11/18] PCI: dwc: dra7xx: Reset all BARs during initialization Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 12/18] PCI: dwc: designware-ep: Do not disable " Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 13/18] misc: pci_endpoint_test: Add support for PCI_ENDPOINT_TEST regs to be mapped to any BAR Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 14/18] misc: pci_endpoint_test: Add support to provide aligned buffer addresses Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 15/18] misc: pci_endpoint_test: Add support to not enable MSI interrupts Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 16/18] misc: pci_endpoint_test: Avoid using hard coded BAR sizes Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 17/18] misc: pci_endpoint_test: Enable/Disable MSI using module param Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 14:58 ` [PATCH 18/18] tools: PCI: Add a missing option help line Kishon Vijay Abraham I
2017-08-18 14:58   ` Kishon Vijay Abraham I
2017-08-18 15:53 ` [PATCH 00/18] PCI: endpoint: Make pci-epf-test more flexible Bjorn Helgaas

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=20170818145810.17649-5-kishon@ti.com \
    --to=kishon@ti.com \
    --cc=Joao.Pinto@synopsys.com \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-pci@vger.kernel.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.