Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index d1e7e41..17bbdc9 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -7,7 +7,7 @@
config PCI_ENDPOINT
bool "PCI Endpoint Support"
- depends on HAS_DMA
+ depends on HAVE_PCI
help
Enable this configuration option to support configurable PCI
endpoint. This should be enabled if the platform has a PCI
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 3e86fa3..1cfe368 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -47,9 +47,8 @@
void *reg[6];
struct pci_epf *epf;
enum pci_barno test_reg_bar;
- bool linkup_notifier;
- bool msix_available;
struct delayed_work cmd_handler;
+ const struct pci_epc_features *epc_features;
};
struct pci_epf_test_reg {
@@ -71,11 +70,6 @@
.interrupt_pin = PCI_INTERRUPT_INTA,
};
-struct pci_epf_test_data {
- enum pci_barno test_reg_bar;
- bool linkup_notifier;
-};
-
static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
static int pci_epf_test_copy(struct pci_epf_test *epf_test)
@@ -175,7 +169,7 @@
goto err_map_addr;
}
- memcpy(buf, src_addr, reg->size);
+ memcpy_fromio(buf, src_addr, reg->size);
crc32 = crc32_le(~0, buf, reg->size);
if (crc32 != reg->checksum)
@@ -230,7 +224,7 @@
get_random_bytes(buf, reg->size);
reg->checksum = crc32_le(~0, buf, reg->size);
- memcpy(dst_addr, buf, reg->size);
+ memcpy_toio(dst_addr, buf, reg->size);
/*
* wait 1ms inorder for the write to complete. Without this delay L3
@@ -387,28 +381,36 @@
epf_bar = &epf->bar[bar];
if (epf_test->reg[bar]) {
- pci_epf_free_space(epf, epf_test->reg[bar], bar);
pci_epc_clear_bar(epc, epf->func_no, epf_bar);
+ pci_epf_free_space(epf, epf_test->reg[bar], bar);
}
}
}
static int pci_epf_test_set_bar(struct pci_epf *epf)
{
- int bar;
+ int bar, add;
int ret;
struct pci_epf_bar *epf_bar;
struct pci_epc *epc = epf->epc;
struct device *dev = &epf->dev;
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
+ const struct pci_epc_features *epc_features;
- for (bar = BAR_0; bar <= BAR_5; bar++) {
+ epc_features = epf_test->epc_features;
+
+ for (bar = BAR_0; bar <= BAR_5; bar += add) {
epf_bar = &epf->bar[bar];
+ /*
+ * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64
+ * if the specific implementation required a 64-bit BAR,
+ * even if we only requested a 32-bit BAR.
+ */
+ add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1;
- epf_bar->flags |= upper_32_bits(epf_bar->size) ?
- PCI_BASE_ADDRESS_MEM_TYPE_64 :
- PCI_BASE_ADDRESS_MEM_TYPE_32;
+ if (!!(epc_features->reserved_bar & (1 << bar)))
+ continue;
ret = pci_epc_set_bar(epc, epf->func_no, epf_bar);
if (ret) {
@@ -417,13 +419,6 @@
if (bar == test_reg_bar)
return ret;
}
- /*
- * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64
- * if the specific implementation required a 64-bit BAR,
- * even if we only requested a 32-bit BAR.
- */
- if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
- bar++;
}
return 0;
@@ -433,22 +428,40 @@
{
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
struct device *dev = &epf->dev;
+ struct pci_epf_bar *epf_bar;
void *base;
- int bar;
+ int bar, add;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
+ const struct pci_epc_features *epc_features;
+ size_t test_reg_size;
- base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
- test_reg_bar);
+ epc_features = epf_test->epc_features;
+
+ if (epc_features->bar_fixed_size[test_reg_bar])
+ test_reg_size = bar_size[test_reg_bar];
+ else
+ test_reg_size = sizeof(struct pci_epf_test_reg);
+
+ base = pci_epf_alloc_space(epf, test_reg_size,
+ test_reg_bar, epc_features->align);
if (!base) {
dev_err(dev, "Failed to allocated register space\n");
return -ENOMEM;
}
epf_test->reg[test_reg_bar] = base;
- for (bar = BAR_0; bar <= BAR_5; bar++) {
+ for (bar = BAR_0; bar <= BAR_5; bar += add) {
+ epf_bar = &epf->bar[bar];
+ add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1;
+
if (bar == test_reg_bar)
continue;
- base = pci_epf_alloc_space(epf, bar_size[bar], bar);
+
+ if (!!(epc_features->reserved_bar & (1 << bar)))
+ continue;
+
+ base = pci_epf_alloc_space(epf, bar_size[bar], bar,
+ epc_features->align);
if (!base)
dev_err(dev, "Failed to allocate space for BAR%d\n",
bar);
@@ -458,25 +471,50 @@
return 0;
}
+static void pci_epf_configure_bar(struct pci_epf *epf,
+ const struct pci_epc_features *epc_features)
+{
+ struct pci_epf_bar *epf_bar;
+ bool bar_fixed_64bit;
+ int i;
+
+ for (i = BAR_0; i <= BAR_5; i++) {
+ epf_bar = &epf->bar[i];
+ bar_fixed_64bit = !!(epc_features->bar_fixed_64bit & (1 << i));
+ if (bar_fixed_64bit)
+ epf_bar->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+ if (epc_features->bar_fixed_size[i])
+ bar_size[i] = epc_features->bar_fixed_size[i];
+ }
+}
+
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;
if (WARN_ON_ONCE(!epc))
return -EINVAL;
- if (epc->features & EPC_FEATURE_NO_LINKUP_NOTIFIER)
- epf_test->linkup_notifier = false;
- else
- epf_test->linkup_notifier = true;
+ 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;
+ test_reg_bar = pci_epc_get_first_free_bar(epc_features);
+ pci_epf_configure_bar(epf, epc_features);
+ }
- epf_test->msix_available = epc->features & EPC_FEATURE_MSIX_AVAILABLE;
-
- epf_test->test_reg_bar = EPC_FEATURE_GET_BAR(epc->features);
+ 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) {
@@ -492,13 +530,15 @@
if (ret)
return ret;
- ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts);
- if (ret) {
- dev_err(dev, "MSI configuration failed\n");
- 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 (epf_test->msix_available) {
+ 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");
@@ -506,7 +546,7 @@
}
}
- if (!epf_test->linkup_notifier)
+ if (!linkup_notifier)
queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work);
return 0;
@@ -523,17 +563,6 @@
{
struct pci_epf_test *epf_test;
struct device *dev = &epf->dev;
- const struct pci_epf_device_id *match;
- struct pci_epf_test_data *data;
- enum pci_barno test_reg_bar = BAR_0;
- bool linkup_notifier = true;
-
- match = pci_epf_match_device(pci_epf_test_ids, epf);
- data = (struct pci_epf_test_data *)match->driver_data;
- if (data) {
- test_reg_bar = data->test_reg_bar;
- linkup_notifier = data->linkup_notifier;
- }
epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
if (!epf_test)
@@ -541,8 +570,6 @@
epf->header = &test_header;
epf_test->epf = epf;
- epf_test->test_reg_bar = test_reg_bar;
- epf_test->linkup_notifier = linkup_notifier;
INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
@@ -570,6 +597,11 @@
kpcitest_workqueue = alloc_workqueue("kpcitest",
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ if (!kpcitest_workqueue) {
+ pr_err("Failed to allocate the kpcitest work queue\n");
+ return -ENOMEM;
+ }
+
ret = pci_epf_register_driver(&test_driver);
if (ret) {
pr_err("Failed to register pci epf test driver --> %d\n", ret);
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 094dcc3..2091508 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -84,6 +84,59 @@
EXPORT_SYMBOL_GPL(pci_epc_get);
/**
+ * pci_epc_get_first_free_bar() - helper to get first unreserved BAR
+ * @epc_features: pci_epc_features structure that holds the reserved bar bitmap
+ *
+ * Invoke to get the first unreserved BAR that can be used for endpoint
+ * function. For any incorrect value in reserved_bar return '0'.
+ */
+unsigned int pci_epc_get_first_free_bar(const struct pci_epc_features
+ *epc_features)
+{
+ int free_bar;
+
+ if (!epc_features)
+ return 0;
+
+ free_bar = ffz(epc_features->reserved_bar);
+ if (free_bar > 5)
+ return 0;
+
+ return free_bar;
+}
+EXPORT_SYMBOL_GPL(pci_epc_get_first_free_bar);
+
+/**
+ * pci_epc_get_features() - get the features supported by EPC
+ * @epc: the features supported by *this* EPC device will be returned
+ * @func_no: the features supported by the EPC device specific to the
+ * endpoint function with func_no will be returned
+ *
+ * Invoke to get the features provided by the EPC which may be
+ * specific to an endpoint function. Returns pci_epc_features on success
+ * and NULL for any failures.
+ */
+const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
+ u8 func_no)
+{
+ const struct pci_epc_features *epc_features;
+ unsigned long flags;
+
+ if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
+ return NULL;
+
+ if (!epc->ops->get_features)
+ return NULL;
+
+ spin_lock_irqsave(&epc->lock, flags);
+ epc_features = epc->ops->get_features(epc, func_no);
+ spin_unlock_irqrestore(&epc->lock, flags);
+
+ return epc_features;
+}
+EXPORT_SYMBOL_GPL(pci_epc_get_features);
+
+/**
* pci_epc_stop() - stop the PCI link
* @epc: the link of the EPC device that has to be stopped
*
@@ -466,11 +519,12 @@
{
unsigned long flags;
- if (!epc || IS_ERR(epc))
+ if (!epc || IS_ERR(epc) || !epf)
return;
spin_lock_irqsave(&epc->lock, flags);
list_del(&epf->list);
+ epf->epc = NULL;
spin_unlock_irqrestore(&epc->lock, flags);
}
EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index 825fa24..fb1306d 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -109,10 +109,12 @@
* pci_epf_alloc_space() - allocate memory for the PCI EPF register space
* @size: the size of the memory that has to be allocated
* @bar: the BAR number corresponding to the allocated register space
+ * @align: alignment size for the allocation region
*
* Invoke to allocate memory for the PCI EPF register space.
*/
-void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
+void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
+ size_t align)
{
void *space;
struct device *dev = epf->epc->dev.parent;
@@ -120,7 +122,11 @@
if (size < 128)
size = 128;
- size = roundup_pow_of_two(size);
+
+ if (align)
+ size = ALIGN(size, align);
+ else
+ size = roundup_pow_of_two(size);
space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
if (!space) {
@@ -131,7 +137,9 @@
epf->bar[bar].phys_addr = phys_addr;
epf->bar[bar].size = size;
epf->bar[bar].barno = bar;
- epf->bar[bar].flags = PCI_BASE_ADDRESS_SPACE_MEMORY;
+ epf->bar[bar].flags |= upper_32_bits(size) ?
+ PCI_BASE_ADDRESS_MEM_TYPE_64 :
+ PCI_BASE_ADDRESS_MEM_TYPE_32;
return space;
}