Commit 5e50ee27 authored by Vidya Sagar's avatar Vidya Sagar Committed by Lorenzo Pieralisi

PCI: pci-epf-test: Add support to defer core initialization

Add support to defer core initialization for the endpoint mode of
operation.

This would enable support for implementations where the core
initialization needs to be deferred until the PCIe reference clock is
available from the host system.
Signed-off-by: default avatarVidya Sagar <vidyas@nvidia.com>
[lorenzo.pieralisi@arm.com: commit log]
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parent ac37dde7
......@@ -360,18 +360,6 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
msecs_to_jiffies(1));
}
static int pci_epf_test_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct pci_epf *epf = container_of(nb, struct pci_epf, nb);
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler,
msecs_to_jiffies(1));
return NOTIFY_OK;
}
static void pci_epf_test_unbind(struct pci_epf *epf)
{
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
......@@ -428,6 +416,78 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
return 0;
}
static int pci_epf_test_core_init(struct pci_epf *epf)
{
struct pci_epf_header *header = epf->header;
const struct pci_epc_features *epc_features;
struct pci_epc *epc = epf->epc;
struct device *dev = &epf->dev;
bool msix_capable = false;
bool msi_capable = true;
int ret;
epc_features = pci_epc_get_features(epc, epf->func_no);
if (epc_features) {
msix_capable = epc_features->msix_capable;
msi_capable = epc_features->msi_capable;
}
ret = pci_epc_write_header(epc, epf->func_no, header);
if (ret) {
dev_err(dev, "Configuration header write failed\n");
return ret;
}
ret = pci_epf_test_set_bar(epf);
if (ret)
return ret;
if (msi_capable) {
ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts);
if (ret) {
dev_err(dev, "MSI configuration failed\n");
return ret;
}
}
if (msix_capable) {
ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts);
if (ret) {
dev_err(dev, "MSI-X configuration failed\n");
return ret;
}
}
return 0;
}
static int pci_epf_test_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct pci_epf *epf = container_of(nb, struct pci_epf, nb);
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
int ret;
switch (val) {
case CORE_INIT:
ret = pci_epf_test_core_init(epf);
if (ret)
return NOTIFY_BAD;
break;
case LINK_UP:
queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler,
msecs_to_jiffies(1));
break;
default:
dev_err(&epf->dev, "Invalid EPF test notifier event\n");
return NOTIFY_BAD;
}
return NOTIFY_OK;
}
static int pci_epf_test_alloc_space(struct pci_epf *epf)
{
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
......@@ -496,14 +556,11 @@ static int pci_epf_test_bind(struct pci_epf *epf)
{
int ret;
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
struct pci_epf_header *header = epf->header;
const struct pci_epc_features *epc_features;
enum pci_barno test_reg_bar = BAR_0;
struct pci_epc *epc = epf->epc;
struct device *dev = &epf->dev;
bool linkup_notifier = false;
bool msix_capable = false;
bool msi_capable = true;
bool core_init_notifier = false;
if (WARN_ON_ONCE(!epc))
return -EINVAL;
......@@ -511,8 +568,7 @@ static int pci_epf_test_bind(struct pci_epf *epf)
epc_features = pci_epc_get_features(epc, epf->func_no);
if (epc_features) {
linkup_notifier = epc_features->linkup_notifier;
msix_capable = epc_features->msix_capable;
msi_capable = epc_features->msi_capable;
core_init_notifier = epc_features->core_init_notifier;
test_reg_bar = pci_epc_get_first_free_bar(epc_features);
pci_epf_configure_bar(epf, epc_features);
}
......@@ -520,34 +576,14 @@ static int pci_epf_test_bind(struct pci_epf *epf)
epf_test->test_reg_bar = test_reg_bar;
epf_test->epc_features = epc_features;
ret = pci_epc_write_header(epc, epf->func_no, header);
if (ret) {
dev_err(dev, "Configuration header write failed\n");
return ret;
}
ret = pci_epf_test_alloc_space(epf);
if (ret)
return ret;
ret = pci_epf_test_set_bar(epf);
if (ret)
return ret;
if (msi_capable) {
ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts);
if (ret) {
dev_err(dev, "MSI configuration failed\n");
return ret;
}
}
if (msix_capable) {
ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts);
if (ret) {
dev_err(dev, "MSI-X configuration failed\n");
if (!core_init_notifier) {
ret = pci_epf_test_core_init(epf);
if (ret)
return ret;
}
}
if (linkup_notifier) {
......
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