summaryrefslogtreecommitdiff
path: root/include/linux/pci-epc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/pci-epc.h')
-rw-r--r--include/linux/pci-epc.h78
1 files changed, 63 insertions, 15 deletions
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index e818e3fdcded..1eca1264815b 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -100,10 +100,10 @@ struct pci_epc_ops {
void (*unmap_addr)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
phys_addr_t addr);
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
- u8 interrupts);
+ u8 nr_irqs);
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,
- u16 interrupts, enum pci_barno, u32 offset);
+ u16 nr_irqs, enum pci_barno, u32 offset);
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,
unsigned int type, u16 interrupt_num);
@@ -188,12 +188,52 @@ struct pci_epc {
* enum pci_epc_bar_type - configurability of endpoint BAR
* @BAR_PROGRAMMABLE: The BAR mask can be configured by the EPC.
* @BAR_FIXED: The BAR mask is fixed by the hardware.
- * @BAR_RESERVED: The BAR should not be touched by an EPF driver.
+ * @BAR_RESIZABLE: The BAR implements the PCI-SIG Resizable BAR Capability.
+ * NOTE: An EPC driver can currently only set a single supported
+ * size.
+ * @BAR_RESERVED: Used for HW-backed BARs (e.g. MSI-X table, DMA regs). The BAR
+ * should not be disabled by an EPC driver. The BAR should not be
+ * reprogrammed by an EPF driver. An EPF driver is allowed to
+ * disable the BAR if absolutely necessary. (However, right now
+ * there is no EPC operation to disable a BAR that has not been
+ * programmed using pci_epc_set_bar().)
+ * @BAR_DISABLED: The BAR should be disabled by an EPC driver. The BAR will be
+ * unavailable to an EPF driver.
*/
enum pci_epc_bar_type {
BAR_PROGRAMMABLE = 0,
BAR_FIXED,
+ BAR_RESIZABLE,
BAR_RESERVED,
+ BAR_DISABLED,
+};
+
+/**
+ * enum pci_epc_bar_rsvd_region_type - type of a fixed subregion behind a BAR
+ * @PCI_EPC_BAR_RSVD_DMA_CTRL_MMIO: Integrated DMA controller MMIO window
+ * @PCI_EPC_BAR_RSVD_MSIX_TBL_RAM: MSI-X table structure
+ * @PCI_EPC_BAR_RSVD_MSIX_PBA_RAM: MSI-X PBA structure
+ *
+ * BARs marked BAR_RESERVED are owned by the SoC/EPC hardware and must not be
+ * reprogrammed by EPF drivers. Some of them still expose fixed subregions that
+ * EPFs may want to reference (e.g. embedded doorbell fallback).
+ */
+enum pci_epc_bar_rsvd_region_type {
+ PCI_EPC_BAR_RSVD_DMA_CTRL_MMIO = 0,
+ PCI_EPC_BAR_RSVD_MSIX_TBL_RAM,
+ PCI_EPC_BAR_RSVD_MSIX_PBA_RAM,
+};
+
+/**
+ * struct pci_epc_bar_rsvd_region - fixed subregion behind a BAR
+ * @type: reserved region type
+ * @offset: offset within the BAR aperture
+ * @size: size of the reserved region
+ */
+struct pci_epc_bar_rsvd_region {
+ enum pci_epc_bar_rsvd_region_type type;
+ resource_size_t offset;
+ resource_size_t size;
};
/**
@@ -202,32 +242,41 @@ enum pci_epc_bar_type {
* @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.
- *
- * 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.)
+ * configure this BAR as 64-bit.
+ * @nr_rsvd_regions: number of fixed subregions described for BAR_RESERVED
+ * @rsvd_regions: fixed subregions behind BAR_RESERVED
*/
struct pci_epc_bar_desc {
enum pci_epc_bar_type type;
u64 fixed_size;
bool only_64bit;
+ u8 nr_rsvd_regions;
+ const struct pci_epc_bar_rsvd_region *rsvd_regions;
};
/**
* 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
+ * @dynamic_inbound_mapping: indicate if the EPC device supports updating
+ * inbound mappings for an already configured BAR
+ * (i.e. allow calling pci_epc_set_bar() again
+ * without first calling pci_epc_clear_bar())
+ * @subrange_mapping: indicate if the EPC device can map inbound subranges for a
+ * BAR. This feature depends on @dynamic_inbound_mapping
+ * feature.
* @msi_capable: indicate if the endpoint function has MSI capability
* @msix_capable: indicate if the endpoint function has MSI-X capability
+ * @intx_capable: indicate if the endpoint can raise INTx interrupts
* @bar: array specifying the hardware description for each BAR
* @align: alignment size required for BAR buffer allocation
*/
struct pci_epc_features {
unsigned int linkup_notifier : 1;
+ unsigned int dynamic_inbound_mapping : 1;
+ unsigned int subrange_mapping : 1;
unsigned int msi_capable : 1;
unsigned int msix_capable : 1;
+ unsigned int intx_capable : 1;
struct pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
size_t align;
};
@@ -257,7 +306,6 @@ __devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
struct pci_epc *
__pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
struct module *owner);
-void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc);
void pci_epc_destroy(struct pci_epc *epc);
int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
enum pci_epc_interface_type type);
@@ -271,6 +319,7 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
enum pci_epc_interface_type type);
int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
struct pci_epf_header *hdr);
+int pci_epc_bar_size_to_rebar_cap(size_t size, u32 *cap);
int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
struct pci_epf_bar *epf_bar);
void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
@@ -280,11 +329,10 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
u64 pci_addr, size_t size);
void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
phys_addr_t phys_addr);
-int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
- u8 interrupts);
+int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 nr_irqs);
int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
-int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
- u16 interrupts, enum pci_barno, u32 offset);
+int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u16 nr_irqs,
+ enum pci_barno, u32 offset);
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,
phys_addr_t phys_addr, u8 interrupt_num,