Merge branch 'pci/endpoint'
- Free all previously requested IRQs in epf_ntb_db_bar_init_msi_doorbell() error path (Koichiro Den) - Free doorbell IRQ in pci-epf-test only if it has actually been requested (Koichiro Den) - Discard pointer to doorbell message array after freeing it in pci_epf_alloc_doorbell() error path (Koichiro Den) - Advertise dynamic inbound mapping support in pci-epf-test and update host pci_endpoint_test to skip doorbell testing if not advertised by endpoint (Koichiro Den) - Constify configfs item and group operations (Christophe JAILLET) - Use array_index_nospec() on configfs MW show/store attributes (Koichiro Den) - Return -ERANGE (not -EINVAL) for configfs out-of-range MW index (Koichiro Den) - Return 0, not remaining timeout, when MHI eDMA ops complete so mhi_ep_ring_add_element() doesn't interpret non-zero as failure (Daniel Hodges) - Remove vntb and ntb duplicate resource teardown that leads to oops when .allow_link() fails or .drop_link() is called (Koichiro Den) - Disable vntb delayed work before clearing BAR mappings and doorbells to avoid oops caused by doing the work after resources have been torn down (Koichiro Den) - Fix pci_epf_add_vepf() kernel-doc typo (Alok Tiwari) - Propagate pci_epf_create() errors to pci_epf_make() callers (Alok Tiwari) - Remove redundant BAR_RESERVED annotation for the high order part of a 64-bit BAR (Niklas Cassel) - Add a way to describe reserved subregions within BARs, e.g., platform-owned fixed register windows, and use it for the RK3588 BAR4 DMA ctrl window (Koichiro Den) - Add BAR_DISABLED for BARs that will never be available to an EPF driver, and change some BAR_RESERVED annotations to BAR_DISABLED (Niklas Cassel) - Disable BARs in common code instead of in each glue driver (Niklas Cassel) - Advertise reserved BARs in Capabilities so host-side drivers can skip them (Niklas Cassel) - Skip reserved BARs in selftests (Niklas Cassel) - Improve error messages and include device name when available (Manivannan Sadhasivam) - Add NTB .get_dma_dev() callback for cases where DMA API requires a different device, e.g., vNTB devices (Koichiro Den) - Return -EINVAL, not -ENOSPC, if endpoint test determines the subrange size is too small (Koichiro Den) - Add reserved region types for MSI-X Table and PBA so Endpoint controllers can them as describe hardware-owned regions in a BAR_RESERVED BAR (Manikanta Maddireddy) - Make Tegra194/234 BAR0 programmable and remove 1MB size limit (Manikanta Maddireddy) - Expose Tegra BAR2 (MSI-X) and BAR4 (DMA) as 64-bit BAR_RESERVED (Manikanta Maddireddy) - Add Tegra194 and Tegra234 device table entries to pci_endpoint_test (Manikanta Maddireddy) - Skip the BAR subrange selftest if there are not enough inbound window resources to run the test (Christian Bruel) * pci/endpoint: selftests: pci_endpoint: Skip BAR subrange test on -ENOSPC misc: pci_endpoint_test: Add Tegra194 and Tegra234 device table entries PCI: tegra194: Expose BAR2 (MSI-X) and BAR4 (DMA) as 64-bit BAR_RESERVED PCI: tegra194: Make BAR0 programmable and remove 1MB size limit PCI: endpoint: Add reserved region type for MSI-X Table and PBA misc: pci_endpoint_test: Use -EINVAL for small subrange size PCI: endpoint: pci-epf-vntb: Implement .get_dma_dev() NTB: ntb_transport: Use ntb_get_dma_dev() for DMA buffers NTB: core: Add .get_dma_dev() callback to ntb_dev_ops PCI: endpoint: Improve error messages PCI: endpoint: Print the EPF name in the error log of pci_epf_make() selftests: pci_endpoint: Skip reserved BARs misc: pci_endpoint_test: Give reserved BARs a distinct error code PCI: endpoint: pci-epf-test: Advertise reserved BARs PCI: dwc: Disable BARs in common code instead of in each glue driver PCI: dwc: Replace certain BAR_RESERVED with BAR_DISABLED in glue drivers PCI: endpoint: Introduce pci_epc_bar_type BAR_DISABLED PCI: dw-rockchip: Describe RK3588 BAR4 DMA ctrl window PCI: endpoint: Describe reserved subregions within BARs PCI: endpoint: Allow only_64bit on BAR_RESERVED PCI: endpoint: Do not mark the BAR succeeding a 64-bit BAR as BAR_RESERVED PCI: endpoint: Propagate error from pci_epf_create() PCI: endpoint: Fix typo in pci_epf_add_vepf() kernel-doc PCI: endpoint: pci-epf-vntb: Stop cmd_handler work in epf_ntb_epc_cleanup PCI: endpoint: pci-epf-ntb: Remove duplicate resource teardown PCI: endpoint: pci-epf-vntb: Remove duplicate resource teardown PCI: epf-mhi: Return 0, not remaining timeout, when eDMA ops complete PCI: endpoint: pci-epf-vntb: Return -ERANGE for out-of-range MW index PCI: endpoint: pci-epf-vntb: Use array_index_nospec() on mws_size[] access PCI: endpoint: Constify struct configfs_item_operations and configfs_group_operations selftests: pci_endpoint: Skip doorbell test when unsupported misc: pci_endpoint_test: Gate doorbell test on dynamic inbound mapping PCI: endpoint: pci-epf-test: Advertise dynamic inbound mapping support PCI: endpoint: pci-ep-msi: Fix error unwind and prevent double alloc PCI: endpoint: pci-epf-test: Don't free doorbell IRQ unless requested PCI: endpoint: pci-epf-vntb: Fix MSI doorbell IRQ unwind
This commit is contained in:
commit
8153aaf6b9
28 changed files with 313 additions and 250 deletions
|
|
@ -61,6 +61,7 @@
|
|||
#define STATUS_BAR_SUBRANGE_SETUP_FAIL BIT(15)
|
||||
#define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS BIT(16)
|
||||
#define STATUS_BAR_SUBRANGE_CLEAR_FAIL BIT(17)
|
||||
#define STATUS_NO_RESOURCE BIT(18)
|
||||
|
||||
#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c
|
||||
#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
|
||||
|
|
@ -84,6 +85,13 @@
|
|||
#define CAP_MSIX BIT(2)
|
||||
#define CAP_INTX BIT(3)
|
||||
#define CAP_SUBRANGE_MAPPING BIT(4)
|
||||
#define CAP_DYNAMIC_INBOUND_MAPPING BIT(5)
|
||||
#define CAP_BAR0_RESERVED BIT(6)
|
||||
#define CAP_BAR1_RESERVED BIT(7)
|
||||
#define CAP_BAR2_RESERVED BIT(8)
|
||||
#define CAP_BAR3_RESERVED BIT(9)
|
||||
#define CAP_BAR4_RESERVED BIT(10)
|
||||
#define CAP_BAR5_RESERVED BIT(11)
|
||||
|
||||
#define PCI_ENDPOINT_TEST_DB_BAR 0x34
|
||||
#define PCI_ENDPOINT_TEST_DB_OFFSET 0x38
|
||||
|
|
@ -107,6 +115,9 @@
|
|||
|
||||
#define PCI_DEVICE_ID_ROCKCHIP_RK3588 0x3588
|
||||
|
||||
#define PCI_DEVICE_ID_NVIDIA_TEGRA194_EP 0x1ad4
|
||||
#define PCI_DEVICE_ID_NVIDIA_TEGRA234_EP 0x229b
|
||||
|
||||
#define PCI_ENDPOINT_TEST_BAR_SUBRANGE_NSUB 2
|
||||
|
||||
static DEFINE_IDA(pci_endpoint_test_ida);
|
||||
|
|
@ -275,6 +286,11 @@ fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool bar_is_reserved(struct pci_endpoint_test *test, enum pci_barno bar)
|
||||
{
|
||||
return test->ep_caps & BIT(bar + __fls(CAP_BAR0_RESERVED));
|
||||
}
|
||||
|
||||
static const u32 bar_test_pattern[] = {
|
||||
0xA0A0A0A0,
|
||||
0xA1A1A1A1,
|
||||
|
|
@ -403,7 +419,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
|
|||
|
||||
/* Write all BARs in order (without reading). */
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
if (test->bar[bar])
|
||||
if (test->bar[bar] && !bar_is_reserved(test, bar))
|
||||
pci_endpoint_test_bars_write_bar(test, bar);
|
||||
|
||||
/*
|
||||
|
|
@ -413,7 +429,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
|
|||
* (Reading back the BAR directly after writing can not detect this.)
|
||||
*/
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
||||
if (test->bar[bar]) {
|
||||
if (test->bar[bar] && !bar_is_reserved(test, bar)) {
|
||||
ret = pci_endpoint_test_bars_read_bar(test, bar);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -465,7 +481,7 @@ static int pci_endpoint_test_bar_subrange_cmd(struct pci_endpoint_test *test,
|
|||
|
||||
status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
|
||||
if (status & fail_bit)
|
||||
return -EIO;
|
||||
return (status & STATUS_NO_RESOURCE) ? -ENOSPC : -EIO;
|
||||
|
||||
if (!(status & ok_bit))
|
||||
return -EIO;
|
||||
|
|
@ -535,7 +551,7 @@ static int pci_endpoint_test_bar_subrange(struct pci_endpoint_test *test,
|
|||
|
||||
sub_size = bar_size / nsub;
|
||||
if (sub_size < sizeof(u32)) {
|
||||
ret = -ENOSPC;
|
||||
ret = -EINVAL;
|
||||
goto out_clear;
|
||||
}
|
||||
|
||||
|
|
@ -1060,6 +1076,9 @@ static int pci_endpoint_test_doorbell(struct pci_endpoint_test *test)
|
|||
u32 addr;
|
||||
int left;
|
||||
|
||||
if (!(test->ep_caps & CAP_DYNAMIC_INBOUND_MAPPING))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (irq_type < PCITEST_IRQ_TYPE_INTX ||
|
||||
irq_type > PCITEST_IRQ_TYPE_MSIX) {
|
||||
dev_err(dev, "Invalid IRQ type\n");
|
||||
|
|
@ -1139,6 +1158,11 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
|
|||
if (is_am654_pci_dev(pdev) && bar == BAR_0)
|
||||
goto ret;
|
||||
|
||||
if (bar_is_reserved(test, bar)) {
|
||||
ret = -ENOBUFS;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (cmd == PCITEST_BAR)
|
||||
ret = pci_endpoint_test_bar(test, bar);
|
||||
else
|
||||
|
|
@ -1418,6 +1442,8 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_ROCKCHIP, PCI_DEVICE_ID_ROCKCHIP_RK3588),
|
||||
.driver_data = (kernel_ulong_t)&rk3588_data,
|
||||
},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TEGRA194_EP),},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TEGRA234_EP),},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
|
||||
|
|
|
|||
|
|
@ -759,13 +759,13 @@ static void ntb_transport_msi_desc_changed(void *data)
|
|||
static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw)
|
||||
{
|
||||
struct ntb_transport_mw *mw = &nt->mw_vec[num_mw];
|
||||
struct pci_dev *pdev = nt->ndev->pdev;
|
||||
struct device *dma_dev = ntb_get_dma_dev(nt->ndev);
|
||||
|
||||
if (!mw->virt_addr)
|
||||
return;
|
||||
|
||||
ntb_mw_clear_trans(nt->ndev, PIDX, num_mw);
|
||||
dma_free_coherent(&pdev->dev, mw->alloc_size,
|
||||
dma_free_coherent(dma_dev, mw->alloc_size,
|
||||
mw->alloc_addr, mw->dma_addr);
|
||||
mw->xlat_size = 0;
|
||||
mw->buff_size = 0;
|
||||
|
|
@ -835,7 +835,7 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
|
|||
resource_size_t size)
|
||||
{
|
||||
struct ntb_transport_mw *mw = &nt->mw_vec[num_mw];
|
||||
struct pci_dev *pdev = nt->ndev->pdev;
|
||||
struct device *dma_dev = ntb_get_dma_dev(nt->ndev);
|
||||
size_t xlat_size, buff_size;
|
||||
resource_size_t xlat_align;
|
||||
resource_size_t xlat_align_size;
|
||||
|
|
@ -864,12 +864,12 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
|
|||
mw->buff_size = buff_size;
|
||||
mw->alloc_size = buff_size;
|
||||
|
||||
rc = ntb_alloc_mw_buffer(mw, &pdev->dev, xlat_align);
|
||||
rc = ntb_alloc_mw_buffer(mw, dma_dev, xlat_align);
|
||||
if (rc) {
|
||||
mw->alloc_size *= 2;
|
||||
rc = ntb_alloc_mw_buffer(mw, &pdev->dev, xlat_align);
|
||||
rc = ntb_alloc_mw_buffer(mw, dma_dev, xlat_align);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
dev_err(dma_dev,
|
||||
"Unable to alloc aligned MW buff\n");
|
||||
mw->xlat_size = 0;
|
||||
mw->buff_size = 0;
|
||||
|
|
@ -882,7 +882,7 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
|
|||
rc = ntb_mw_set_trans(nt->ndev, PIDX, num_mw, mw->dma_addr,
|
||||
mw->xlat_size);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Unable to set mw%d translation", num_mw);
|
||||
dev_err(dma_dev, "Unable to set mw%d translation", num_mw);
|
||||
ntb_free_mw(nt, num_mw);
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,10 +378,6 @@ static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
|
||||
dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1401,15 +1401,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {
|
|||
.stop_link = imx_pcie_stop_link,
|
||||
};
|
||||
|
||||
static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
enum pci_barno bar;
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
|
||||
for (bar = BAR_0; bar <= BAR_5; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
unsigned int type, u16 interrupt_num)
|
||||
{
|
||||
|
|
@ -1433,19 +1424,19 @@ static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
|||
static const struct pci_epc_features imx8m_pcie_epc_features = {
|
||||
DWC_EPC_COMMON_FEATURES,
|
||||
.msi_capable = true,
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_1] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_3] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_256, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_5] = { .type = BAR_DISABLED, },
|
||||
.align = SZ_64K,
|
||||
};
|
||||
|
||||
static const struct pci_epc_features imx8q_pcie_epc_features = {
|
||||
DWC_EPC_COMMON_FEATURES,
|
||||
.msi_capable = true,
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_1] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_3] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_5] = { .type = BAR_DISABLED, },
|
||||
.align = SZ_64K,
|
||||
};
|
||||
|
||||
|
|
@ -1478,7 +1469,6 @@ imx_pcie_ep_get_features(struct dw_pcie_ep *ep)
|
|||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops pcie_ep_ops = {
|
||||
.init = imx_pcie_ep_init,
|
||||
.raise_irq = imx_pcie_ep_raise_irq,
|
||||
.get_features = imx_pcie_ep_get_features,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -933,6 +933,18 @@ static const struct pci_epc_features ks_pcie_am654_epc_features = {
|
|||
DWC_EPC_COMMON_FEATURES,
|
||||
.msi_capable = true,
|
||||
.msix_capable = true,
|
||||
/*
|
||||
* TODO: This driver is the only DWC glue driver that had BAR_RESERVED
|
||||
* BARs, but did not call dw_pcie_ep_reset_bar() for the reserved BARs.
|
||||
*
|
||||
* To not change the existing behavior, these BARs were not migrated to
|
||||
* BAR_DISABLED. If this driver wants the BAR_RESERVED BARs to be
|
||||
* disabled, it should migrate them to BAR_DISABLED.
|
||||
*
|
||||
* If they actually should be enabled, then the driver must also define
|
||||
* what is behind these reserved BARs, see the definition of struct
|
||||
* pci_epc_bar_rsvd_region.
|
||||
*/
|
||||
.bar[BAR_0] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .type = BAR_RESIZABLE, },
|
||||
|
|
|
|||
|
|
@ -152,15 +152,11 @@ static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
|
||||
struct dw_pcie_ep_func *ep_func;
|
||||
enum pci_barno bar;
|
||||
|
||||
ep_func = dw_pcie_ep_get_func_from_ep(ep, 0);
|
||||
if (!ep_func)
|
||||
return;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
|
||||
pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false;
|
||||
pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;
|
||||
}
|
||||
|
|
@ -251,9 +247,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
|
|||
pci->ops = pcie->drvdata->dw_pcie_ops;
|
||||
|
||||
ls_epc->bar[BAR_2].only_64bit = true;
|
||||
ls_epc->bar[BAR_3].type = BAR_RESERVED;
|
||||
ls_epc->bar[BAR_4].only_64bit = true;
|
||||
ls_epc->bar[BAR_5].type = BAR_RESERVED;
|
||||
ls_epc->linkup_notifier = true;
|
||||
|
||||
pcie->pci = pci;
|
||||
|
|
|
|||
|
|
@ -340,15 +340,11 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
|
||||
enum pci_barno bar;
|
||||
|
||||
artpec6_pcie_assert_core_reset(artpec6_pcie);
|
||||
artpec6_pcie_init_phy(artpec6_pcie);
|
||||
artpec6_pcie_deassert_core_reset(artpec6_pcie);
|
||||
artpec6_pcie_wait_for_phy(artpec6_pcie);
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
|
|
|
|||
|
|
@ -1114,6 +1114,28 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
|
|||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
}
|
||||
|
||||
static void dw_pcie_ep_disable_bars(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_epc_bar_type bar_type;
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
||||
bar_type = dw_pcie_ep_get_bar_type(ep, bar);
|
||||
|
||||
/*
|
||||
* Reserved BARs should not get disabled by default. All other
|
||||
* BAR types are disabled by default.
|
||||
*
|
||||
* This is in line with the current EPC core design, where all
|
||||
* BARs are disabled by default, and then the EPF driver enables
|
||||
* the BARs it wishes to use.
|
||||
*/
|
||||
if (bar_type != BAR_RESERVED)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dw_pcie_ep_init_registers - Initialize DWC EP specific registers
|
||||
* @ep: DWC EP device
|
||||
|
|
@ -1196,6 +1218,8 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
|
|||
if (ep->ops->init)
|
||||
ep->ops->init(ep);
|
||||
|
||||
dw_pcie_ep_disable_bars(ep);
|
||||
|
||||
/*
|
||||
* PCIe r6.0, section 7.9.15 states that for endpoints that support
|
||||
* PTM, this capability structure is required in exactly one
|
||||
|
|
|
|||
|
|
@ -32,15 +32,6 @@ struct dw_plat_pcie_of_data {
|
|||
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
|
||||
};
|
||||
|
||||
static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
unsigned int type, u16 interrupt_num)
|
||||
{
|
||||
|
|
@ -73,7 +64,6 @@ dw_plat_pcie_get_features(struct dw_pcie_ep *ep)
|
|||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops pcie_ep_ops = {
|
||||
.init = dw_plat_pcie_ep_init,
|
||||
.raise_irq = dw_plat_pcie_ep_raise_irq,
|
||||
.get_features = dw_plat_pcie_get_features,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -361,13 +361,9 @@ static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)
|
|||
static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
rockchip_pcie_enable_l0s(pci);
|
||||
rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
};
|
||||
|
||||
static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
|
|
@ -403,12 +399,19 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
|
|||
.bar[BAR_5] = { .type = BAR_RESIZABLE, },
|
||||
};
|
||||
|
||||
static const struct pci_epc_bar_rsvd_region rk3588_bar4_rsvd[] = {
|
||||
{
|
||||
/* DMA_CAP (BAR4: DMA Port Logic Structure) */
|
||||
.type = PCI_EPC_BAR_RSVD_DMA_CTRL_MMIO,
|
||||
.offset = 0x0,
|
||||
.size = 0x2000,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* BAR4 on rk3588 exposes the ATU Port Logic Structure to the host regardless of
|
||||
* iATU settings for BAR4. This means that BAR4 cannot be used by an EPF driver,
|
||||
* so mark it as RESERVED. (rockchip_pcie_ep_init() will disable all BARs by
|
||||
* default.) If the host could write to BAR4, the iATU settings (for all other
|
||||
* BARs) would be overwritten, resulting in (all other BARs) no longer working.
|
||||
* so mark it as RESERVED.
|
||||
*/
|
||||
static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
|
||||
DWC_EPC_COMMON_FEATURES,
|
||||
|
|
@ -420,7 +423,11 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
|
|||
.bar[BAR_1] = { .type = BAR_RESIZABLE, },
|
||||
.bar[BAR_2] = { .type = BAR_RESIZABLE, },
|
||||
.bar[BAR_3] = { .type = BAR_RESIZABLE, },
|
||||
.bar[BAR_4] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = {
|
||||
.type = BAR_RESERVED,
|
||||
.nr_rsvd_regions = ARRAY_SIZE(rk3588_bar4_rsvd),
|
||||
.rsvd_regions = rk3588_bar4_rsvd,
|
||||
},
|
||||
.bar[BAR_5] = { .type = BAR_RESIZABLE, },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -313,11 +313,8 @@ static const struct pci_epc_features keembay_pcie_epc_features = {
|
|||
.msi_capable = true,
|
||||
.msix_capable = true,
|
||||
.bar[BAR_0] = { .only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .only_64bit = true, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .only_64bit = true, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.align = SZ_16K,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -850,9 +850,7 @@ static const struct pci_epc_features qcom_pcie_epc_features = {
|
|||
.msi_capable = true,
|
||||
.align = SZ_4K,
|
||||
.bar[BAR_0] = { .only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .only_64bit = true, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
};
|
||||
|
||||
static const struct pci_epc_features *
|
||||
|
|
@ -861,17 +859,7 @@ qcom_pcie_epc_get_features(struct dw_pcie_ep *pci_ep)
|
|||
return &qcom_pcie_epc_features;
|
||||
}
|
||||
|
||||
static void qcom_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = BAR_0; bar <= BAR_5; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops pci_ep_ops = {
|
||||
.init = qcom_pcie_ep_init,
|
||||
.raise_irq = qcom_pcie_ep_raise_irq,
|
||||
.get_features = qcom_pcie_epc_get_features,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -386,15 +386,6 @@ static void rcar_gen4_pcie_ep_pre_init(struct dw_pcie_ep *ep)
|
|||
writel(PCIEDMAINTSTSEN_INIT, rcar->base + PCIEDMAINTSTSEN);
|
||||
}
|
||||
|
||||
static void rcar_gen4_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static void rcar_gen4_pcie_ep_deinit(struct rcar_gen4_pcie *rcar)
|
||||
{
|
||||
writel(0, rcar->base + PCIEDMAINTSTSEN);
|
||||
|
|
@ -422,10 +413,10 @@ static int rcar_gen4_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
|||
static const struct pci_epc_features rcar_gen4_pcie_epc_features = {
|
||||
DWC_EPC_COMMON_FEATURES,
|
||||
.msi_capable = true,
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_1] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_3] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256 },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_5] = { .type = BAR_DISABLED, },
|
||||
.align = SZ_1M,
|
||||
};
|
||||
|
||||
|
|
@ -449,7 +440,6 @@ static unsigned int rcar_gen4_pcie_ep_get_dbi2_offset(struct dw_pcie_ep *ep,
|
|||
|
||||
static const struct dw_pcie_ep_ops pcie_ep_ops = {
|
||||
.pre_init = rcar_gen4_pcie_ep_pre_init,
|
||||
.init = rcar_gen4_pcie_ep_init,
|
||||
.raise_irq = rcar_gen4_pcie_ep_raise_irq,
|
||||
.get_features = rcar_gen4_pcie_ep_get_features,
|
||||
.get_dbi_offset = rcar_gen4_pcie_ep_get_dbi_offset,
|
||||
|
|
|
|||
|
|
@ -28,15 +28,6 @@ struct stm32_pcie {
|
|||
unsigned int perst_irq;
|
||||
};
|
||||
|
||||
static void stm32_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int stm32_pcie_start_link(struct dw_pcie *pci)
|
||||
{
|
||||
struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
|
||||
|
|
@ -82,7 +73,6 @@ stm32_pcie_get_features(struct dw_pcie_ep *ep)
|
|||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops stm32_pcie_ep_ops = {
|
||||
.init = stm32_pcie_ep_init,
|
||||
.raise_irq = stm32_pcie_raise_irq,
|
||||
.get_features = stm32_pcie_get_features,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1923,15 +1923,6 @@ static irqreturn_t tegra_pcie_ep_pex_rst_irq(int irq, void *arg)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void tegra_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
};
|
||||
|
||||
static int tegra_pcie_ep_raise_intx_irq(struct tegra_pcie_dw *pcie, u16 irq)
|
||||
{
|
||||
/* Tegra194 supports only INTA */
|
||||
|
|
@ -1987,17 +1978,48 @@ static int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct pci_epc_bar_rsvd_region tegra194_bar2_rsvd[] = {
|
||||
{
|
||||
/* MSI-X table structure */
|
||||
.type = PCI_EPC_BAR_RSVD_MSIX_TBL_RAM,
|
||||
.offset = 0x0,
|
||||
.size = SZ_64K,
|
||||
},
|
||||
{
|
||||
/* MSI-X PBA structure */
|
||||
.type = PCI_EPC_BAR_RSVD_MSIX_PBA_RAM,
|
||||
.offset = 0x10000,
|
||||
.size = SZ_64K,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pci_epc_bar_rsvd_region tegra194_bar4_rsvd[] = {
|
||||
{
|
||||
/* DMA_CAP (BAR4: DMA Port Logic Structure) */
|
||||
.type = PCI_EPC_BAR_RSVD_DMA_CTRL_MMIO,
|
||||
.offset = 0x0,
|
||||
.size = SZ_4K,
|
||||
},
|
||||
};
|
||||
|
||||
/* Tegra EP: BAR0 = 64-bit programmable BAR, BAR2 = 64-bit MSI-X table, BAR4 = 64-bit DMA regs. */
|
||||
static const struct pci_epc_features tegra_pcie_epc_features = {
|
||||
DWC_EPC_COMMON_FEATURES,
|
||||
.linkup_notifier = true,
|
||||
.msi_capable = true,
|
||||
.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
|
||||
.only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_0] = { .only_64bit = true, },
|
||||
.bar[BAR_2] = {
|
||||
.type = BAR_RESERVED,
|
||||
.only_64bit = true,
|
||||
.nr_rsvd_regions = ARRAY_SIZE(tegra194_bar2_rsvd),
|
||||
.rsvd_regions = tegra194_bar2_rsvd,
|
||||
},
|
||||
.bar[BAR_4] = {
|
||||
.type = BAR_RESERVED,
|
||||
.only_64bit = true,
|
||||
.nr_rsvd_regions = ARRAY_SIZE(tegra194_bar4_rsvd),
|
||||
.rsvd_regions = tegra194_bar4_rsvd,
|
||||
},
|
||||
.align = SZ_64K,
|
||||
};
|
||||
|
||||
|
|
@ -2008,7 +2030,6 @@ tegra_pcie_ep_get_features(struct dw_pcie_ep *ep)
|
|||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops pcie_ep_ops = {
|
||||
.init = tegra_pcie_ep_init,
|
||||
.raise_irq = tegra_pcie_ep_raise_irq,
|
||||
.get_features = tegra_pcie_ep_get_features,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -203,15 +203,6 @@ static void uniphier_pcie_stop_link(struct dw_pcie *pci)
|
|||
uniphier_pcie_ltssm_enable(priv, false);
|
||||
}
|
||||
|
||||
static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = BAR_0; bar <= BAR_5; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int uniphier_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
|
|
@ -283,7 +274,6 @@ uniphier_pcie_get_features(struct dw_pcie_ep *ep)
|
|||
}
|
||||
|
||||
static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = {
|
||||
.init = uniphier_pcie_ep_init,
|
||||
.raise_irq = uniphier_pcie_ep_raise_irq,
|
||||
.get_features = uniphier_pcie_get_features,
|
||||
};
|
||||
|
|
@ -426,11 +416,9 @@ static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {
|
|||
.msix_capable = false,
|
||||
.align = 1 << 16,
|
||||
.bar[BAR_0] = { .only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .only_64bit = true, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .type = BAR_DISABLED, },
|
||||
.bar[BAR_5] = { .type = BAR_DISABLED, },
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -445,11 +433,8 @@ static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {
|
|||
.msix_capable = false,
|
||||
.align = 1 << 12,
|
||||
.bar[BAR_0] = { .only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .only_64bit = true, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .only_64bit = true, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -440,13 +440,10 @@ static const struct pci_epc_features rcar_pcie_epc_features = {
|
|||
/* use 64-bit BARs so mark BAR[1,3,5] as reserved */
|
||||
.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = 128,
|
||||
.only_64bit = true, },
|
||||
.bar[BAR_1] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = 256,
|
||||
.only_64bit = true, },
|
||||
.bar[BAR_3] = { .type = BAR_RESERVED, },
|
||||
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256,
|
||||
.only_64bit = true, },
|
||||
.bar[BAR_5] = { .type = BAR_RESERVED, },
|
||||
};
|
||||
|
||||
static const struct pci_epc_features*
|
||||
|
|
|
|||
|
|
@ -367,6 +367,8 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
|
|||
dev_err(dev, "DMA transfer timeout\n");
|
||||
dmaengine_terminate_sync(chan);
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
err_unmap:
|
||||
|
|
@ -438,6 +440,8 @@ static int pci_epf_mhi_edma_write(struct mhi_ep_cntrl *mhi_cntrl,
|
|||
dev_err(dev, "DMA transfer timeout\n");
|
||||
dmaengine_terminate_sync(chan);
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
err_unmap:
|
||||
|
|
|
|||
|
|
@ -1494,47 +1494,6 @@ err_alloc_peer_mem:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_epc_destroy_interface() - Cleanup NTB EPC interface
|
||||
* @ntb: NTB device that facilitates communication between HOST1 and HOST2
|
||||
* @type: PRIMARY interface or SECONDARY interface
|
||||
*
|
||||
* Unbind NTB function device from EPC and relinquish reference to pci_epc
|
||||
* for each of the interface.
|
||||
*/
|
||||
static void epf_ntb_epc_destroy_interface(struct epf_ntb *ntb,
|
||||
enum pci_epc_interface_type type)
|
||||
{
|
||||
struct epf_ntb_epc *ntb_epc;
|
||||
struct pci_epc *epc;
|
||||
struct pci_epf *epf;
|
||||
|
||||
if (type < 0)
|
||||
return;
|
||||
|
||||
epf = ntb->epf;
|
||||
ntb_epc = ntb->epc[type];
|
||||
if (!ntb_epc)
|
||||
return;
|
||||
epc = ntb_epc->epc;
|
||||
pci_epc_remove_epf(epc, epf, type);
|
||||
pci_epc_put(epc);
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_epc_destroy() - Cleanup NTB EPC interface
|
||||
* @ntb: NTB device that facilitates communication between HOST1 and HOST2
|
||||
*
|
||||
* Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces
|
||||
*/
|
||||
static void epf_ntb_epc_destroy(struct epf_ntb *ntb)
|
||||
{
|
||||
enum pci_epc_interface_type type;
|
||||
|
||||
for (type = PRIMARY_INTERFACE; type <= SECONDARY_INTERFACE; type++)
|
||||
epf_ntb_epc_destroy_interface(ntb, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_epc_create_interface() - Create and initialize NTB EPC interface
|
||||
* @ntb: NTB device that facilitates communication between HOST1 and HOST2
|
||||
|
|
@ -1614,15 +1573,8 @@ static int epf_ntb_epc_create(struct epf_ntb *ntb)
|
|||
|
||||
ret = epf_ntb_epc_create_interface(ntb, epf->sec_epc,
|
||||
SECONDARY_INTERFACE);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(dev, "SECONDARY intf: Fail to create NTB EPC\n");
|
||||
goto err_epc_create;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_epc_create:
|
||||
epf_ntb_epc_destroy_interface(ntb, PRIMARY_INTERFACE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1887,7 +1839,7 @@ static int epf_ntb_bind(struct pci_epf *epf)
|
|||
ret = epf_ntb_init_epc_bar(ntb);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to create NTB EPC\n");
|
||||
goto err_bar_init;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = epf_ntb_config_spad_bar_alloc_interface(ntb);
|
||||
|
|
@ -1909,9 +1861,6 @@ static int epf_ntb_bind(struct pci_epf *epf)
|
|||
err_bar_alloc:
|
||||
epf_ntb_config_spad_bar_free(ntb);
|
||||
|
||||
err_bar_init:
|
||||
epf_ntb_epc_destroy(ntb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1927,7 +1876,6 @@ static void epf_ntb_unbind(struct pci_epf *epf)
|
|||
|
||||
epf_ntb_epc_cleanup(ntb);
|
||||
epf_ntb_config_spad_bar_free(ntb);
|
||||
epf_ntb_epc_destroy(ntb);
|
||||
}
|
||||
|
||||
#define EPF_NTB_R(_name) \
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#define STATUS_BAR_SUBRANGE_SETUP_FAIL BIT(15)
|
||||
#define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS BIT(16)
|
||||
#define STATUS_BAR_SUBRANGE_CLEAR_FAIL BIT(17)
|
||||
#define STATUS_NO_RESOURCE BIT(18)
|
||||
|
||||
#define FLAG_USE_DMA BIT(0)
|
||||
|
||||
|
|
@ -64,6 +65,13 @@
|
|||
#define CAP_MSIX BIT(2)
|
||||
#define CAP_INTX BIT(3)
|
||||
#define CAP_SUBRANGE_MAPPING BIT(4)
|
||||
#define CAP_DYNAMIC_INBOUND_MAPPING BIT(5)
|
||||
#define CAP_BAR0_RESERVED BIT(6)
|
||||
#define CAP_BAR1_RESERVED BIT(7)
|
||||
#define CAP_BAR2_RESERVED BIT(8)
|
||||
#define CAP_BAR3_RESERVED BIT(9)
|
||||
#define CAP_BAR4_RESERVED BIT(10)
|
||||
#define CAP_BAR5_RESERVED BIT(11)
|
||||
|
||||
#define PCI_EPF_TEST_BAR_SUBRANGE_NSUB 2
|
||||
|
||||
|
|
@ -715,7 +723,6 @@ static void pci_epf_test_doorbell_cleanup(struct pci_epf_test *epf_test)
|
|||
struct pci_epf_test_reg *reg = epf_test->reg[epf_test->test_reg_bar];
|
||||
struct pci_epf *epf = epf_test->epf;
|
||||
|
||||
free_irq(epf->db_msg[0].virq, epf_test);
|
||||
reg->doorbell_bar = cpu_to_le32(NO_BAR);
|
||||
|
||||
pci_epf_free_doorbell(epf);
|
||||
|
|
@ -759,7 +766,7 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test,
|
|||
&epf_test->db_bar.phys_addr, &offset);
|
||||
|
||||
if (ret)
|
||||
goto err_doorbell_cleanup;
|
||||
goto err_free_irq;
|
||||
|
||||
reg->doorbell_offset = cpu_to_le32(offset);
|
||||
|
||||
|
|
@ -769,12 +776,14 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test,
|
|||
|
||||
ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, &epf_test->db_bar);
|
||||
if (ret)
|
||||
goto err_doorbell_cleanup;
|
||||
goto err_free_irq;
|
||||
|
||||
status |= STATUS_DOORBELL_ENABLE_SUCCESS;
|
||||
reg->status = cpu_to_le32(status);
|
||||
return;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(epf->db_msg[0].virq, epf_test);
|
||||
err_doorbell_cleanup:
|
||||
pci_epf_test_doorbell_cleanup(epf_test);
|
||||
set_status_err:
|
||||
|
|
@ -794,6 +803,7 @@ static void pci_epf_test_disable_doorbell(struct pci_epf_test *epf_test,
|
|||
if (bar < BAR_0)
|
||||
goto set_status_err;
|
||||
|
||||
free_irq(epf->db_msg[0].virq, epf_test);
|
||||
pci_epf_test_doorbell_cleanup(epf_test);
|
||||
|
||||
/*
|
||||
|
|
@ -892,6 +902,8 @@ static void pci_epf_test_bar_subrange_setup(struct pci_epf_test *epf_test,
|
|||
ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, bar);
|
||||
if (ret) {
|
||||
dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret);
|
||||
if (ret == -ENOSPC)
|
||||
status |= STATUS_NO_RESOURCE;
|
||||
bar->submap = old_submap;
|
||||
bar->num_submap = old_nsub;
|
||||
kfree(submap);
|
||||
|
|
@ -1102,10 +1114,31 @@ static void pci_epf_test_set_capabilities(struct pci_epf *epf)
|
|||
if (epf_test->epc_features->intx_capable)
|
||||
caps |= CAP_INTX;
|
||||
|
||||
if (epf_test->epc_features->dynamic_inbound_mapping)
|
||||
caps |= CAP_DYNAMIC_INBOUND_MAPPING;
|
||||
|
||||
if (epf_test->epc_features->dynamic_inbound_mapping &&
|
||||
epf_test->epc_features->subrange_mapping)
|
||||
caps |= CAP_SUBRANGE_MAPPING;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_0].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR0_RESERVED;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_1].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR1_RESERVED;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_2].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR2_RESERVED;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_3].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR3_RESERVED;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_4].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR4_RESERVED;
|
||||
|
||||
if (epf_test->epc_features->bar[BAR_5].type == BAR_RESERVED)
|
||||
caps |= CAP_BAR5_RESERVED;
|
||||
|
||||
reg->caps = cpu_to_le32(caps);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -527,20 +527,20 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
|
|||
struct msi_msg *msg;
|
||||
size_t sz;
|
||||
int ret;
|
||||
int i;
|
||||
int i, req;
|
||||
|
||||
ret = pci_epf_alloc_doorbell(epf, ntb->db_count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ntb->db_count; i++) {
|
||||
ret = request_irq(epf->db_msg[i].virq, epf_ntb_doorbell_handler,
|
||||
for (req = 0; req < ntb->db_count; req++) {
|
||||
ret = request_irq(epf->db_msg[req].virq, epf_ntb_doorbell_handler,
|
||||
0, "pci_epf_vntb_db", ntb);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&epf->dev,
|
||||
"Failed to request doorbell IRQ: %d\n",
|
||||
epf->db_msg[i].virq);
|
||||
epf->db_msg[req].virq);
|
||||
goto err_free_irq;
|
||||
}
|
||||
}
|
||||
|
|
@ -598,8 +598,8 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
|
|||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
for (i--; i >= 0; i--)
|
||||
free_irq(epf->db_msg[i].virq, ntb);
|
||||
for (req--; req >= 0; req--)
|
||||
free_irq(epf->db_msg[req].virq, ntb);
|
||||
|
||||
pci_epf_free_doorbell(ntb->epf);
|
||||
return ret;
|
||||
|
|
@ -763,19 +763,6 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb, int num_mws)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_epc_destroy() - Cleanup NTB EPC interface
|
||||
* @ntb: NTB device that facilitates communication between HOST and VHOST
|
||||
*
|
||||
* Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces
|
||||
*/
|
||||
static void epf_ntb_epc_destroy(struct epf_ntb *ntb)
|
||||
{
|
||||
pci_epc_remove_epf(ntb->epf->epc, ntb->epf, 0);
|
||||
pci_epc_put(ntb->epf->epc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* epf_ntb_is_bar_used() - Check if a bar is used in the ntb configuration
|
||||
* @ntb: NTB device that facilitates communication between HOST and VHOST
|
||||
|
|
@ -955,6 +942,7 @@ err_config_interrupt:
|
|||
*/
|
||||
static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
|
||||
{
|
||||
disable_delayed_work_sync(&ntb->cmd_handler);
|
||||
epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
|
||||
epf_ntb_db_bar_clear(ntb);
|
||||
epf_ntb_config_sspad_bar_clear(ntb);
|
||||
|
|
@ -995,17 +983,19 @@ static ssize_t epf_ntb_##_name##_show(struct config_item *item, \
|
|||
struct config_group *group = to_config_group(item); \
|
||||
struct epf_ntb *ntb = to_epf_ntb(group); \
|
||||
struct device *dev = &ntb->epf->dev; \
|
||||
int win_no; \
|
||||
int win_no, idx; \
|
||||
\
|
||||
if (sscanf(#_name, "mw%d", &win_no) != 1) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
if (win_no <= 0 || win_no > ntb->num_mws) { \
|
||||
dev_err(dev, "Invalid num_nws: %d value\n", ntb->num_mws); \
|
||||
return -EINVAL; \
|
||||
idx = win_no - 1; \
|
||||
if (idx < 0 || idx >= ntb->num_mws) { \
|
||||
dev_err(dev, "MW%d out of range (num_mws=%d)\n", \
|
||||
win_no, ntb->num_mws); \
|
||||
return -ERANGE; \
|
||||
} \
|
||||
\
|
||||
return sprintf(page, "%lld\n", ntb->mws_size[win_no - 1]); \
|
||||
idx = array_index_nospec(idx, ntb->num_mws); \
|
||||
return sprintf(page, "%llu\n", ntb->mws_size[idx]); \
|
||||
}
|
||||
|
||||
#define EPF_NTB_MW_W(_name) \
|
||||
|
|
@ -1015,7 +1005,7 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
|
|||
struct config_group *group = to_config_group(item); \
|
||||
struct epf_ntb *ntb = to_epf_ntb(group); \
|
||||
struct device *dev = &ntb->epf->dev; \
|
||||
int win_no; \
|
||||
int win_no, idx; \
|
||||
u64 val; \
|
||||
int ret; \
|
||||
\
|
||||
|
|
@ -1026,12 +1016,14 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
|
|||
if (sscanf(#_name, "mw%d", &win_no) != 1) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
if (win_no <= 0 || win_no > ntb->num_mws) { \
|
||||
dev_err(dev, "Invalid num_nws: %d value\n", ntb->num_mws); \
|
||||
return -EINVAL; \
|
||||
idx = win_no - 1; \
|
||||
if (idx < 0 || idx >= ntb->num_mws) { \
|
||||
dev_err(dev, "MW%d out of range (num_mws=%d)\n", \
|
||||
win_no, ntb->num_mws); \
|
||||
return -ERANGE; \
|
||||
} \
|
||||
\
|
||||
ntb->mws_size[win_no - 1] = val; \
|
||||
idx = array_index_nospec(idx, ntb->num_mws); \
|
||||
ntb->mws_size[idx] = val; \
|
||||
\
|
||||
return len; \
|
||||
}
|
||||
|
|
@ -1436,6 +1428,14 @@ static int vntb_epf_link_disable(struct ntb_dev *ntb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct device *vntb_epf_get_dma_dev(struct ntb_dev *ndev)
|
||||
{
|
||||
struct epf_ntb *ntb = ntb_ndev(ndev);
|
||||
struct pci_epc *epc = ntb->epf->epc;
|
||||
|
||||
return epc->dev.parent;
|
||||
}
|
||||
|
||||
static const struct ntb_dev_ops vntb_epf_ops = {
|
||||
.mw_count = vntb_epf_mw_count,
|
||||
.spad_count = vntb_epf_spad_count,
|
||||
|
|
@ -1457,6 +1457,7 @@ static const struct ntb_dev_ops vntb_epf_ops = {
|
|||
.db_clear_mask = vntb_epf_db_clear_mask,
|
||||
.db_clear = vntb_epf_db_clear,
|
||||
.link_disable = vntb_epf_link_disable,
|
||||
.get_dma_dev = vntb_epf_get_dma_dev,
|
||||
};
|
||||
|
||||
static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
|
@ -1525,7 +1526,7 @@ static int epf_ntb_bind(struct pci_epf *epf)
|
|||
ret = epf_ntb_init_epc_bar(ntb);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to create NTB EPC\n");
|
||||
goto err_bar_init;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = epf_ntb_config_spad_bar_alloc(ntb);
|
||||
|
|
@ -1565,9 +1566,6 @@ err_epc_cleanup:
|
|||
err_bar_alloc:
|
||||
epf_ntb_config_spad_bar_free(ntb);
|
||||
|
||||
err_bar_init:
|
||||
epf_ntb_epc_destroy(ntb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1583,7 +1581,6 @@ static void epf_ntb_unbind(struct pci_epf *epf)
|
|||
|
||||
epf_ntb_epc_cleanup(ntb);
|
||||
epf_ntb_config_spad_bar_free(ntb);
|
||||
epf_ntb_epc_destroy(ntb);
|
||||
|
||||
pci_unregister_driver(&vntb_pci_driver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ static void pci_secondary_epc_epf_unlink(struct config_item *epf_item,
|
|||
pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations pci_secondary_epc_item_ops = {
|
||||
static const struct configfs_item_operations pci_secondary_epc_item_ops = {
|
||||
.allow_link = pci_secondary_epc_epf_link,
|
||||
.drop_link = pci_secondary_epc_epf_unlink,
|
||||
};
|
||||
|
|
@ -148,7 +148,7 @@ static void pci_primary_epc_epf_unlink(struct config_item *epf_item,
|
|||
pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations pci_primary_epc_item_ops = {
|
||||
static const struct configfs_item_operations pci_primary_epc_item_ops = {
|
||||
.allow_link = pci_primary_epc_epf_link,
|
||||
.drop_link = pci_primary_epc_epf_unlink,
|
||||
};
|
||||
|
|
@ -256,7 +256,7 @@ static void pci_epc_epf_unlink(struct config_item *epc_item,
|
|||
pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations pci_epc_item_ops = {
|
||||
static const struct configfs_item_operations pci_epc_item_ops = {
|
||||
.allow_link = pci_epc_epf_link,
|
||||
.drop_link = pci_epc_epf_unlink,
|
||||
};
|
||||
|
|
@ -507,7 +507,7 @@ static void pci_epf_release(struct config_item *item)
|
|||
kfree(epf_group);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations pci_epf_ops = {
|
||||
static const struct configfs_item_operations pci_epf_ops = {
|
||||
.allow_link = pci_epf_vepf_link,
|
||||
.drop_link = pci_epf_vepf_unlink,
|
||||
.release = pci_epf_release,
|
||||
|
|
@ -565,7 +565,8 @@ static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
|
|||
|
||||
if (IS_ERR(group)) {
|
||||
dev_err(&epf_group->epf->dev,
|
||||
"failed to create epf type specific attributes\n");
|
||||
"failed to create epf type specific attributes: %pe\n",
|
||||
group);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -578,13 +579,17 @@ static void pci_epf_cfs_add_sub_groups(struct pci_epf_group *epf_group)
|
|||
|
||||
group = pci_ep_cfs_add_primary_group(epf_group);
|
||||
if (IS_ERR(group)) {
|
||||
pr_err("failed to create 'primary' EPC interface\n");
|
||||
dev_err(&epf_group->epf->dev,
|
||||
"failed to create 'primary' EPC interface: %pe\n",
|
||||
group);
|
||||
return;
|
||||
}
|
||||
|
||||
group = pci_ep_cfs_add_secondary_group(epf_group);
|
||||
if (IS_ERR(group)) {
|
||||
pr_err("failed to create 'secondary' EPC interface\n");
|
||||
dev_err(&epf_group->epf->dev,
|
||||
"failed to create 'secondary' EPC interface: %pe\n",
|
||||
group);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -624,8 +629,9 @@ static struct config_group *pci_epf_make(struct config_group *group,
|
|||
|
||||
epf = pci_epf_create(epf_name);
|
||||
if (IS_ERR(epf)) {
|
||||
pr_err("failed to create endpoint function device\n");
|
||||
err = -EINVAL;
|
||||
err = PTR_ERR(epf);
|
||||
pr_err("failed to create endpoint function device (%s): %d\n",
|
||||
epf_name, err);
|
||||
goto free_name;
|
||||
}
|
||||
|
||||
|
|
@ -657,7 +663,7 @@ static void pci_epf_drop(struct config_group *group, struct config_item *item)
|
|||
config_item_put(item);
|
||||
}
|
||||
|
||||
static struct configfs_group_operations pci_epf_group_ops = {
|
||||
static const struct configfs_group_operations pci_epf_group_ops = {
|
||||
.make_group = &pci_epf_make,
|
||||
.drop_item = &pci_epf_drop,
|
||||
};
|
||||
|
|
@ -674,8 +680,8 @@ struct config_group *pci_ep_cfs_add_epf_group(const char *name)
|
|||
group = configfs_register_default_group(functions_group, name,
|
||||
&pci_epf_group_type);
|
||||
if (IS_ERR(group))
|
||||
pr_err("failed to register configfs group for %s function\n",
|
||||
name);
|
||||
pr_err("failed to register configfs group for %s function: %pe\n",
|
||||
name, group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (epf->db_msg)
|
||||
return -EBUSY;
|
||||
|
||||
domain = of_msi_map_get_device_domain(epc->dev.parent, 0,
|
||||
DOMAIN_BUS_PLATFORM_MSI);
|
||||
if (!domain) {
|
||||
|
|
@ -79,6 +82,8 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)
|
|||
if (ret) {
|
||||
dev_err(dev, "Failed to allocate MSI\n");
|
||||
kfree(msg);
|
||||
epf->db_msg = NULL;
|
||||
epf->num_db = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,8 +103,9 @@ enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
|
|||
bar++;
|
||||
|
||||
for (i = bar; i < PCI_STD_NUM_BARS; i++) {
|
||||
/* If the BAR is not reserved, return it. */
|
||||
if (epc_features->bar[i].type != BAR_RESERVED)
|
||||
/* If the BAR is not reserved or disabled, return it. */
|
||||
if (epc_features->bar[i].type != BAR_RESERVED &&
|
||||
epc_features->bar[i].type != BAR_DISABLED)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(pci_epf_bind);
|
|||
* @epf_vf: the virtual EP function to be added
|
||||
*
|
||||
* A physical endpoint function can be associated with multiple virtual
|
||||
* endpoint functions. Invoke pci_epf_add_epf() to add a virtual PCI endpoint
|
||||
* endpoint functions. Invoke pci_epf_add_vepf() to add a virtual PCI endpoint
|
||||
* function to a physical PCI endpoint function.
|
||||
*/
|
||||
int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
|
|||
* @msg_clear_mask: See ntb_msg_clear_mask().
|
||||
* @msg_read: See ntb_msg_read().
|
||||
* @peer_msg_write: See ntb_peer_msg_write().
|
||||
* @get_dma_dev: See ntb_get_dma_dev().
|
||||
*/
|
||||
struct ntb_dev_ops {
|
||||
int (*port_number)(struct ntb_dev *ntb);
|
||||
|
|
@ -329,6 +330,7 @@ struct ntb_dev_ops {
|
|||
int (*msg_clear_mask)(struct ntb_dev *ntb, u64 mask_bits);
|
||||
u32 (*msg_read)(struct ntb_dev *ntb, int *pidx, int midx);
|
||||
int (*peer_msg_write)(struct ntb_dev *ntb, int pidx, int midx, u32 msg);
|
||||
struct device *(*get_dma_dev)(struct ntb_dev *ntb);
|
||||
};
|
||||
|
||||
static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops *ops)
|
||||
|
|
@ -391,6 +393,8 @@ static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops *ops)
|
|||
/* !ops->msg_clear_mask == !ops->msg_count && */
|
||||
!ops->msg_read == !ops->msg_count &&
|
||||
!ops->peer_msg_write == !ops->msg_count &&
|
||||
|
||||
/* ops->get_dma_dev is optional */
|
||||
1;
|
||||
}
|
||||
|
||||
|
|
@ -1563,6 +1567,26 @@ static inline int ntb_peer_msg_write(struct ntb_dev *ntb, int pidx, int midx,
|
|||
return ntb->ops->peer_msg_write(ntb, pidx, midx, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntb_get_dma_dev() - get the device to use for DMA allocations/mappings
|
||||
* @ntb: NTB device context.
|
||||
*
|
||||
* Return a struct device suitable for DMA API allocations and mappings.
|
||||
* This is typically the parent of the NTB device, but may be overridden by a
|
||||
* driver by implementing .get_dma_dev().
|
||||
*
|
||||
* Drivers that implement .get_dma_dev() must return a non-NULL pointer.
|
||||
*
|
||||
* Return: device pointer to use for DMA operations.
|
||||
*/
|
||||
static inline struct device *ntb_get_dma_dev(struct ntb_dev *ntb)
|
||||
{
|
||||
if (!ntb->ops->get_dma_dev)
|
||||
return ntb->dev.parent;
|
||||
|
||||
return ntb->ops->get_dma_dev(ntb);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntb_peer_resource_idx() - get a resource index for a given peer idx
|
||||
* @ntb: NTB device context.
|
||||
|
|
|
|||
|
|
@ -191,13 +191,49 @@ struct pci_epc {
|
|||
* @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: The BAR should not be touched by an EPF driver.
|
||||
* @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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -206,18 +242,16 @@ 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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ TEST_F(pci_ep_bar, BAR_TEST)
|
|||
pci_ep_ioctl(PCITEST_BAR, variant->barno);
|
||||
if (ret == -ENODATA)
|
||||
SKIP(return, "BAR is disabled");
|
||||
if (ret == -ENOBUFS)
|
||||
SKIP(return, "BAR is reserved");
|
||||
EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno);
|
||||
}
|
||||
|
||||
|
|
@ -84,6 +86,10 @@ TEST_F(pci_ep_bar, BAR_SUBRANGE_TEST)
|
|||
SKIP(return, "BAR is test register space");
|
||||
if (ret == -EOPNOTSUPP)
|
||||
SKIP(return, "Subrange map is not supported");
|
||||
if (ret == -ENOBUFS)
|
||||
SKIP(return, "BAR is reserved");
|
||||
if (ret == -ENOSPC)
|
||||
SKIP(return, "Not enough inbound windows");
|
||||
EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno);
|
||||
}
|
||||
|
||||
|
|
@ -276,6 +282,8 @@ TEST_F(pcie_ep_doorbell, DOORBELL_TEST)
|
|||
ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
|
||||
|
||||
pci_ep_ioctl(PCITEST_DOORBELL, 0);
|
||||
if (ret == -EOPNOTSUPP)
|
||||
SKIP(return, "Doorbell test is not supported");
|
||||
EXPECT_FALSE(ret) TH_LOG("Test failed for Doorbell\n");
|
||||
}
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue