2018-01-26 18:50:27 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2021-07-03 15:13:02 +00:00
|
|
|
/*
|
2017-04-10 13:55:10 +00:00
|
|
|
* PCI Endpoint *Controller* (EPC) header file
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2017 Texas Instruments
|
|
|
|
|
* Author: Kishon Vijay Abraham I <kishon@ti.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef __LINUX_PCI_EPC_H
|
|
|
|
|
#define __LINUX_PCI_EPC_H
|
|
|
|
|
|
|
|
|
|
#include <linux/pci-epf.h>
|
|
|
|
|
|
|
|
|
|
struct pci_epc;
|
|
|
|
|
|
2021-02-01 19:57:58 +00:00
|
|
|
enum pci_epc_interface_type {
|
|
|
|
|
UNKNOWN_INTERFACE = -1,
|
|
|
|
|
PRIMARY_INTERFACE,
|
|
|
|
|
SECONDARY_INTERFACE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline const char *
|
|
|
|
|
pci_epc_interface_string(enum pci_epc_interface_type type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case PRIMARY_INTERFACE:
|
|
|
|
|
return "primary";
|
|
|
|
|
case SECONDARY_INTERFACE:
|
|
|
|
|
return "secondary";
|
|
|
|
|
default:
|
|
|
|
|
return "UNKNOWN interface";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
Some endpoint controllers have requirements on the alignment of the
controller physical memory address that must be used to map a RC PCI
address region. For instance, the endpoint controller of the RK3399 SoC
uses at most the lower 20 bits of a physical memory address region as
the lower bits of a RC PCI address region. For mapping a PCI address
region of size bytes starting from pci_addr, the exact number of
address bits used is the number of address bits changing in the address
range [pci_addr..pci_addr + size - 1]. For this example, this creates
the following constraints:
1) The offset into the controller physical memory allocated for a
mapping depends on the mapping size *and* the starting PCI address
for the mapping.
2) A mapping size cannot exceed the controller windows size (1MB) minus
the offset needed into the allocated physical memory, which can end
up being a smaller size than the desired mapping size.
Handling these constraints independently of the controller being used
in an endpoint function driver is not possible with the current EPC
API as only the ->align field in struct pci_epc_features is provided
but used for BAR (inbound ATU mappings) mapping only. A new API is
needed for function drivers to discover mapping constraints and handle
non-static requirements based on the RC PCI address range to access.
Introduce the endpoint controller operation ->align_addr() to allow
the EPC core functions to obtain the size and the offset into a
controller address region that must be allocated and mapped to access
a RC PCI address region. The size of the mapping provided by the
align_addr() operation can then be used as the size argument for the
function pci_epc_mem_alloc_addr() and the offset into the allocated
controller memory provided can be used to correctly handle data
transfers. For endpoint controllers that have PCI address alignment
constraints, the align_addr() operation may indicate upon return an
effective PCI address mapping size that is smaller (but not 0) than the
requested PCI address region size.
The controller ->align_addr() operation is optional: controllers that
do not have any alignment constraints for mapping RC PCI address regions
do not need to implement this operation. For such controllers, it is
always assumed that the mapping size is equal to the requested size of
the PCI region and that the mapping offset is 0.
The function pci_epc_mem_map() is introduced to use this new controller
operation (if it is defined) to handle controller memory allocation and
mapping to a RC PCI address region in endpoint function drivers.
This function first uses the ->align_addr() controller operation to
determine the controller memory address size (and offset into) needed
for mapping an RC PCI address region. The result of this operation is
used to allocate a controller physical memory region using
pci_epc_mem_alloc_addr() and then to map that memory to the RC PCI
address space with pci_epc_map_addr().
Since ->align_addr() () may indicate that not all of a RC PCI address
region can be mapped, pci_epc_mem_map() may only partially map the RC
PCI address region specified. It is the responsibility of the caller
(an endpoint function driver) to handle such smaller mapping by
repeatedly using pci_epc_mem_map() over the desried PCI address range.
The counterpart of pci_epc_mem_map() to unmap and free a mapped
controller memory address region is pci_epc_mem_unmap().
Both functions operate using the new struct pci_epc_map data structure.
This new structure represents a mapping PCI address, mapping effective
size, the size of the controller memory needed for the mapping as well
as the physical and virtual CPU addresses of the mapping (phys_base and
virt_base fields). For convenience, the physical and virtual CPU
addresses within that mapping to use to access the target RC PCI address
region are also provided (phys_addr and virt_addr fields).
Endpoint function drivers can use struct pci_epc_map to access the
mapped RC PCI address region using the ->virt_addr and ->pci_size
fields.
Co-developed-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-4-dlemoal@kernel.org
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2024-10-12 11:32:43 +00:00
|
|
|
/**
|
|
|
|
|
* struct pci_epc_map - information about EPC memory for mapping a RC PCI
|
|
|
|
|
* address range
|
|
|
|
|
* @pci_addr: start address of the RC PCI address range to map
|
|
|
|
|
* @pci_size: size of the RC PCI address range mapped from @pci_addr
|
|
|
|
|
* @map_pci_addr: RC PCI address used as the first address mapped (may be lower
|
|
|
|
|
* than @pci_addr)
|
|
|
|
|
* @map_size: size of the controller memory needed for mapping the RC PCI address
|
2024-11-14 16:10:32 +00:00
|
|
|
* range @map_pci_addr..@pci_addr+@pci_size
|
PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
Some endpoint controllers have requirements on the alignment of the
controller physical memory address that must be used to map a RC PCI
address region. For instance, the endpoint controller of the RK3399 SoC
uses at most the lower 20 bits of a physical memory address region as
the lower bits of a RC PCI address region. For mapping a PCI address
region of size bytes starting from pci_addr, the exact number of
address bits used is the number of address bits changing in the address
range [pci_addr..pci_addr + size - 1]. For this example, this creates
the following constraints:
1) The offset into the controller physical memory allocated for a
mapping depends on the mapping size *and* the starting PCI address
for the mapping.
2) A mapping size cannot exceed the controller windows size (1MB) minus
the offset needed into the allocated physical memory, which can end
up being a smaller size than the desired mapping size.
Handling these constraints independently of the controller being used
in an endpoint function driver is not possible with the current EPC
API as only the ->align field in struct pci_epc_features is provided
but used for BAR (inbound ATU mappings) mapping only. A new API is
needed for function drivers to discover mapping constraints and handle
non-static requirements based on the RC PCI address range to access.
Introduce the endpoint controller operation ->align_addr() to allow
the EPC core functions to obtain the size and the offset into a
controller address region that must be allocated and mapped to access
a RC PCI address region. The size of the mapping provided by the
align_addr() operation can then be used as the size argument for the
function pci_epc_mem_alloc_addr() and the offset into the allocated
controller memory provided can be used to correctly handle data
transfers. For endpoint controllers that have PCI address alignment
constraints, the align_addr() operation may indicate upon return an
effective PCI address mapping size that is smaller (but not 0) than the
requested PCI address region size.
The controller ->align_addr() operation is optional: controllers that
do not have any alignment constraints for mapping RC PCI address regions
do not need to implement this operation. For such controllers, it is
always assumed that the mapping size is equal to the requested size of
the PCI region and that the mapping offset is 0.
The function pci_epc_mem_map() is introduced to use this new controller
operation (if it is defined) to handle controller memory allocation and
mapping to a RC PCI address region in endpoint function drivers.
This function first uses the ->align_addr() controller operation to
determine the controller memory address size (and offset into) needed
for mapping an RC PCI address region. The result of this operation is
used to allocate a controller physical memory region using
pci_epc_mem_alloc_addr() and then to map that memory to the RC PCI
address space with pci_epc_map_addr().
Since ->align_addr() () may indicate that not all of a RC PCI address
region can be mapped, pci_epc_mem_map() may only partially map the RC
PCI address region specified. It is the responsibility of the caller
(an endpoint function driver) to handle such smaller mapping by
repeatedly using pci_epc_mem_map() over the desried PCI address range.
The counterpart of pci_epc_mem_map() to unmap and free a mapped
controller memory address region is pci_epc_mem_unmap().
Both functions operate using the new struct pci_epc_map data structure.
This new structure represents a mapping PCI address, mapping effective
size, the size of the controller memory needed for the mapping as well
as the physical and virtual CPU addresses of the mapping (phys_base and
virt_base fields). For convenience, the physical and virtual CPU
addresses within that mapping to use to access the target RC PCI address
region are also provided (phys_addr and virt_addr fields).
Endpoint function drivers can use struct pci_epc_map to access the
mapped RC PCI address region using the ->virt_addr and ->pci_size
fields.
Co-developed-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-4-dlemoal@kernel.org
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2024-10-12 11:32:43 +00:00
|
|
|
* @phys_base: base physical address of the allocated EPC memory for mapping the
|
|
|
|
|
* RC PCI address range
|
|
|
|
|
* @phys_addr: physical address at which @pci_addr is mapped
|
|
|
|
|
* @virt_base: base virtual address of the allocated EPC memory for mapping the
|
|
|
|
|
* RC PCI address range
|
|
|
|
|
* @virt_addr: virtual address at which @pci_addr is mapped
|
|
|
|
|
*/
|
|
|
|
|
struct pci_epc_map {
|
|
|
|
|
u64 pci_addr;
|
|
|
|
|
size_t pci_size;
|
|
|
|
|
|
|
|
|
|
u64 map_pci_addr;
|
|
|
|
|
size_t map_size;
|
|
|
|
|
|
|
|
|
|
phys_addr_t phys_base;
|
|
|
|
|
phys_addr_t phys_addr;
|
|
|
|
|
void __iomem *virt_base;
|
|
|
|
|
void __iomem *virt_addr;
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-10 13:55:10 +00:00
|
|
|
/**
|
|
|
|
|
* struct pci_epc_ops - set of function pointers for performing EPC operations
|
|
|
|
|
* @write_header: ops to populate configuration space header
|
|
|
|
|
* @set_bar: ops to configure the BAR
|
|
|
|
|
* @clear_bar: ops to reset the BAR
|
PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
Some endpoint controllers have requirements on the alignment of the
controller physical memory address that must be used to map a RC PCI
address region. For instance, the endpoint controller of the RK3399 SoC
uses at most the lower 20 bits of a physical memory address region as
the lower bits of a RC PCI address region. For mapping a PCI address
region of size bytes starting from pci_addr, the exact number of
address bits used is the number of address bits changing in the address
range [pci_addr..pci_addr + size - 1]. For this example, this creates
the following constraints:
1) The offset into the controller physical memory allocated for a
mapping depends on the mapping size *and* the starting PCI address
for the mapping.
2) A mapping size cannot exceed the controller windows size (1MB) minus
the offset needed into the allocated physical memory, which can end
up being a smaller size than the desired mapping size.
Handling these constraints independently of the controller being used
in an endpoint function driver is not possible with the current EPC
API as only the ->align field in struct pci_epc_features is provided
but used for BAR (inbound ATU mappings) mapping only. A new API is
needed for function drivers to discover mapping constraints and handle
non-static requirements based on the RC PCI address range to access.
Introduce the endpoint controller operation ->align_addr() to allow
the EPC core functions to obtain the size and the offset into a
controller address region that must be allocated and mapped to access
a RC PCI address region. The size of the mapping provided by the
align_addr() operation can then be used as the size argument for the
function pci_epc_mem_alloc_addr() and the offset into the allocated
controller memory provided can be used to correctly handle data
transfers. For endpoint controllers that have PCI address alignment
constraints, the align_addr() operation may indicate upon return an
effective PCI address mapping size that is smaller (but not 0) than the
requested PCI address region size.
The controller ->align_addr() operation is optional: controllers that
do not have any alignment constraints for mapping RC PCI address regions
do not need to implement this operation. For such controllers, it is
always assumed that the mapping size is equal to the requested size of
the PCI region and that the mapping offset is 0.
The function pci_epc_mem_map() is introduced to use this new controller
operation (if it is defined) to handle controller memory allocation and
mapping to a RC PCI address region in endpoint function drivers.
This function first uses the ->align_addr() controller operation to
determine the controller memory address size (and offset into) needed
for mapping an RC PCI address region. The result of this operation is
used to allocate a controller physical memory region using
pci_epc_mem_alloc_addr() and then to map that memory to the RC PCI
address space with pci_epc_map_addr().
Since ->align_addr() () may indicate that not all of a RC PCI address
region can be mapped, pci_epc_mem_map() may only partially map the RC
PCI address region specified. It is the responsibility of the caller
(an endpoint function driver) to handle such smaller mapping by
repeatedly using pci_epc_mem_map() over the desried PCI address range.
The counterpart of pci_epc_mem_map() to unmap and free a mapped
controller memory address region is pci_epc_mem_unmap().
Both functions operate using the new struct pci_epc_map data structure.
This new structure represents a mapping PCI address, mapping effective
size, the size of the controller memory needed for the mapping as well
as the physical and virtual CPU addresses of the mapping (phys_base and
virt_base fields). For convenience, the physical and virtual CPU
addresses within that mapping to use to access the target RC PCI address
region are also provided (phys_addr and virt_addr fields).
Endpoint function drivers can use struct pci_epc_map to access the
mapped RC PCI address region using the ->virt_addr and ->pci_size
fields.
Co-developed-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-4-dlemoal@kernel.org
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2024-10-12 11:32:43 +00:00
|
|
|
* @align_addr: operation to get the mapping address, mapping size and offset
|
|
|
|
|
* into a controller memory window needed to map an RC PCI address
|
|
|
|
|
* region
|
2017-04-10 13:55:10 +00:00
|
|
|
* @map_addr: ops to map CPU address to PCI address
|
|
|
|
|
* @unmap_addr: ops to unmap CPU address and PCI address
|
|
|
|
|
* @set_msi: ops to set the requested number of MSI interrupts in the MSI
|
|
|
|
|
* capability register
|
|
|
|
|
* @get_msi: ops to get the number of MSI interrupts allocated by the RC from
|
|
|
|
|
* the MSI capability register
|
2018-07-19 08:32:12 +00:00
|
|
|
* @set_msix: ops to set the requested number of MSI-X interrupts in the
|
|
|
|
|
* MSI-X capability register
|
|
|
|
|
* @get_msix: ops to get the number of MSI-X interrupts allocated by the RC
|
|
|
|
|
* from the MSI-X capability register
|
2018-07-19 08:32:13 +00:00
|
|
|
* @raise_irq: ops to raise a legacy, MSI or MSI-X interrupt
|
2021-02-01 19:58:00 +00:00
|
|
|
* @map_msi_irq: ops to map physical address to MSI address and return MSI data
|
2017-04-10 13:55:10 +00:00
|
|
|
* @start: ops to start the PCI link
|
|
|
|
|
* @stop: ops to stop the PCI link
|
2021-07-03 15:13:02 +00:00
|
|
|
* @get_features: ops to get the features supported by the EPC
|
2017-04-10 13:55:10 +00:00
|
|
|
* @owner: the module owner containing the ops
|
|
|
|
|
*/
|
|
|
|
|
struct pci_epc_ops {
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*write_header)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2017-04-10 13:55:10 +00:00
|
|
|
struct pci_epf_header *hdr);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*set_bar)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-03-28 11:50:07 +00:00
|
|
|
struct pci_epf_bar *epf_bar);
|
2021-08-19 12:33:39 +00:00
|
|
|
void (*clear_bar)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-03-28 11:50:14 +00:00
|
|
|
struct pci_epf_bar *epf_bar);
|
PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
Some endpoint controllers have requirements on the alignment of the
controller physical memory address that must be used to map a RC PCI
address region. For instance, the endpoint controller of the RK3399 SoC
uses at most the lower 20 bits of a physical memory address region as
the lower bits of a RC PCI address region. For mapping a PCI address
region of size bytes starting from pci_addr, the exact number of
address bits used is the number of address bits changing in the address
range [pci_addr..pci_addr + size - 1]. For this example, this creates
the following constraints:
1) The offset into the controller physical memory allocated for a
mapping depends on the mapping size *and* the starting PCI address
for the mapping.
2) A mapping size cannot exceed the controller windows size (1MB) minus
the offset needed into the allocated physical memory, which can end
up being a smaller size than the desired mapping size.
Handling these constraints independently of the controller being used
in an endpoint function driver is not possible with the current EPC
API as only the ->align field in struct pci_epc_features is provided
but used for BAR (inbound ATU mappings) mapping only. A new API is
needed for function drivers to discover mapping constraints and handle
non-static requirements based on the RC PCI address range to access.
Introduce the endpoint controller operation ->align_addr() to allow
the EPC core functions to obtain the size and the offset into a
controller address region that must be allocated and mapped to access
a RC PCI address region. The size of the mapping provided by the
align_addr() operation can then be used as the size argument for the
function pci_epc_mem_alloc_addr() and the offset into the allocated
controller memory provided can be used to correctly handle data
transfers. For endpoint controllers that have PCI address alignment
constraints, the align_addr() operation may indicate upon return an
effective PCI address mapping size that is smaller (but not 0) than the
requested PCI address region size.
The controller ->align_addr() operation is optional: controllers that
do not have any alignment constraints for mapping RC PCI address regions
do not need to implement this operation. For such controllers, it is
always assumed that the mapping size is equal to the requested size of
the PCI region and that the mapping offset is 0.
The function pci_epc_mem_map() is introduced to use this new controller
operation (if it is defined) to handle controller memory allocation and
mapping to a RC PCI address region in endpoint function drivers.
This function first uses the ->align_addr() controller operation to
determine the controller memory address size (and offset into) needed
for mapping an RC PCI address region. The result of this operation is
used to allocate a controller physical memory region using
pci_epc_mem_alloc_addr() and then to map that memory to the RC PCI
address space with pci_epc_map_addr().
Since ->align_addr() () may indicate that not all of a RC PCI address
region can be mapped, pci_epc_mem_map() may only partially map the RC
PCI address region specified. It is the responsibility of the caller
(an endpoint function driver) to handle such smaller mapping by
repeatedly using pci_epc_mem_map() over the desried PCI address range.
The counterpart of pci_epc_mem_map() to unmap and free a mapped
controller memory address region is pci_epc_mem_unmap().
Both functions operate using the new struct pci_epc_map data structure.
This new structure represents a mapping PCI address, mapping effective
size, the size of the controller memory needed for the mapping as well
as the physical and virtual CPU addresses of the mapping (phys_base and
virt_base fields). For convenience, the physical and virtual CPU
addresses within that mapping to use to access the target RC PCI address
region are also provided (phys_addr and virt_addr fields).
Endpoint function drivers can use struct pci_epc_map to access the
mapped RC PCI address region using the ->virt_addr and ->pci_size
fields.
Co-developed-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-4-dlemoal@kernel.org
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2024-10-12 11:32:43 +00:00
|
|
|
u64 (*align_addr)(struct pci_epc *epc, u64 pci_addr, size_t *size,
|
|
|
|
|
size_t *offset);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*map_addr)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-01-30 20:56:56 +00:00
|
|
|
phys_addr_t addr, u64 pci_addr, size_t size);
|
2021-08-19 12:33:39 +00:00
|
|
|
void (*unmap_addr)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-01-30 20:56:56 +00:00
|
|
|
phys_addr_t addr);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2025-05-14 07:43:18 +00:00
|
|
|
u8 nr_irqs);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*get_msi)(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
|
|
|
|
|
int (*set_msix)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2025-05-14 07:43:19 +00:00
|
|
|
u16 nr_irqs, enum pci_barno, u32 offset);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*get_msix)(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
|
|
|
|
|
int (*raise_irq)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2023-11-22 06:03:52 +00:00
|
|
|
unsigned int type, u16 interrupt_num);
|
2021-08-19 12:33:39 +00:00
|
|
|
int (*map_msi_irq)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2021-02-01 19:58:00 +00:00
|
|
|
phys_addr_t phys_addr, u8 interrupt_num,
|
|
|
|
|
u32 entry_size, u32 *msi_data,
|
|
|
|
|
u32 *msi_addr_offset);
|
2017-04-10 13:55:10 +00:00
|
|
|
int (*start)(struct pci_epc *epc);
|
|
|
|
|
void (*stop)(struct pci_epc *epc);
|
2019-01-14 11:14:59 +00:00
|
|
|
const struct pci_epc_features* (*get_features)(struct pci_epc *epc,
|
2021-08-19 12:33:39 +00:00
|
|
|
u8 func_no, u8 vfunc_no);
|
2017-04-10 13:55:10 +00:00
|
|
|
struct module *owner;
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-07 12:33:16 +00:00
|
|
|
/**
|
|
|
|
|
* struct pci_epc_mem_window - address window of the endpoint controller
|
|
|
|
|
* @phys_base: physical base address of the PCI address window
|
|
|
|
|
* @size: the size of the PCI address window
|
|
|
|
|
* @page_size: size of each page
|
|
|
|
|
*/
|
|
|
|
|
struct pci_epc_mem_window {
|
|
|
|
|
phys_addr_t phys_base;
|
|
|
|
|
size_t size;
|
|
|
|
|
size_t page_size;
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-10 13:55:10 +00:00
|
|
|
/**
|
|
|
|
|
* struct pci_epc_mem - address space of the endpoint controller
|
2020-05-07 12:33:16 +00:00
|
|
|
* @window: address window of the endpoint controller
|
2017-04-10 13:55:10 +00:00
|
|
|
* @bitmap: bitmap to manage the PCI address space
|
|
|
|
|
* @pages: number of bits representing the address region
|
2020-02-24 09:53:36 +00:00
|
|
|
* @lock: mutex to protect bitmap
|
2017-04-10 13:55:10 +00:00
|
|
|
*/
|
|
|
|
|
struct pci_epc_mem {
|
2020-05-07 12:33:16 +00:00
|
|
|
struct pci_epc_mem_window window;
|
2017-04-10 13:55:10 +00:00
|
|
|
unsigned long *bitmap;
|
|
|
|
|
int pages;
|
2020-02-24 09:53:36 +00:00
|
|
|
/* mutex to protect against concurrent access for memory allocation*/
|
|
|
|
|
struct mutex lock;
|
2017-04-10 13:55:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* struct pci_epc - represents the PCI EPC device
|
|
|
|
|
* @dev: PCI EPC device
|
|
|
|
|
* @pci_epf: list of endpoint functions present in this EPC device
|
2023-12-06 18:17:51 +00:00
|
|
|
* @list_lock: Mutex for protecting pci_epf list
|
2017-04-10 13:55:10 +00:00
|
|
|
* @ops: function pointers for performing endpoint operations
|
2020-05-07 12:33:16 +00:00
|
|
|
* @windows: array of address space of the endpoint controller
|
|
|
|
|
* @mem: first window of the endpoint controller, which corresponds to
|
|
|
|
|
* default address space of the endpoint controller supporting
|
|
|
|
|
* single window.
|
|
|
|
|
* @num_windows: number of windows supported by device
|
2017-04-10 13:55:10 +00:00
|
|
|
* @max_functions: max number of functions that can be configured in this EPC
|
2021-08-19 12:33:39 +00:00
|
|
|
* @max_vfs: Array indicating the maximum number of virtual functions that can
|
|
|
|
|
* be associated with each physical function
|
2017-03-27 09:45:01 +00:00
|
|
|
* @group: configfs group representing the PCI EPC device
|
2020-02-24 09:53:35 +00:00
|
|
|
* @lock: mutex to protect pci_epc ops
|
2020-02-24 09:53:38 +00:00
|
|
|
* @function_num_map: bitmap to manage physical function number
|
2024-08-28 15:46:15 +00:00
|
|
|
* @domain_nr: PCI domain number of the endpoint controller
|
2024-03-27 09:13:37 +00:00
|
|
|
* @init_complete: flag to indicate whether the EPC initialization is complete
|
|
|
|
|
* or not
|
2017-04-10 13:55:10 +00:00
|
|
|
*/
|
|
|
|
|
struct pci_epc {
|
|
|
|
|
struct device dev;
|
|
|
|
|
struct list_head pci_epf;
|
2023-01-24 07:11:56 +00:00
|
|
|
struct mutex list_lock;
|
2017-04-10 13:55:10 +00:00
|
|
|
const struct pci_epc_ops *ops;
|
2020-05-07 12:33:16 +00:00
|
|
|
struct pci_epc_mem **windows;
|
2017-04-10 13:55:10 +00:00
|
|
|
struct pci_epc_mem *mem;
|
2020-05-07 12:33:16 +00:00
|
|
|
unsigned int num_windows;
|
2017-04-10 13:55:10 +00:00
|
|
|
u8 max_functions;
|
2021-08-19 12:33:39 +00:00
|
|
|
u8 *max_vfs;
|
2017-03-27 09:45:01 +00:00
|
|
|
struct config_group *group;
|
2020-02-24 09:53:35 +00:00
|
|
|
/* mutex to protect against concurrent access of EP controller */
|
|
|
|
|
struct mutex lock;
|
2020-02-24 09:53:38 +00:00
|
|
|
unsigned long function_num_map;
|
2024-08-28 15:46:15 +00:00
|
|
|
int domain_nr;
|
2024-03-27 09:13:37 +00:00
|
|
|
bool init_complete;
|
2017-04-10 13:55:10 +00:00
|
|
|
};
|
|
|
|
|
|
2024-02-16 13:45:14 +00:00
|
|
|
/**
|
2024-09-03 20:38:25 +00:00
|
|
|
* enum pci_epc_bar_type - configurability of endpoint BAR
|
2024-02-16 13:45:14 +00:00
|
|
|
* @BAR_PROGRAMMABLE: The BAR mask can be configured by the EPC.
|
|
|
|
|
* @BAR_FIXED: The BAR mask is fixed by the hardware.
|
2025-01-31 18:29:50 +00:00
|
|
|
* @BAR_RESIZABLE: The BAR implements the PCI-SIG Resizable BAR Capability.
|
|
|
|
|
* NOTE: An EPC driver can currently only set a single supported
|
|
|
|
|
* size.
|
2024-02-16 13:45:14 +00:00
|
|
|
* @BAR_RESERVED: The BAR should not be touched by an EPF driver.
|
|
|
|
|
*/
|
|
|
|
|
enum pci_epc_bar_type {
|
|
|
|
|
BAR_PROGRAMMABLE = 0,
|
|
|
|
|
BAR_FIXED,
|
2025-01-31 18:29:50 +00:00
|
|
|
BAR_RESIZABLE,
|
2024-02-16 13:45:14 +00:00
|
|
|
BAR_RESERVED,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* struct pci_epc_bar_desc - hardware description for a BAR
|
|
|
|
|
* @type: the type of the BAR
|
|
|
|
|
* @fixed_size: the fixed size, only applicable if type is BAR_FIXED_MASK.
|
|
|
|
|
* @only_64bit: if true, an EPF driver is not allowed to choose if this BAR
|
|
|
|
|
* should be configured as 32-bit or 64-bit, the EPF driver must
|
|
|
|
|
* configure this BAR as 64-bit. Additionally, the BAR succeeding
|
|
|
|
|
* this BAR must be set to type BAR_RESERVED.
|
2024-02-16 13:45:15 +00:00
|
|
|
*
|
|
|
|
|
* only_64bit should not be set on a BAR of type BAR_RESERVED.
|
|
|
|
|
* (If BARx is a 64-bit BAR that an EPF driver is not allowed to
|
|
|
|
|
* touch, then both BARx and BARx+1 must be set to type
|
|
|
|
|
* BAR_RESERVED.)
|
2024-02-16 13:45:14 +00:00
|
|
|
*/
|
|
|
|
|
struct pci_epc_bar_desc {
|
|
|
|
|
enum pci_epc_bar_type type;
|
|
|
|
|
u64 fixed_size;
|
|
|
|
|
bool only_64bit;
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-14 11:14:59 +00:00
|
|
|
/**
|
|
|
|
|
* struct pci_epc_features - features supported by a EPC device per function
|
|
|
|
|
* @linkup_notifier: indicate if the EPC device can notify EPF driver on link up
|
|
|
|
|
* @msi_capable: indicate if the endpoint function has MSI capability
|
|
|
|
|
* @msix_capable: indicate if the endpoint function has MSI-X capability
|
2025-03-10 11:10:21 +00:00
|
|
|
* @intx_capable: indicate if the endpoint can raise INTx interrupts
|
2024-02-16 13:45:14 +00:00
|
|
|
* @bar: array specifying the hardware description for each BAR
|
2019-03-25 09:39:39 +00:00
|
|
|
* @align: alignment size required for BAR buffer allocation
|
2019-01-14 11:14:59 +00:00
|
|
|
*/
|
|
|
|
|
struct pci_epc_features {
|
|
|
|
|
unsigned int linkup_notifier : 1;
|
|
|
|
|
unsigned int msi_capable : 1;
|
|
|
|
|
unsigned int msix_capable : 1;
|
2025-03-10 11:10:21 +00:00
|
|
|
unsigned int intx_capable : 1;
|
2024-02-16 13:45:14 +00:00
|
|
|
struct pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
|
2019-03-25 09:39:39 +00:00
|
|
|
size_t align;
|
2019-01-14 11:14:59 +00:00
|
|
|
};
|
|
|
|
|
|
2017-04-10 13:55:10 +00:00
|
|
|
#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
|
|
|
|
|
|
2024-06-06 07:26:35 +00:00
|
|
|
#ifdef CONFIG_PCI_ENDPOINT
|
|
|
|
|
|
2017-04-10 13:55:10 +00:00
|
|
|
#define pci_epc_create(dev, ops) \
|
|
|
|
|
__pci_epc_create((dev), (ops), THIS_MODULE)
|
|
|
|
|
#define devm_pci_epc_create(dev, ops) \
|
|
|
|
|
__devm_pci_epc_create((dev), (ops), THIS_MODULE)
|
|
|
|
|
|
|
|
|
|
static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
|
|
|
|
|
{
|
|
|
|
|
dev_set_drvdata(&epc->dev, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void *epc_get_drvdata(struct pci_epc *epc)
|
|
|
|
|
{
|
|
|
|
|
return dev_get_drvdata(&epc->dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct pci_epc *
|
|
|
|
|
__devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
|
|
|
|
|
struct module *owner);
|
|
|
|
|
struct pci_epc *
|
|
|
|
|
__pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
|
|
|
|
|
struct module *owner);
|
|
|
|
|
void pci_epc_destroy(struct pci_epc *epc);
|
2021-02-01 19:57:58 +00:00
|
|
|
int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
|
|
|
|
|
enum pci_epc_interface_type type);
|
2017-04-10 13:55:10 +00:00
|
|
|
void pci_epc_linkup(struct pci_epc *epc);
|
2023-06-02 11:47:51 +00:00
|
|
|
void pci_epc_linkdown(struct pci_epc *epc);
|
2020-02-17 12:10:34 +00:00
|
|
|
void pci_epc_init_notify(struct pci_epc *epc);
|
2024-03-27 09:13:37 +00:00
|
|
|
void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf);
|
2024-06-06 07:26:35 +00:00
|
|
|
void pci_epc_deinit_notify(struct pci_epc *epc);
|
2024-04-30 06:13:44 +00:00
|
|
|
void pci_epc_bus_master_enable_notify(struct pci_epc *epc);
|
2021-02-01 19:57:58 +00:00
|
|
|
void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
|
|
|
|
|
enum pci_epc_interface_type type);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-01-30 20:56:56 +00:00
|
|
|
struct pci_epf_header *hdr);
|
2025-01-31 18:29:51 +00:00
|
|
|
int pci_epc_bar_size_to_rebar_cap(size_t size, u32 *cap);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-03-28 11:50:07 +00:00
|
|
|
struct pci_epf_bar *epf_bar);
|
2021-08-19 12:33:39 +00:00
|
|
|
void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-03-28 11:50:14 +00:00
|
|
|
struct pci_epf_bar *epf_bar);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-01-30 20:56:56 +00:00
|
|
|
phys_addr_t phys_addr,
|
2017-04-10 13:55:10 +00:00
|
|
|
u64 pci_addr, size_t size);
|
2021-08-19 12:33:39 +00:00
|
|
|
void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2018-01-30 20:56:56 +00:00
|
|
|
phys_addr_t phys_addr);
|
2025-05-14 07:43:18 +00:00
|
|
|
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 nr_irqs);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
|
2025-05-14 07:43:19 +00:00
|
|
|
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u16 nr_irqs,
|
|
|
|
|
enum pci_barno, u32 offset);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
|
|
|
|
|
int pci_epc_map_msi_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2021-02-01 19:58:00 +00:00
|
|
|
phys_addr_t phys_addr, u8 interrupt_num,
|
|
|
|
|
u32 entry_size, u32 *msi_data, u32 *msi_addr_offset);
|
2021-08-19 12:33:39 +00:00
|
|
|
int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
2023-11-22 06:03:52 +00:00
|
|
|
unsigned int type, u16 interrupt_num);
|
2017-04-10 13:55:10 +00:00
|
|
|
int pci_epc_start(struct pci_epc *epc);
|
|
|
|
|
void pci_epc_stop(struct pci_epc *epc);
|
2019-01-14 11:14:59 +00:00
|
|
|
const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
|
2021-08-19 12:33:39 +00:00
|
|
|
u8 func_no, u8 vfunc_no);
|
2021-02-01 19:57:56 +00:00
|
|
|
enum pci_barno
|
|
|
|
|
pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features);
|
|
|
|
|
enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
|
|
|
|
|
*epc_features, enum pci_barno bar);
|
2017-04-10 13:55:10 +00:00
|
|
|
struct pci_epc *pci_epc_get(const char *epc_name);
|
|
|
|
|
void pci_epc_put(struct pci_epc *epc);
|
|
|
|
|
|
2020-05-07 12:33:15 +00:00
|
|
|
int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t base,
|
|
|
|
|
size_t size, size_t page_size);
|
2020-05-07 12:33:16 +00:00
|
|
|
int pci_epc_multi_mem_init(struct pci_epc *epc,
|
|
|
|
|
struct pci_epc_mem_window *window,
|
|
|
|
|
unsigned int num_windows);
|
2017-04-10 13:55:10 +00:00
|
|
|
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);
|
|
|
|
|
void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
|
|
|
|
|
void __iomem *virt_addr, size_t size);
|
PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
Some endpoint controllers have requirements on the alignment of the
controller physical memory address that must be used to map a RC PCI
address region. For instance, the endpoint controller of the RK3399 SoC
uses at most the lower 20 bits of a physical memory address region as
the lower bits of a RC PCI address region. For mapping a PCI address
region of size bytes starting from pci_addr, the exact number of
address bits used is the number of address bits changing in the address
range [pci_addr..pci_addr + size - 1]. For this example, this creates
the following constraints:
1) The offset into the controller physical memory allocated for a
mapping depends on the mapping size *and* the starting PCI address
for the mapping.
2) A mapping size cannot exceed the controller windows size (1MB) minus
the offset needed into the allocated physical memory, which can end
up being a smaller size than the desired mapping size.
Handling these constraints independently of the controller being used
in an endpoint function driver is not possible with the current EPC
API as only the ->align field in struct pci_epc_features is provided
but used for BAR (inbound ATU mappings) mapping only. A new API is
needed for function drivers to discover mapping constraints and handle
non-static requirements based on the RC PCI address range to access.
Introduce the endpoint controller operation ->align_addr() to allow
the EPC core functions to obtain the size and the offset into a
controller address region that must be allocated and mapped to access
a RC PCI address region. The size of the mapping provided by the
align_addr() operation can then be used as the size argument for the
function pci_epc_mem_alloc_addr() and the offset into the allocated
controller memory provided can be used to correctly handle data
transfers. For endpoint controllers that have PCI address alignment
constraints, the align_addr() operation may indicate upon return an
effective PCI address mapping size that is smaller (but not 0) than the
requested PCI address region size.
The controller ->align_addr() operation is optional: controllers that
do not have any alignment constraints for mapping RC PCI address regions
do not need to implement this operation. For such controllers, it is
always assumed that the mapping size is equal to the requested size of
the PCI region and that the mapping offset is 0.
The function pci_epc_mem_map() is introduced to use this new controller
operation (if it is defined) to handle controller memory allocation and
mapping to a RC PCI address region in endpoint function drivers.
This function first uses the ->align_addr() controller operation to
determine the controller memory address size (and offset into) needed
for mapping an RC PCI address region. The result of this operation is
used to allocate a controller physical memory region using
pci_epc_mem_alloc_addr() and then to map that memory to the RC PCI
address space with pci_epc_map_addr().
Since ->align_addr() () may indicate that not all of a RC PCI address
region can be mapped, pci_epc_mem_map() may only partially map the RC
PCI address region specified. It is the responsibility of the caller
(an endpoint function driver) to handle such smaller mapping by
repeatedly using pci_epc_mem_map() over the desried PCI address range.
The counterpart of pci_epc_mem_map() to unmap and free a mapped
controller memory address region is pci_epc_mem_unmap().
Both functions operate using the new struct pci_epc_map data structure.
This new structure represents a mapping PCI address, mapping effective
size, the size of the controller memory needed for the mapping as well
as the physical and virtual CPU addresses of the mapping (phys_base and
virt_base fields). For convenience, the physical and virtual CPU
addresses within that mapping to use to access the target RC PCI address
region are also provided (phys_addr and virt_addr fields).
Endpoint function drivers can use struct pci_epc_map to access the
mapped RC PCI address region using the ->virt_addr and ->pci_size
fields.
Co-developed-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-4-dlemoal@kernel.org
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2024-10-12 11:32:43 +00:00
|
|
|
int pci_epc_mem_map(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
|
|
|
|
u64 pci_addr, size_t pci_size, struct pci_epc_map *map);
|
|
|
|
|
void pci_epc_mem_unmap(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
|
|
|
|
struct pci_epc_map *map);
|
2024-06-06 07:26:35 +00:00
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
static inline void pci_epc_init_notify(struct pci_epc *epc)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void pci_epc_deinit_notify(struct pci_epc *epc)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif /* CONFIG_PCI_ENDPOINT */
|
2017-04-10 13:55:10 +00:00
|
|
|
#endif /* __LINUX_PCI_EPC_H */
|