Merge branch 'pci/endpoint'
- Remove unused struct pci_epf_group.type_group (Christophe JAILLET) - Use cached epc_features instead of pci_epc_get_features() to avoid having to check for failure (potential NULL pointer dereference) (Manivannan Sadhasivam) - Drop pointless local msix_capable variable in pci_epf_test_alloc_space() (Manivannan Sadhasivam) - Rename struct pci_epc_event_ops.core_init to .epc_init, since "core" is no longer meaningful here (Manivannan Sadhasivam) - Rename pci_epc_bme_notify(), pci_epf_mhi_bme(), pci_epc_bme_notify() to spell out "bus_master_enable" instead of "bme" (Manivannan Sadhasivam) - Factor pci_epf_test_clear_bar() and pci_epf_test_free_space() out of pci_epf_test_unbind() so they can be reused elsewhere (Manivannan Sadhasivam) - Move DMA initialization to the pci_epf_mhi_epc_init() callback so endpoint drivers do this uniformly (Manivannan Sadhasivam) - Add endpoint testing for Link Down events (Manivannan Sadhasivam) - Add 'epc_deinit' event so endpoints that can be reset via PERST# (qcom, tegra194) can notify EPF drivers when this happens (Manivannan Sadhasivam) - Make pci_epc_class constant (Greg Kroah-Hartman) - Fix vpci_scan_bus() error checking to print error for failure (not success) and clean up after failure (Dan Carpenter) - Fix epf_ntb_epc_cleanup() error handling to clean up scratchpad BARs and clean up in mirror order of allocation (Dan Carpenter) - Add rk3588, which requires 64KB BAR alignment, to pci_endpoint_test (Niklas Cassel) - Use memcpy_toio()/memcpy_fromio() for endpoint BAR tests to improve performance (Niklas Cassel) - Set DMA mask to 48 bits always to simplify endpoint test, since there's there's no need to check for error or to fallback to 32 bits (Frank Li) - Suggest using programmable Vendor/Device ID (when supported) to use pci_endpoint_test without having to add new entries (Yoshihiro Shimoda) - Remove unused pci_endpoint_test_bar_{readl,writel}() (Jiapeng Chong) - Remove 'linkup' and add 'add_cfs' to the endpoint function driver 'ops' documentation to match the code (Alexander Stein) - * pci/endpoint: Documentation: PCI: pci-endpoint: Fix EPF ops list misc: pci_endpoint_test: Remove unused pci_endpoint_test_bar_{readl,writel} functions misc: pci_endpoint_test: Document policy about adding pci_device_id misc: pci_endpoint_test: Refactor dma_set_mask_and_coherent() logic misc: pci_endpoint_test: Use memcpy_toio()/memcpy_fromio() for BAR tests misc: pci_endpoint_test: Add support for Rockchip rk3588 PCI: endpoint: Fix error handling in epf_ntb_epc_cleanup() PCI: endpoint: Clean up error handling in vpci_scan_bus() PCI: endpoint: Make pci_epc_class struct constant PCI: endpoint: Introduce 'epc_deinit' event and notify the EPF drivers PCI: endpoint: pci-epf-test: Handle Link Down event PCI: endpoint: pci-epf-{mhi/test}: Move DMA initialization to EPC init callback PCI: endpoint: pci-epf-test: Refactor pci_epf_test_unbind() function PCI: endpoint: Rename BME to Bus Master Enable PCI: endpoint: Rename core_init() callback in 'struct pci_epc_event_ops' to epc_init() PCI: endpoint: pci-epf-test: Use 'msix_capable' flag directly in pci_epf_test_alloc_space() PCI: endpoint: pci-epf-test: Make use of cached 'epc_features' in pci_epf_test_core_init() PCI: endpoint: Remove unused field in struct pci_epf_group
This commit is contained in:
commit
0f74d89843
@ -172,8 +172,8 @@ by the PCI endpoint function driver.
|
|||||||
* bind: ops to perform when a EPC device has been bound to EPF device
|
* bind: ops to perform when a EPC device has been bound to EPF device
|
||||||
* unbind: ops to perform when a binding has been lost between a EPC
|
* unbind: ops to perform when a binding has been lost between a EPC
|
||||||
device and EPF device
|
device and EPF device
|
||||||
* linkup: ops to perform when the EPC device has established a
|
* add_cfs: optional ops to create function specific configfs
|
||||||
connection with a host system
|
attributes
|
||||||
|
|
||||||
The PCI Function driver can then register the PCI EPF driver by using
|
The PCI Function driver can then register the PCI EPF driver by using
|
||||||
pci_epf_register_driver().
|
pci_epf_register_driver().
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
#include <linux/cleanup.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
@ -84,6 +85,9 @@
|
|||||||
#define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025
|
#define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025
|
||||||
#define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031
|
#define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031
|
||||||
|
|
||||||
|
#define PCI_VENDOR_ID_ROCKCHIP 0x1d87
|
||||||
|
#define PCI_DEVICE_ID_ROCKCHIP_RK3588 0x3588
|
||||||
|
|
||||||
static DEFINE_IDA(pci_endpoint_test_ida);
|
static DEFINE_IDA(pci_endpoint_test_ida);
|
||||||
|
|
||||||
#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
|
#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
|
||||||
@ -140,18 +144,6 @@ static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
|
|||||||
writel(value, test->base + offset);
|
writel(value, test->base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
|
|
||||||
int bar, int offset)
|
|
||||||
{
|
|
||||||
return readl(test->bar[bar] + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
|
|
||||||
int bar, u32 offset, u32 value)
|
|
||||||
{
|
|
||||||
writel(value, test->bar[bar] + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
|
static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct pci_endpoint_test *test = dev_id;
|
struct pci_endpoint_test *test = dev_id;
|
||||||
@ -272,31 +264,60 @@ static const u32 bar_test_pattern[] = {
|
|||||||
0xA5A5A5A5,
|
0xA5A5A5A5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test,
|
||||||
|
enum pci_barno barno, int offset,
|
||||||
|
void *write_buf, void *read_buf,
|
||||||
|
int size)
|
||||||
|
{
|
||||||
|
memset(write_buf, bar_test_pattern[barno], size);
|
||||||
|
memcpy_toio(test->bar[barno] + offset, write_buf, size);
|
||||||
|
|
||||||
|
memcpy_fromio(read_buf, test->bar[barno] + offset, size);
|
||||||
|
|
||||||
|
return memcmp(write_buf, read_buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
|
static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
|
||||||
enum pci_barno barno)
|
enum pci_barno barno)
|
||||||
{
|
{
|
||||||
int j;
|
int j, bar_size, buf_size, iters, remain;
|
||||||
u32 val;
|
void *write_buf __free(kfree) = NULL;
|
||||||
int size;
|
void *read_buf __free(kfree) = NULL;
|
||||||
struct pci_dev *pdev = test->pdev;
|
struct pci_dev *pdev = test->pdev;
|
||||||
|
|
||||||
if (!test->bar[barno])
|
if (!test->bar[barno])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size = pci_resource_len(pdev, barno);
|
bar_size = pci_resource_len(pdev, barno);
|
||||||
|
|
||||||
if (barno == test->test_reg_bar)
|
if (barno == test->test_reg_bar)
|
||||||
size = 0x4;
|
bar_size = 0x4;
|
||||||
|
|
||||||
for (j = 0; j < size; j += 4)
|
/*
|
||||||
pci_endpoint_test_bar_writel(test, barno, j,
|
* Allocate a buffer of max size 1MB, and reuse that buffer while
|
||||||
bar_test_pattern[barno]);
|
* iterating over the whole BAR size (which might be much larger).
|
||||||
|
*/
|
||||||
|
buf_size = min(SZ_1M, bar_size);
|
||||||
|
|
||||||
for (j = 0; j < size; j += 4) {
|
write_buf = kmalloc(buf_size, GFP_KERNEL);
|
||||||
val = pci_endpoint_test_bar_readl(test, barno, j);
|
if (!write_buf)
|
||||||
if (val != bar_test_pattern[barno])
|
return false;
|
||||||
|
|
||||||
|
read_buf = kmalloc(buf_size, GFP_KERNEL);
|
||||||
|
if (!read_buf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iters = bar_size / buf_size;
|
||||||
|
for (j = 0; j < iters; j++)
|
||||||
|
if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * j,
|
||||||
|
write_buf, read_buf, buf_size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
remain = bar_size % buf_size;
|
||||||
|
if (remain)
|
||||||
|
if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * iters,
|
||||||
|
write_buf, read_buf, remain))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -824,11 +845,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
|
|||||||
init_completion(&test->irq_raised);
|
init_completion(&test->irq_raised);
|
||||||
mutex_init(&test->mutex);
|
mutex_init(&test->mutex);
|
||||||
|
|
||||||
if ((dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)) != 0) &&
|
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
|
||||||
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
|
|
||||||
dev_err(dev, "Cannot set DMA mask\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pci_enable_device(pdev);
|
err = pci_enable_device(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -980,6 +997,15 @@ static const struct pci_endpoint_test_data j721e_data = {
|
|||||||
.irq_type = IRQ_TYPE_MSI,
|
.irq_type = IRQ_TYPE_MSI,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct pci_endpoint_test_data rk3588_data = {
|
||||||
|
.alignment = SZ_64K,
|
||||||
|
.irq_type = IRQ_TYPE_MSI,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the controller's Vendor/Device ID are programmable, you may be able to
|
||||||
|
* use one of the existing entries for testing instead of adding a new one.
|
||||||
|
*/
|
||||||
static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x),
|
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x),
|
||||||
.driver_data = (kernel_ulong_t)&default_data,
|
.driver_data = (kernel_ulong_t)&default_data,
|
||||||
@ -1017,6 +1043,9 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
|||||||
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721S2),
|
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721S2),
|
||||||
.driver_data = (kernel_ulong_t)&j721e_data,
|
.driver_data = (kernel_ulong_t)&j721e_data,
|
||||||
},
|
},
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_ROCKCHIP, PCI_DEVICE_ID_ROCKCHIP_RK3588),
|
||||||
|
.driver_data = (kernel_ulong_t)&rk3588_data,
|
||||||
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
|
MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
|
||||||
|
@ -632,7 +632,6 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
|
|||||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||||
|
|
||||||
dw_pcie_edma_remove(pci);
|
dw_pcie_edma_remove(pci);
|
||||||
ep->epc->init_complete = false;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
|
EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
|
||||||
|
|
||||||
|
@ -507,6 +507,7 @@ static void qcom_pcie_perst_assert(struct dw_pcie *pci)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_epc_deinit_notify(pci->ep.epc);
|
||||||
dw_pcie_ep_cleanup(&pci->ep);
|
dw_pcie_ep_cleanup(&pci->ep);
|
||||||
qcom_pcie_disable_resources(pcie_ep);
|
qcom_pcie_disable_resources(pcie_ep);
|
||||||
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED;
|
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED;
|
||||||
@ -642,10 +643,10 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
|
|||||||
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
|
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
|
||||||
pci_epc_linkdown(pci->ep.epc);
|
pci_epc_linkdown(pci->ep.epc);
|
||||||
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
|
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
|
||||||
dev_dbg(dev, "Received BME event. Link is enabled!\n");
|
dev_dbg(dev, "Received Bus Master Enable event\n");
|
||||||
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
|
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
|
||||||
qcom_pcie_ep_icc_update(pcie_ep);
|
qcom_pcie_ep_icc_update(pcie_ep);
|
||||||
pci_epc_bme_notify(pci->ep.epc);
|
pci_epc_bus_master_enable_notify(pci->ep.epc);
|
||||||
} else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) {
|
} else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) {
|
||||||
dev_dbg(dev, "Received PM Turn-off event! Entering L23\n");
|
dev_dbg(dev, "Received PM Turn-off event! Entering L23\n");
|
||||||
val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL);
|
val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL);
|
||||||
|
@ -1715,6 +1715,7 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
|
|||||||
if (ret)
|
if (ret)
|
||||||
dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
|
dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
|
||||||
|
|
||||||
|
pci_epc_deinit_notify(pcie->pci.ep.epc);
|
||||||
dw_pcie_ep_cleanup(&pcie->pci.ep);
|
dw_pcie_ep_cleanup(&pcie->pci.ep);
|
||||||
|
|
||||||
reset_control_assert(pcie->core_rst);
|
reset_control_assert(pcie->core_rst);
|
||||||
|
@ -716,7 +716,7 @@ static void pci_epf_mhi_dma_deinit(struct pci_epf_mhi *epf_mhi)
|
|||||||
epf_mhi->dma_chan_rx = NULL;
|
epf_mhi->dma_chan_rx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_epf_mhi_core_init(struct pci_epf *epf)
|
static int pci_epf_mhi_epc_init(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
||||||
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
|
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
|
||||||
@ -753,9 +753,35 @@ static int pci_epf_mhi_core_init(struct pci_epf *epf)
|
|||||||
if (!epf_mhi->epc_features)
|
if (!epf_mhi->epc_features)
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
|
||||||
|
if (info->flags & MHI_EPF_USE_DMA) {
|
||||||
|
ret = pci_epf_mhi_dma_init(epf_mhi);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to initialize DMA: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_epf_mhi_epc_deinit(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
||||||
|
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
|
||||||
|
struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
|
||||||
|
struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
|
||||||
|
struct pci_epc *epc = epf->epc;
|
||||||
|
|
||||||
|
if (mhi_cntrl->mhi_dev) {
|
||||||
|
mhi_ep_power_down(mhi_cntrl);
|
||||||
|
if (info->flags & MHI_EPF_USE_DMA)
|
||||||
|
pci_epf_mhi_dma_deinit(epf_mhi);
|
||||||
|
mhi_ep_unregister_controller(mhi_cntrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_epf_mhi_link_up(struct pci_epf *epf)
|
static int pci_epf_mhi_link_up(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
||||||
@ -765,14 +791,6 @@ static int pci_epf_mhi_link_up(struct pci_epf *epf)
|
|||||||
struct device *dev = &epf->dev;
|
struct device *dev = &epf->dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (info->flags & MHI_EPF_USE_DMA) {
|
|
||||||
ret = pci_epf_mhi_dma_init(epf_mhi);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to initialize DMA: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mhi_cntrl->mmio = epf_mhi->mmio;
|
mhi_cntrl->mmio = epf_mhi->mmio;
|
||||||
mhi_cntrl->irq = epf_mhi->irq;
|
mhi_cntrl->irq = epf_mhi->irq;
|
||||||
mhi_cntrl->mru = info->mru;
|
mhi_cntrl->mru = info->mru;
|
||||||
@ -819,7 +837,7 @@ static int pci_epf_mhi_link_down(struct pci_epf *epf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_epf_mhi_bme(struct pci_epf *epf)
|
static int pci_epf_mhi_bus_master_enable(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
||||||
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
|
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
|
||||||
@ -882,8 +900,8 @@ static void pci_epf_mhi_unbind(struct pci_epf *epf)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Forcefully power down the MHI EP stack. Only way to bring the MHI EP
|
* Forcefully power down the MHI EP stack. Only way to bring the MHI EP
|
||||||
* stack back to working state after successive bind is by getting BME
|
* stack back to working state after successive bind is by getting Bus
|
||||||
* from host.
|
* Master Enable event from host.
|
||||||
*/
|
*/
|
||||||
if (mhi_cntrl->mhi_dev) {
|
if (mhi_cntrl->mhi_dev) {
|
||||||
mhi_ep_power_down(mhi_cntrl);
|
mhi_ep_power_down(mhi_cntrl);
|
||||||
@ -897,10 +915,11 @@ static void pci_epf_mhi_unbind(struct pci_epf *epf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct pci_epc_event_ops pci_epf_mhi_event_ops = {
|
static const struct pci_epc_event_ops pci_epf_mhi_event_ops = {
|
||||||
.core_init = pci_epf_mhi_core_init,
|
.epc_init = pci_epf_mhi_epc_init,
|
||||||
|
.epc_deinit = pci_epf_mhi_epc_deinit,
|
||||||
.link_up = pci_epf_mhi_link_up,
|
.link_up = pci_epf_mhi_link_up,
|
||||||
.link_down = pci_epf_mhi_link_down,
|
.link_down = pci_epf_mhi_link_down,
|
||||||
.bme = pci_epf_mhi_bme,
|
.bus_master_enable = pci_epf_mhi_bus_master_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pci_epf_mhi_probe(struct pci_epf *epf,
|
static int pci_epf_mhi_probe(struct pci_epf *epf,
|
||||||
|
@ -686,25 +686,6 @@ reset_handler:
|
|||||||
msecs_to_jiffies(1));
|
msecs_to_jiffies(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_epf_test_unbind(struct pci_epf *epf)
|
|
||||||
{
|
|
||||||
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
|
||||||
struct pci_epc *epc = epf->epc;
|
|
||||||
int bar;
|
|
||||||
|
|
||||||
cancel_delayed_work(&epf_test->cmd_handler);
|
|
||||||
pci_epf_test_clean_dma_chan(epf_test);
|
|
||||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
|
||||||
if (!epf_test->reg[bar])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no,
|
|
||||||
&epf->bar[bar]);
|
|
||||||
pci_epf_free_space(epf, epf_test->reg[bar], bar,
|
|
||||||
PRIMARY_INTERFACE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_epf_test_set_bar(struct pci_epf *epf)
|
static int pci_epf_test_set_bar(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
int bar, ret;
|
int bar, ret;
|
||||||
@ -731,23 +712,36 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_epf_test_core_init(struct pci_epf *epf)
|
static void pci_epf_test_clear_bar(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
|
struct pci_epc *epc = epf->epc;
|
||||||
|
int bar;
|
||||||
|
|
||||||
|
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
||||||
|
if (!epf_test->reg[bar])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no,
|
||||||
|
&epf->bar[bar]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pci_epf_test_epc_init(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
struct pci_epf_header *header = epf->header;
|
struct pci_epf_header *header = epf->header;
|
||||||
const struct pci_epc_features *epc_features;
|
const struct pci_epc_features *epc_features = epf_test->epc_features;
|
||||||
struct pci_epc *epc = epf->epc;
|
struct pci_epc *epc = epf->epc;
|
||||||
struct device *dev = &epf->dev;
|
struct device *dev = &epf->dev;
|
||||||
bool linkup_notifier = false;
|
bool linkup_notifier = false;
|
||||||
bool msix_capable = false;
|
|
||||||
bool msi_capable = true;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
epc_features = pci_epc_get_features(epc, epf->func_no, epf->vfunc_no);
|
epf_test->dma_supported = true;
|
||||||
if (epc_features) {
|
|
||||||
msix_capable = epc_features->msix_capable;
|
ret = pci_epf_test_init_dma_chan(epf_test);
|
||||||
msi_capable = epc_features->msi_capable;
|
if (ret)
|
||||||
}
|
epf_test->dma_supported = false;
|
||||||
|
|
||||||
if (epf->vfunc_no <= 1) {
|
if (epf->vfunc_no <= 1) {
|
||||||
ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no, header);
|
ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no, header);
|
||||||
@ -761,7 +755,7 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (msi_capable) {
|
if (epc_features->msi_capable) {
|
||||||
ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no,
|
ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no,
|
||||||
epf->msi_interrupts);
|
epf->msi_interrupts);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -770,7 +764,7 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msix_capable) {
|
if (epc_features->msix_capable) {
|
||||||
ret = pci_epc_set_msix(epc, epf->func_no, epf->vfunc_no,
|
ret = pci_epc_set_msix(epc, epf->func_no, epf->vfunc_no,
|
||||||
epf->msix_interrupts,
|
epf->msix_interrupts,
|
||||||
epf_test->test_reg_bar,
|
epf_test->test_reg_bar,
|
||||||
@ -788,6 +782,15 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_epf_test_epc_deinit(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
|
|
||||||
|
cancel_delayed_work(&epf_test->cmd_handler);
|
||||||
|
pci_epf_test_clean_dma_chan(epf_test);
|
||||||
|
pci_epf_test_clear_bar(epf);
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_epf_test_link_up(struct pci_epf *epf)
|
static int pci_epf_test_link_up(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
@ -798,9 +801,20 @@ static int pci_epf_test_link_up(struct pci_epf *epf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pci_epf_test_link_down(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&epf_test->cmd_handler);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pci_epc_event_ops pci_epf_test_event_ops = {
|
static const struct pci_epc_event_ops pci_epf_test_event_ops = {
|
||||||
.core_init = pci_epf_test_core_init,
|
.epc_init = pci_epf_test_epc_init,
|
||||||
|
.epc_deinit = pci_epf_test_epc_deinit,
|
||||||
.link_up = pci_epf_test_link_up,
|
.link_up = pci_epf_test_link_up,
|
||||||
|
.link_down = pci_epf_test_link_down,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pci_epf_test_alloc_space(struct pci_epf *epf)
|
static int pci_epf_test_alloc_space(struct pci_epf *epf)
|
||||||
@ -810,19 +824,15 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
|
|||||||
size_t msix_table_size = 0;
|
size_t msix_table_size = 0;
|
||||||
size_t test_reg_bar_size;
|
size_t test_reg_bar_size;
|
||||||
size_t pba_size = 0;
|
size_t pba_size = 0;
|
||||||
bool msix_capable;
|
|
||||||
void *base;
|
void *base;
|
||||||
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
|
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
|
||||||
enum pci_barno bar;
|
enum pci_barno bar;
|
||||||
const struct pci_epc_features *epc_features;
|
const struct pci_epc_features *epc_features = epf_test->epc_features;
|
||||||
size_t test_reg_size;
|
size_t test_reg_size;
|
||||||
|
|
||||||
epc_features = epf_test->epc_features;
|
|
||||||
|
|
||||||
test_reg_bar_size = ALIGN(sizeof(struct pci_epf_test_reg), 128);
|
test_reg_bar_size = ALIGN(sizeof(struct pci_epf_test_reg), 128);
|
||||||
|
|
||||||
msix_capable = epc_features->msix_capable;
|
if (epc_features->msix_capable) {
|
||||||
if (msix_capable) {
|
|
||||||
msix_table_size = PCI_MSIX_ENTRY_SIZE * epf->msix_interrupts;
|
msix_table_size = PCI_MSIX_ENTRY_SIZE * epf->msix_interrupts;
|
||||||
epf_test->msix_table_offset = test_reg_bar_size;
|
epf_test->msix_table_offset = test_reg_bar_size;
|
||||||
/* Align to QWORD or 8 Bytes */
|
/* Align to QWORD or 8 Bytes */
|
||||||
@ -857,6 +867,20 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_epf_test_free_space(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
|
int bar;
|
||||||
|
|
||||||
|
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
||||||
|
if (!epf_test->reg[bar])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pci_epf_free_space(epf, epf_test->reg[bar], bar,
|
||||||
|
PRIMARY_INTERFACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_epf_test_bind(struct pci_epf *epf)
|
static int pci_epf_test_bind(struct pci_epf *epf)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -885,15 +909,22 @@ static int pci_epf_test_bind(struct pci_epf *epf)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
epf_test->dma_supported = true;
|
|
||||||
|
|
||||||
ret = pci_epf_test_init_dma_chan(epf_test);
|
|
||||||
if (ret)
|
|
||||||
epf_test->dma_supported = false;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_epf_test_unbind(struct pci_epf *epf)
|
||||||
|
{
|
||||||
|
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
|
||||||
|
struct pci_epc *epc = epf->epc;
|
||||||
|
|
||||||
|
cancel_delayed_work(&epf_test->cmd_handler);
|
||||||
|
if (epc->init_complete) {
|
||||||
|
pci_epf_test_clean_dma_chan(epf_test);
|
||||||
|
pci_epf_test_clear_bar(epf);
|
||||||
|
}
|
||||||
|
pci_epf_test_free_space(epf);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pci_epf_device_id pci_epf_test_ids[] = {
|
static const struct pci_epf_device_id pci_epf_test_ids[] = {
|
||||||
{
|
{
|
||||||
.name = "pci_epf_test",
|
.name = "pci_epf_test",
|
||||||
|
@ -799,8 +799,9 @@ err_config_interrupt:
|
|||||||
*/
|
*/
|
||||||
static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
|
static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
|
||||||
{
|
{
|
||||||
epf_ntb_db_bar_clear(ntb);
|
|
||||||
epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
|
epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
|
||||||
|
epf_ntb_db_bar_clear(ntb);
|
||||||
|
epf_ntb_config_sspad_bar_clear(ntb);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EPF_NTB_R(_name) \
|
#define EPF_NTB_R(_name) \
|
||||||
@ -1018,8 +1019,10 @@ static int vpci_scan_bus(void *sysdata)
|
|||||||
struct epf_ntb *ndev = sysdata;
|
struct epf_ntb *ndev = sysdata;
|
||||||
|
|
||||||
vpci_bus = pci_scan_bus(ndev->vbus_number, &vpci_ops, sysdata);
|
vpci_bus = pci_scan_bus(ndev->vbus_number, &vpci_ops, sysdata);
|
||||||
if (vpci_bus)
|
if (!vpci_bus) {
|
||||||
pr_err("create pci bus\n");
|
pr_err("create pci bus failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
pci_bus_add_devices(vpci_bus);
|
pci_bus_add_devices(vpci_bus);
|
||||||
|
|
||||||
@ -1335,13 +1338,19 @@ static int epf_ntb_bind(struct pci_epf *epf)
|
|||||||
ret = pci_register_driver(&vntb_pci_driver);
|
ret = pci_register_driver(&vntb_pci_driver);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failure register vntb pci driver\n");
|
dev_err(dev, "failure register vntb pci driver\n");
|
||||||
goto err_bar_alloc;
|
goto err_epc_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
vpci_scan_bus(ntb);
|
ret = vpci_scan_bus(ntb);
|
||||||
|
if (ret)
|
||||||
|
goto err_unregister;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_unregister:
|
||||||
|
pci_unregister_driver(&vntb_pci_driver);
|
||||||
|
err_epc_cleanup:
|
||||||
|
epf_ntb_epc_cleanup(ntb);
|
||||||
err_bar_alloc:
|
err_bar_alloc:
|
||||||
epf_ntb_config_spad_bar_free(ntb);
|
epf_ntb_config_spad_bar_free(ntb);
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ struct pci_epf_group {
|
|||||||
struct config_group group;
|
struct config_group group;
|
||||||
struct config_group primary_epc_group;
|
struct config_group primary_epc_group;
|
||||||
struct config_group secondary_epc_group;
|
struct config_group secondary_epc_group;
|
||||||
struct config_group *type_group;
|
|
||||||
struct delayed_work cfs_work;
|
struct delayed_work cfs_work;
|
||||||
struct pci_epf *epf;
|
struct pci_epf *epf;
|
||||||
int index;
|
int index;
|
||||||
|
@ -14,7 +14,9 @@
|
|||||||
#include <linux/pci-epf.h>
|
#include <linux/pci-epf.h>
|
||||||
#include <linux/pci-ep-cfs.h>
|
#include <linux/pci-ep-cfs.h>
|
||||||
|
|
||||||
static struct class *pci_epc_class;
|
static const struct class pci_epc_class = {
|
||||||
|
.name = "pci_epc",
|
||||||
|
};
|
||||||
|
|
||||||
static void devm_pci_epc_release(struct device *dev, void *res)
|
static void devm_pci_epc_release(struct device *dev, void *res)
|
||||||
{
|
{
|
||||||
@ -60,7 +62,7 @@ struct pci_epc *pci_epc_get(const char *epc_name)
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct class_dev_iter iter;
|
struct class_dev_iter iter;
|
||||||
|
|
||||||
class_dev_iter_init(&iter, pci_epc_class, NULL, NULL);
|
class_dev_iter_init(&iter, &pci_epc_class, NULL, NULL);
|
||||||
while ((dev = class_dev_iter_next(&iter))) {
|
while ((dev = class_dev_iter_next(&iter))) {
|
||||||
if (strcmp(epc_name, dev_name(dev)))
|
if (strcmp(epc_name, dev_name(dev)))
|
||||||
continue;
|
continue;
|
||||||
@ -727,9 +729,9 @@ void pci_epc_linkdown(struct pci_epc *epc)
|
|||||||
EXPORT_SYMBOL_GPL(pci_epc_linkdown);
|
EXPORT_SYMBOL_GPL(pci_epc_linkdown);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_epc_init_notify() - Notify the EPF device that EPC device's core
|
* pci_epc_init_notify() - Notify the EPF device that EPC device initialization
|
||||||
* initialization is completed.
|
* is completed.
|
||||||
* @epc: the EPC device whose core initialization is completed
|
* @epc: the EPC device whose initialization is completed
|
||||||
*
|
*
|
||||||
* Invoke to Notify the EPF device that the EPC device's initialization
|
* Invoke to Notify the EPF device that the EPC device's initialization
|
||||||
* is completed.
|
* is completed.
|
||||||
@ -744,8 +746,8 @@ void pci_epc_init_notify(struct pci_epc *epc)
|
|||||||
mutex_lock(&epc->list_lock);
|
mutex_lock(&epc->list_lock);
|
||||||
list_for_each_entry(epf, &epc->pci_epf, list) {
|
list_for_each_entry(epf, &epc->pci_epf, list) {
|
||||||
mutex_lock(&epf->lock);
|
mutex_lock(&epf->lock);
|
||||||
if (epf->event_ops && epf->event_ops->core_init)
|
if (epf->event_ops && epf->event_ops->epc_init)
|
||||||
epf->event_ops->core_init(epf);
|
epf->event_ops->epc_init(epf);
|
||||||
mutex_unlock(&epf->lock);
|
mutex_unlock(&epf->lock);
|
||||||
}
|
}
|
||||||
epc->init_complete = true;
|
epc->init_complete = true;
|
||||||
@ -756,7 +758,7 @@ EXPORT_SYMBOL_GPL(pci_epc_init_notify);
|
|||||||
/**
|
/**
|
||||||
* pci_epc_notify_pending_init() - Notify the pending EPC device initialization
|
* pci_epc_notify_pending_init() - Notify the pending EPC device initialization
|
||||||
* complete to the EPF device
|
* complete to the EPF device
|
||||||
* @epc: the EPC device whose core initialization is pending to be notified
|
* @epc: the EPC device whose initialization is pending to be notified
|
||||||
* @epf: the EPF device to be notified
|
* @epf: the EPF device to be notified
|
||||||
*
|
*
|
||||||
* Invoke to notify the pending EPC device initialization complete to the EPF
|
* Invoke to notify the pending EPC device initialization complete to the EPF
|
||||||
@ -767,22 +769,20 @@ void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf)
|
|||||||
{
|
{
|
||||||
if (epc->init_complete) {
|
if (epc->init_complete) {
|
||||||
mutex_lock(&epf->lock);
|
mutex_lock(&epf->lock);
|
||||||
if (epf->event_ops && epf->event_ops->core_init)
|
if (epf->event_ops && epf->event_ops->epc_init)
|
||||||
epf->event_ops->core_init(epf);
|
epf->event_ops->epc_init(epf);
|
||||||
mutex_unlock(&epf->lock);
|
mutex_unlock(&epf->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init);
|
EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_epc_bme_notify() - Notify the EPF device that the EPC device has received
|
* pci_epc_deinit_notify() - Notify the EPF device about EPC deinitialization
|
||||||
* the BME event from the Root complex
|
* @epc: the EPC device whose deinitialization is completed
|
||||||
* @epc: the EPC device that received the BME event
|
|
||||||
*
|
*
|
||||||
* Invoke to Notify the EPF device that the EPC device has received the Bus
|
* Invoke to notify the EPF device that the EPC deinitialization is completed.
|
||||||
* Master Enable (BME) event from the Root complex
|
|
||||||
*/
|
*/
|
||||||
void pci_epc_bme_notify(struct pci_epc *epc)
|
void pci_epc_deinit_notify(struct pci_epc *epc)
|
||||||
{
|
{
|
||||||
struct pci_epf *epf;
|
struct pci_epf *epf;
|
||||||
|
|
||||||
@ -792,13 +792,41 @@ void pci_epc_bme_notify(struct pci_epc *epc)
|
|||||||
mutex_lock(&epc->list_lock);
|
mutex_lock(&epc->list_lock);
|
||||||
list_for_each_entry(epf, &epc->pci_epf, list) {
|
list_for_each_entry(epf, &epc->pci_epf, list) {
|
||||||
mutex_lock(&epf->lock);
|
mutex_lock(&epf->lock);
|
||||||
if (epf->event_ops && epf->event_ops->bme)
|
if (epf->event_ops && epf->event_ops->epc_deinit)
|
||||||
epf->event_ops->bme(epf);
|
epf->event_ops->epc_deinit(epf);
|
||||||
|
mutex_unlock(&epf->lock);
|
||||||
|
}
|
||||||
|
epc->init_complete = false;
|
||||||
|
mutex_unlock(&epc->list_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pci_epc_deinit_notify);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pci_epc_bus_master_enable_notify() - Notify the EPF device that the EPC
|
||||||
|
* device has received the Bus Master
|
||||||
|
* Enable event from the Root complex
|
||||||
|
* @epc: the EPC device that received the Bus Master Enable event
|
||||||
|
*
|
||||||
|
* Notify the EPF device that the EPC device has generated the Bus Master Enable
|
||||||
|
* event due to host setting the Bus Master Enable bit in the Command register.
|
||||||
|
*/
|
||||||
|
void pci_epc_bus_master_enable_notify(struct pci_epc *epc)
|
||||||
|
{
|
||||||
|
struct pci_epf *epf;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(epc))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&epc->list_lock);
|
||||||
|
list_for_each_entry(epf, &epc->pci_epf, list) {
|
||||||
|
mutex_lock(&epf->lock);
|
||||||
|
if (epf->event_ops && epf->event_ops->bus_master_enable)
|
||||||
|
epf->event_ops->bus_master_enable(epf);
|
||||||
mutex_unlock(&epf->lock);
|
mutex_unlock(&epf->lock);
|
||||||
}
|
}
|
||||||
mutex_unlock(&epc->list_lock);
|
mutex_unlock(&epc->list_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pci_epc_bme_notify);
|
EXPORT_SYMBOL_GPL(pci_epc_bus_master_enable_notify);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_epc_destroy() - destroy the EPC device
|
* pci_epc_destroy() - destroy the EPC device
|
||||||
@ -867,7 +895,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
|
|||||||
INIT_LIST_HEAD(&epc->pci_epf);
|
INIT_LIST_HEAD(&epc->pci_epf);
|
||||||
|
|
||||||
device_initialize(&epc->dev);
|
device_initialize(&epc->dev);
|
||||||
epc->dev.class = pci_epc_class;
|
epc->dev.class = &pci_epc_class;
|
||||||
epc->dev.parent = dev;
|
epc->dev.parent = dev;
|
||||||
epc->dev.release = pci_epc_release;
|
epc->dev.release = pci_epc_release;
|
||||||
epc->ops = ops;
|
epc->ops = ops;
|
||||||
@ -927,20 +955,13 @@ EXPORT_SYMBOL_GPL(__devm_pci_epc_create);
|
|||||||
|
|
||||||
static int __init pci_epc_init(void)
|
static int __init pci_epc_init(void)
|
||||||
{
|
{
|
||||||
pci_epc_class = class_create("pci_epc");
|
return class_register(&pci_epc_class);
|
||||||
if (IS_ERR(pci_epc_class)) {
|
|
||||||
pr_err("failed to create pci epc class --> %ld\n",
|
|
||||||
PTR_ERR(pci_epc_class));
|
|
||||||
return PTR_ERR(pci_epc_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
module_init(pci_epc_init);
|
module_init(pci_epc_init);
|
||||||
|
|
||||||
static void __exit pci_epc_exit(void)
|
static void __exit pci_epc_exit(void)
|
||||||
{
|
{
|
||||||
class_destroy(pci_epc_class);
|
class_unregister(&pci_epc_class);
|
||||||
}
|
}
|
||||||
module_exit(pci_epc_exit);
|
module_exit(pci_epc_exit);
|
||||||
|
|
||||||
|
@ -197,6 +197,8 @@ struct pci_epc_features {
|
|||||||
|
|
||||||
#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
|
#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI_ENDPOINT
|
||||||
|
|
||||||
#define pci_epc_create(dev, ops) \
|
#define pci_epc_create(dev, ops) \
|
||||||
__pci_epc_create((dev), (ops), THIS_MODULE)
|
__pci_epc_create((dev), (ops), THIS_MODULE)
|
||||||
#define devm_pci_epc_create(dev, ops) \
|
#define devm_pci_epc_create(dev, ops) \
|
||||||
@ -226,7 +228,8 @@ void pci_epc_linkup(struct pci_epc *epc);
|
|||||||
void pci_epc_linkdown(struct pci_epc *epc);
|
void pci_epc_linkdown(struct pci_epc *epc);
|
||||||
void pci_epc_init_notify(struct pci_epc *epc);
|
void pci_epc_init_notify(struct pci_epc *epc);
|
||||||
void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf);
|
void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf);
|
||||||
void pci_epc_bme_notify(struct pci_epc *epc);
|
void pci_epc_deinit_notify(struct pci_epc *epc);
|
||||||
|
void pci_epc_bus_master_enable_notify(struct pci_epc *epc);
|
||||||
void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
|
void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
|
||||||
enum pci_epc_interface_type type);
|
enum pci_epc_interface_type type);
|
||||||
int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
||||||
@ -272,4 +275,14 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
|
|||||||
phys_addr_t *phys_addr, size_t size);
|
phys_addr_t *phys_addr, size_t size);
|
||||||
void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
|
void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
|
||||||
void __iomem *virt_addr, size_t size);
|
void __iomem *virt_addr, size_t size);
|
||||||
|
|
||||||
|
#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 */
|
||||||
#endif /* __LINUX_PCI_EPC_H */
|
#endif /* __LINUX_PCI_EPC_H */
|
||||||
|
@ -70,16 +70,18 @@ struct pci_epf_ops {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* struct pci_epc_event_ops - Callbacks for capturing the EPC events
|
* struct pci_epc_event_ops - Callbacks for capturing the EPC events
|
||||||
* @core_init: Callback for the EPC initialization complete event
|
* @epc_init: Callback for the EPC initialization complete event
|
||||||
|
* @epc_deinit: Callback for the EPC deinitialization event
|
||||||
* @link_up: Callback for the EPC link up event
|
* @link_up: Callback for the EPC link up event
|
||||||
* @link_down: Callback for the EPC link down event
|
* @link_down: Callback for the EPC link down event
|
||||||
* @bme: Callback for the EPC BME (Bus Master Enable) event
|
* @bus_master_enable: Callback for the EPC Bus Master Enable event
|
||||||
*/
|
*/
|
||||||
struct pci_epc_event_ops {
|
struct pci_epc_event_ops {
|
||||||
int (*core_init)(struct pci_epf *epf);
|
int (*epc_init)(struct pci_epf *epf);
|
||||||
|
void (*epc_deinit)(struct pci_epf *epf);
|
||||||
int (*link_up)(struct pci_epf *epf);
|
int (*link_up)(struct pci_epf *epf);
|
||||||
int (*link_down)(struct pci_epf *epf);
|
int (*link_down)(struct pci_epf *epf);
|
||||||
int (*bme)(struct pci_epf *epf);
|
int (*bus_master_enable)(struct pci_epf *epf);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user