Commit 0f74d898 authored by Bjorn Helgaas's avatar Bjorn Helgaas

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
parents 7095d21e 96447ede
...@@ -172,8 +172,8 @@ by the PCI endpoint function driver. ...@@ -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 @@ ...@@ -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 @@ ...@@ -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, ...@@ -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[] = { ...@@ -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;
/*
* Allocate a buffer of max size 1MB, and reuse that buffer while
* 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);
pci_endpoint_test_bar_writel(test, barno, j, if (!write_buf)
bar_test_pattern[barno]); return false;
for (j = 0; j < size; j += 4) { read_buf = kmalloc(buf_size, GFP_KERNEL);
val = pci_endpoint_test_bar_readl(test, barno, j); if (!read_buf)
if (val != bar_test_pattern[barno]) 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, ...@@ -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 = { ...@@ -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[] = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static void pci_epf_test_cmd_handler(struct work_struct *work) ...@@ -686,25 +686,6 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,13 +909,20 @@ static int pci_epf_test_bind(struct pci_epf *epf) ...@@ -885,13 +909,20 @@ static int pci_epf_test_bind(struct pci_epf *epf)
if (ret) if (ret)
return ret; return ret;
epf_test->dma_supported = true; return 0;
}
ret = pci_epf_test_init_dma_chan(epf_test); static void pci_epf_test_unbind(struct pci_epf *epf)
if (ret) {
epf_test->dma_supported = false; struct pci_epf_test *epf_test = epf_get_drvdata(epf);
struct pci_epc *epc = epf->epc;
return 0; 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[] = {
......
...@@ -799,8 +799,9 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb) ...@@ -799,8 +799,9 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
*/ */
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) ...@@ -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) ...@@ -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 { ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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); mutex_unlock(&epf->lock);
} }
epc->init_complete = false;
mutex_unlock(&epc->list_lock); mutex_unlock(&epc->list_lock);
} }
EXPORT_SYMBOL_GPL(pci_epc_bme_notify); 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(&epc->list_lock);
}
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, ...@@ -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); ...@@ -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 { ...@@ -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); ...@@ -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, ...@@ -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 { ...@@ -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);
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment