2023-01-13 09:13:28

by Shunsuke Mie

[permalink] [raw]
Subject: [RFC PATCH 0/3] Deal with alignment restriction on EP side

Some PCIe EPC controllers have restriction to map PCIe address space to the
local memory space. The mapping is needed to access memory of other side.
On epf test, RC module prepares an aligned memory, and EP module maps the
region. However, a EP module which emulate a device (e.g. VirtIO, NVMe and
etc) cannot expect that a driver for the device prepares an aligned memory.
So, a EP side should deal with the alignment restriction.

This patchset addresses with the alignment restriction on EP size. A
content as follows:
1. Improve a pci epc unmap/map functions to cover the alignment restriction
with adding epc driver support as EPC ops.
2. Implement the support function for DWC EPC driver.
3. Adapt the pci-epf-test to the map/unmap function updated at first patch.

I tested this changes on RENESAS board has DWC PCIeC.

This is a RFC, and it has patches for testing only. Following changes are
not included yet:
1. Removing alignment codes on RC side completely
2. Adapting map/unmap() changes to pci-epf-ntb/vntb

Best,
Shunsuke

Shunsuke Mie (3):
PCI: endpoint: support an alignment aware map/unmaping
PCI: dwc: support align_mem() callback for pci_epc_epc
PCI: endpoint: support pci_epc_mem_map/unmap API changes

.../pci/controller/dwc/pcie-designware-ep.c | 13 +++
drivers/pci/endpoint/functions/pci-epf-test.c | 89 +++++--------------
drivers/pci/endpoint/pci-epc-core.c | 57 +++++++++---
include/linux/pci-epc.h | 10 ++-
4 files changed, 90 insertions(+), 79 deletions(-)

--
2.25.1


2023-01-13 09:30:30

by Shunsuke Mie

[permalink] [raw]
Subject: [RFC PATCH 2/3] PCI: dwc: support align_mem() callback for pci_epc_epc

DWC PCIe EPC driver has alignment restriction for mapping as
pci->region_align. Use it to align memory.

Signed-off-by: Shunsuke Mie <[email protected]>
---
drivers/pci/controller/dwc/pcie-designware-ep.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d06654895eba..7a7d7513b612 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -444,6 +444,18 @@ static void dw_pcie_ep_stop(struct pci_epc *epc)
dw_pcie_stop_link(pci);
}

+static u64 dw_pcie_ep_align_mem(struct pci_epc *epc, u64 addr, size_t *size)
+{
+ struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ u64 aaddr;
+
+ aaddr = ALIGN_DOWN(addr, pci->region_align);
+ *size += addr - aaddr;
+
+ return aaddr;
+}
+
static int dw_pcie_ep_start(struct pci_epc *epc)
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
@@ -474,6 +486,7 @@ static const struct pci_epc_ops epc_ops = {
.set_msix = dw_pcie_ep_set_msix,
.get_msix = dw_pcie_ep_get_msix,
.raise_irq = dw_pcie_ep_raise_irq,
+ .align_mem = dw_pcie_ep_align_mem,
.start = dw_pcie_ep_start,
.stop = dw_pcie_ep_stop,
.get_features = dw_pcie_ep_get_features,
--
2.25.1

2023-01-13 09:31:22

by Shunsuke Mie

[permalink] [raw]
Subject: [RFC PATCH 3/3] PCI: endpoint: support pci_epc_mem_map/unmap API changes

The APIs have changed to support non aligned memory mapping on
endpoint. Adapt the new API to pci-epf-test. The API allocate
pci epc memory inside, so remove allocations.

Signed-off-by: Shunsuke Mie <[email protected]>
---
drivers/pci/endpoint/functions/pci-epf-test.c | 89 +++++--------------
1 file changed, 24 insertions(+), 65 deletions(-)

diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 55283d2379a6..73e75591fd81 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -323,37 +323,22 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
struct pci_epc *epc = epf->epc;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
+ size_t size = reg->size;

- src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
- if (!src_addr) {
- dev_err(dev, "Failed to allocate source address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
- ret = -ENOMEM;
- goto err;
- }
-
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr,
- reg->src_addr, reg->size);
- if (ret) {
+ src_addr = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, reg->src_addr,
+ &src_phys_addr, size);
+ if (IS_ERR(src_addr)) {
dev_err(dev, "Failed to map source address\n");
reg->status = STATUS_SRC_ADDR_INVALID;
- goto err_src_addr;
- }
-
- dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size);
- if (!dst_addr) {
- dev_err(dev, "Failed to allocate destination address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
- ret = -ENOMEM;
- goto err_src_map_addr;
+ goto err;
}

- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr,
- reg->dst_addr, reg->size);
+ dst_addr = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, reg->dst_addr,
+ &dst_phys_addr, size);
if (ret) {
dev_err(dev, "Failed to map destination address\n");
reg->status = STATUS_DST_ADDR_INVALID;
- goto err_dst_addr;
+ goto err_src_map_addr;
}

ktime_get_ts64(&start);
@@ -393,16 +378,10 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma);

err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr);
-
-err_dst_addr:
- pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr, dst_addr, size);

err_src_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr);
-
-err_src_addr:
- pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr, src_addr, size);

err:
return ret;
@@ -410,7 +389,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)

static int pci_epf_test_read(struct pci_epf_test *epf_test)
{
- int ret;
+ int ret = 0;
void __iomem *src_addr;
void *buf;
u32 crc32;
@@ -424,21 +403,14 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
struct device *dma_dev = epf->epc->dev.parent;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
+ size_t size = reg->size;

- src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
- if (!src_addr) {
- dev_err(dev, "Failed to allocate address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
- ret = -ENOMEM;
- goto err;
- }
-
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
- reg->src_addr, reg->size);
- if (ret) {
+ src_addr = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no,
+ reg->src_addr, &phys_addr, size);
+ if (IS_ERR(src_addr)) {
dev_err(dev, "Failed to map address\n");
reg->status = STATUS_SRC_ADDR_INVALID;
- goto err_addr;
+ goto err;
}

buf = kzalloc(reg->size, GFP_KERNEL);
@@ -489,10 +461,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
kfree(buf);

err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
-
-err_addr:
- pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr, src_addr, size);

err:
return ret;
@@ -500,7 +469,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)

static int pci_epf_test_write(struct pci_epf_test *epf_test)
{
- int ret;
+ int ret = 0;
void __iomem *dst_addr;
void *buf;
bool use_dma;
@@ -513,21 +482,14 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
struct device *dma_dev = epf->epc->dev.parent;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
+ size_t size = reg->size;

- dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
- if (!dst_addr) {
- dev_err(dev, "Failed to allocate address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
- ret = -ENOMEM;
- goto err;
- }
-
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
- reg->dst_addr, reg->size);
- if (ret) {
+ dst_addr = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no,
+ reg->dst_addr, &phys_addr, size);
+ if (IS_ERR(dst_addr)) {
dev_err(dev, "Failed to map address\n");
reg->status = STATUS_DST_ADDR_INVALID;
- goto err_addr;
+ goto err;
}

buf = kzalloc(reg->size, GFP_KERNEL);
@@ -585,10 +547,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
kfree(buf);

err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
-
-err_addr:
- pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr, dst_addr, size);

err:
return ret;
--
2.25.1

2023-01-17 22:29:44

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [RFC PATCH 0/3] Deal with alignment restriction on EP side

On Fri, Jan 13, 2023 at 06:03:47PM +0900, Shunsuke Mie wrote:
> Some PCIe EPC controllers have restriction to map PCIe address space to the
> local memory space. The mapping is needed to access memory of other side.
> On epf test, RC module prepares an aligned memory, and EP module maps the
> region. However, a EP module which emulate a device (e.g. VirtIO, NVMe and
> etc) cannot expect that a driver for the device prepares an aligned memory.
> So, a EP side should deal with the alignment restriction.
>
> This patchset addresses with the alignment restriction on EP size. A
> content as follows:
> 1. Improve a pci epc unmap/map functions to cover the alignment restriction
> with adding epc driver support as EPC ops.
> 2. Implement the support function for DWC EPC driver.
> 3. Adapt the pci-epf-test to the map/unmap function updated at first patch.
>
> I tested this changes on RENESAS board has DWC PCIeC.
>
> This is a RFC, and it has patches for testing only. Following changes are
> not included yet:
> 1. Removing alignment codes on RC side completely
> 2. Adapting map/unmap() changes to pci-epf-ntb/vntb
>
> Best,
> Shunsuke
>
> Shunsuke Mie (3):
> PCI: endpoint: support an alignment aware map/unmaping
> PCI: dwc: support align_mem() callback for pci_epc_epc
> PCI: endpoint: support pci_epc_mem_map/unmap API changes

s/unmaping/unmapping/

Capitalize subject lines ("Support ...").

Would be nice to say something more specific than "support ... API
changes."

The last patch seems to be for a test case. Some previous changes to
it use the "PCI: pci-epf-test" prefix so it's distinct from the
pci-epc-core changes.

> .../pci/controller/dwc/pcie-designware-ep.c | 13 +++
> drivers/pci/endpoint/functions/pci-epf-test.c | 89 +++++--------------
> drivers/pci/endpoint/pci-epc-core.c | 57 +++++++++---
> include/linux/pci-epc.h | 10 ++-
> 4 files changed, 90 insertions(+), 79 deletions(-)
>
> --
> 2.25.1
>

2023-01-18 11:20:44

by Shunsuke Mie

[permalink] [raw]
Subject: Re: [RFC PATCH 0/3] Deal with alignment restriction on EP side


On 2023/01/18 5:32, Bjorn Helgaas wrote:
> On Fri, Jan 13, 2023 at 06:03:47PM +0900, Shunsuke Mie wrote:
>> Some PCIe EPC controllers have restriction to map PCIe address space to the
>> local memory space. The mapping is needed to access memory of other side.
>> On epf test, RC module prepares an aligned memory, and EP module maps the
>> region. However, a EP module which emulate a device (e.g. VirtIO, NVMe and
>> etc) cannot expect that a driver for the device prepares an aligned memory.
>> So, a EP side should deal with the alignment restriction.
>>
>> This patchset addresses with the alignment restriction on EP size. A
>> content as follows:
>> 1. Improve a pci epc unmap/map functions to cover the alignment restriction
>> with adding epc driver support as EPC ops.
>> 2. Implement the support function for DWC EPC driver.
>> 3. Adapt the pci-epf-test to the map/unmap function updated at first patch.
>>
>> I tested this changes on RENESAS board has DWC PCIeC.
>>
>> This is a RFC, and it has patches for testing only. Following changes are
>> not included yet:
>> 1. Removing alignment codes on RC side completely
>> 2. Adapting map/unmap() changes to pci-epf-ntb/vntb
>>
>> Best,
>> Shunsuke
>>
>> Shunsuke Mie (3):
>> PCI: endpoint: support an alignment aware map/unmaping
>> PCI: dwc: support align_mem() callback for pci_epc_epc
>> PCI: endpoint: support pci_epc_mem_map/unmap API changes
> s/unmaping/unmapping/
>
> Capitalize subject lines ("Support ...").
>
> Would be nice to say something more specific than "support ... API
> changes."
I'll reflect this remarks.
>
> The last patch seems to be for a test case. Some previous changes to
> it use the "PCI: pci-epf-test" prefix so it's distinct from the
> pci-epc-core changes.
I'll follow the previous changes.
>> .../pci/controller/dwc/pcie-designware-ep.c | 13 +++
>> drivers/pci/endpoint/functions/pci-epf-test.c | 89 +++++--------------
>> drivers/pci/endpoint/pci-epc-core.c | 57 +++++++++---
>> include/linux/pci-epc.h | 10 ++-
>> 4 files changed, 90 insertions(+), 79 deletions(-)
>>
>> --
>> 2.25.1
>>
Best,

Shunsuke