summaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig8
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/c2port/c2port-duramar2150.c4
-rw-r--r--drivers/misc/cxl/file.c7
-rw-r--r--drivers/misc/cxl/native.c14
-rw-r--r--drivers/misc/dummy-irq.c2
-rw-r--r--drivers/misc/mei/bus.c4
-rw-r--r--drivers/misc/mic/vop/vop_main.c9
-rw-r--r--drivers/misc/pci_endpoint_test.c534
-rw-r--r--drivers/misc/sgi-xp/xp.h12
-rw-r--r--drivers/misc/sgi-xp/xp_main.c36
-rw-r--r--drivers/misc/sram-exec.c3
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c10
13 files changed, 596 insertions, 48 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 39d1acb27452..07bbd4cc1852 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -490,6 +490,14 @@ config ASPEED_LPC_CTRL
ioctl()s, the driver also provides a read/write interface to a BMC ram
region where the host LPC read/write region can be buffered.
+config PCI_ENDPOINT_TEST
+ depends on PCI
+ select CRC32
+ tristate "PCI Endpoint Test driver"
+ ---help---
+ Enable this configuration option to enable the host side test driver
+ for PCI Endpoint.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 4fb10af2ea1c..81ef3e67acc9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
index 5484301d57d9..3dc61ea7dc64 100644
--- a/drivers/misc/c2port/c2port-duramar2150.c
+++ b/drivers/misc/c2port/c2port-duramar2150.c
@@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void)
duramar2150_c2port_dev = c2port_device_register("uc",
&duramar2150_c2port_ops, NULL);
- if (!duramar2150_c2port_dev) {
- ret = -ENODEV;
+ if (IS_ERR(duramar2150_c2port_dev)) {
+ ret = PTR_ERR(duramar2150_c2port_dev);
goto free_region;
}
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 17b433f1ce23..0761271d68c5 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -159,11 +159,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
/* Do this outside the status_mutex to avoid a circular dependency with
* the locking in cxl_mmap_fault() */
- if (copy_from_user(&work, uwork,
- sizeof(struct cxl_ioctl_start_work))) {
- rc = -EFAULT;
- goto out;
- }
+ if (copy_from_user(&work, uwork, sizeof(work)))
+ return -EFAULT;
mutex_lock(&ctx->status_mutex);
if (ctx->status != OPENED) {
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 871a2f09c718..8d6ea9712dbd 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -1302,13 +1302,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
void cxl_native_release_psl_err_irq(struct cxl *adapter)
{
- if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
+ if (adapter->native->err_virq == 0 ||
+ adapter->native->err_virq !=
+ irq_find_mapping(NULL, adapter->native->err_hwirq))
return;
cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
cxl_unmap_irq(adapter->native->err_virq, adapter);
cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
kfree(adapter->irq_name);
+ adapter->native->err_virq = 0;
}
int cxl_native_register_serr_irq(struct cxl_afu *afu)
@@ -1346,13 +1349,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
void cxl_native_release_serr_irq(struct cxl_afu *afu)
{
- if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+ if (afu->serr_virq == 0 ||
+ afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
return;
cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
cxl_unmap_irq(afu->serr_virq, afu);
cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
kfree(afu->err_irq_name);
+ afu->serr_virq = 0;
}
int cxl_native_register_psl_irq(struct cxl_afu *afu)
@@ -1375,12 +1380,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
void cxl_native_release_psl_irq(struct cxl_afu *afu)
{
- if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
+ if (afu->native->psl_virq == 0 ||
+ afu->native->psl_virq !=
+ irq_find_mapping(NULL, afu->native->psl_hwirq))
return;
cxl_unmap_irq(afu->native->psl_virq, afu);
cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
kfree(afu->psl_irq_name);
+ afu->native->psl_virq = 0;
}
static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
diff --git a/drivers/misc/dummy-irq.c b/drivers/misc/dummy-irq.c
index acbbe0390be4..76a1015d5783 100644
--- a/drivers/misc/dummy-irq.c
+++ b/drivers/misc/dummy-irq.c
@@ -59,6 +59,6 @@ module_exit(dummy_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiri Kosina");
-module_param(irq, uint, 0444);
+module_param_hw(irq, uint, irq, 0444);
MODULE_PARM_DESC(irq, "The IRQ to register for");
MODULE_DESCRIPTION("Dummy IRQ handler driver");
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index d1928fdd0f43..07aad8576334 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -763,8 +763,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ u8 version = mei_me_cl_ver(cldev->me_cl);
- return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
+ return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
+ cldev->name, uuid, version);
}
static DEVICE_ATTR_RO(modalias);
diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c
index c2e29d7f0de8..a341938c7e2c 100644
--- a/drivers/misc/mic/vop/vop_main.c
+++ b/drivers/misc/mic/vop/vop_main.c
@@ -278,7 +278,7 @@ static void vop_del_vqs(struct virtio_device *dev)
static struct virtqueue *vop_find_vq(struct virtio_device *dev,
unsigned index,
void (*callback)(struct virtqueue *vq),
- const char *name)
+ const char *name, bool ctx)
{
struct _vop_vdev *vdev = to_vopvdev(dev);
struct vop_device *vpdev = vdev->vpdev;
@@ -314,6 +314,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
dev,
false,
+ ctx,
(void __force *)va, vop_notify, callback, name);
if (!vq) {
err = -ENOMEM;
@@ -374,7 +375,8 @@ unmap:
static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
struct virtqueue *vqs[],
vq_callback_t *callbacks[],
- const char * const names[], struct irq_affinity *desc)
+ const char * const names[], const bool *ctx,
+ struct irq_affinity *desc)
{
struct _vop_vdev *vdev = to_vopvdev(dev);
struct vop_device *vpdev = vdev->vpdev;
@@ -388,7 +390,8 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
for (i = 0; i < nvqs; ++i) {
dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
__func__, i, names[i]);
- vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i]);
+ vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+ ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
err = PTR_ERR(vqs[i]);
goto error;
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
new file mode 100644
index 000000000000..09c10f426b64
--- /dev/null
+++ b/drivers/misc/pci_endpoint_test.c
@@ -0,0 +1,534 @@
+/**
+ * Host side test driver to test endpoint functionality
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/pci_regs.h>
+
+#include <uapi/linux/pcitest.h>
+
+#define DRV_MODULE_NAME "pci-endpoint-test"
+
+#define PCI_ENDPOINT_TEST_MAGIC 0x0
+
+#define PCI_ENDPOINT_TEST_COMMAND 0x4
+#define COMMAND_RAISE_LEGACY_IRQ BIT(0)
+#define COMMAND_RAISE_MSI_IRQ BIT(1)
+#define MSI_NUMBER_SHIFT 2
+/* 6 bits for MSI number */
+#define COMMAND_READ BIT(8)
+#define COMMAND_WRITE BIT(9)
+#define COMMAND_COPY BIT(10)
+
+#define PCI_ENDPOINT_TEST_STATUS 0x8
+#define STATUS_READ_SUCCESS BIT(0)
+#define STATUS_READ_FAIL BIT(1)
+#define STATUS_WRITE_SUCCESS BIT(2)
+#define STATUS_WRITE_FAIL BIT(3)
+#define STATUS_COPY_SUCCESS BIT(4)
+#define STATUS_COPY_FAIL BIT(5)
+#define STATUS_IRQ_RAISED BIT(6)
+#define STATUS_SRC_ADDR_INVALID BIT(7)
+#define STATUS_DST_ADDR_INVALID BIT(8)
+
+#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc
+#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
+
+#define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14
+#define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18
+
+#define PCI_ENDPOINT_TEST_SIZE 0x1c
+#define PCI_ENDPOINT_TEST_CHECKSUM 0x20
+
+static DEFINE_IDA(pci_endpoint_test_ida);
+
+#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
+ miscdev)
+enum pci_barno {
+ BAR_0,
+ BAR_1,
+ BAR_2,
+ BAR_3,
+ BAR_4,
+ BAR_5,
+};
+
+struct pci_endpoint_test {
+ struct pci_dev *pdev;
+ void __iomem *base;
+ void __iomem *bar[6];
+ struct completion irq_raised;
+ int last_irq;
+ /* mutex to protect the ioctls */
+ struct mutex mutex;
+ struct miscdevice miscdev;
+};
+
+static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 };
+
+static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
+ u32 offset)
+{
+ return readl(test->base + offset);
+}
+
+static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
+ u32 offset, u32 value)
+{
+ 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)
+{
+ struct pci_endpoint_test *test = dev_id;
+ u32 reg;
+
+ reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
+ if (reg & STATUS_IRQ_RAISED) {
+ test->last_irq = irq;
+ complete(&test->irq_raised);
+ reg &= ~STATUS_IRQ_RAISED;
+ }
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
+ reg);
+
+ return IRQ_HANDLED;
+}
+
+static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
+ enum pci_barno barno)
+{
+ int j;
+ u32 val;
+ int size;
+
+ if (!test->bar[barno])
+ return false;
+
+ size = bar_size[barno];
+
+ for (j = 0; j < size; j += 4)
+ pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
+
+ for (j = 0; j < size; j += 4) {
+ val = pci_endpoint_test_bar_readl(test, barno, j);
+ if (val != 0xA0A0A0A0)
+ return false;
+ }
+
+ return true;
+}
+
+static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
+{
+ u32 val;
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+ COMMAND_RAISE_LEGACY_IRQ);
+ val = wait_for_completion_timeout(&test->irq_raised,
+ msecs_to_jiffies(1000));
+ if (!val)
+ return false;
+
+ return true;
+}
+
+static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
+ u8 msi_num)
+{
+ u32 val;
+ struct pci_dev *pdev = test->pdev;
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+ msi_num << MSI_NUMBER_SHIFT |
+ COMMAND_RAISE_MSI_IRQ);
+ val = wait_for_completion_timeout(&test->irq_raised,
+ msecs_to_jiffies(1000));
+ if (!val)
+ return false;
+
+ if (test->last_irq - pdev->irq == msi_num - 1)
+ return true;
+
+ return false;
+}
+
+static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
+{
+ bool ret = false;
+ void *src_addr;
+ void *dst_addr;
+ dma_addr_t src_phys_addr;
+ dma_addr_t dst_phys_addr;
+ struct pci_dev *pdev = test->pdev;
+ struct device *dev = &pdev->dev;
+ u32 src_crc32;
+ u32 dst_crc32;
+
+ src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
+ if (!src_addr) {
+ dev_err(dev, "failed to allocate source buffer\n");
+ ret = false;
+ goto err;
+ }
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
+ lower_32_bits(src_phys_addr));
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
+ upper_32_bits(src_phys_addr));
+
+ get_random_bytes(src_addr, size);
+ src_crc32 = crc32_le(~0, src_addr, size);
+
+ dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
+ if (!dst_addr) {
+ dev_err(dev, "failed to allocate destination address\n");
+ ret = false;
+ goto err_src_addr;
+ }
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
+ lower_32_bits(dst_phys_addr));
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
+ upper_32_bits(dst_phys_addr));
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
+ size);
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+ 1 << MSI_NUMBER_SHIFT | COMMAND_COPY);
+
+ wait_for_completion(&test->irq_raised);
+
+ dst_crc32 = crc32_le(~0, dst_addr, size);
+ if (dst_crc32 == src_crc32)
+ ret = true;
+
+ dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
+
+err_src_addr:
+ dma_free_coherent(dev, size, src_addr, src_phys_addr);
+
+err:
+ return ret;
+}
+
+static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
+{
+ bool ret = false;
+ u32 reg;
+ void *addr;
+ dma_addr_t phys_addr;
+ struct pci_dev *pdev = test->pdev;
+ struct device *dev = &pdev->dev;
+ u32 crc32;
+
+ addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
+ if (!addr) {
+ dev_err(dev, "failed to allocate address\n");
+ ret = false;
+ goto err;
+ }
+
+ get_random_bytes(addr, size);
+
+ crc32 = crc32_le(~0, addr, size);
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
+ crc32);
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
+ lower_32_bits(phys_addr));
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
+ upper_32_bits(phys_addr));
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+ 1 << MSI_NUMBER_SHIFT | COMMAND_READ);
+
+ wait_for_completion(&test->irq_raised);
+
+ reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
+ if (reg & STATUS_READ_SUCCESS)
+ ret = true;
+
+ dma_free_coherent(dev, size, addr, phys_addr);
+
+err:
+ return ret;
+}
+
+static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
+{
+ bool ret = false;
+ void *addr;
+ dma_addr_t phys_addr;
+ struct pci_dev *pdev = test->pdev;
+ struct device *dev = &pdev->dev;
+ u32 crc32;
+
+ addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
+ if (!addr) {
+ dev_err(dev, "failed to allocate destination address\n");
+ ret = false;
+ goto err;
+ }
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
+ lower_32_bits(phys_addr));
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
+ upper_32_bits(phys_addr));
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
+
+ pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+ 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE);
+
+ wait_for_completion(&test->irq_raised);
+
+ crc32 = crc32_le(~0, addr, size);
+ if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
+ ret = true;
+
+ dma_free_coherent(dev, size, addr, phys_addr);
+err:
+ return ret;
+}
+
+static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -EINVAL;
+ enum pci_barno bar;
+ struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
+
+ mutex_lock(&test->mutex);
+ switch (cmd) {
+ case PCITEST_BAR:
+ bar = arg;
+ if (bar < 0 || bar > 5)
+ goto ret;
+ ret = pci_endpoint_test_bar(test, bar);
+ break;
+ case PCITEST_LEGACY_IRQ:
+ ret = pci_endpoint_test_legacy_irq(test);
+ break;
+ case PCITEST_MSI:
+ ret = pci_endpoint_test_msi_irq(test, arg);
+ break;
+ case PCITEST_WRITE:
+ ret = pci_endpoint_test_write(test, arg);
+ break;
+ case PCITEST_READ:
+ ret = pci_endpoint_test_read(test, arg);
+ break;
+ case PCITEST_COPY:
+ ret = pci_endpoint_test_copy(test, arg);
+ break;
+ }
+
+ret:
+ mutex_unlock(&test->mutex);
+ return ret;
+}
+
+static const struct file_operations pci_endpoint_test_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pci_endpoint_test_ioctl,
+};
+
+static int pci_endpoint_test_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int i;
+ int err;
+ int irq;
+ int id;
+ char name[20];
+ enum pci_barno bar;
+ void __iomem *base;
+ struct device *dev = &pdev->dev;
+ struct pci_endpoint_test *test;
+ struct miscdevice *misc_device;
+
+ if (pci_is_bridge(pdev))
+ return -ENODEV;
+
+ test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
+ if (!test)
+ return -ENOMEM;
+
+ test->pdev = pdev;
+ init_completion(&test->irq_raised);
+ mutex_init(&test->mutex);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(dev, "Cannot enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRV_MODULE_NAME);
+ if (err) {
+ dev_err(dev, "Cannot obtain PCI resources\n");
+ goto err_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
+ if (irq < 0)
+ dev_err(dev, "failed to get MSI interrupts\n");
+
+ err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
+ IRQF_SHARED, DRV_MODULE_NAME, test);
+ if (err) {
+ dev_err(dev, "failed to request IRQ %d\n", pdev->irq);
+ goto err_disable_msi;
+ }
+
+ for (i = 1; i < irq; i++) {
+ err = devm_request_irq(dev, pdev->irq + i,
+ pci_endpoint_test_irqhandler,
+ IRQF_SHARED, DRV_MODULE_NAME, test);
+ if (err)
+ dev_err(dev, "failed to request IRQ %d for MSI %d\n",
+ pdev->irq + i, i + 1);
+ }
+
+ for (bar = BAR_0; bar <= BAR_5; bar++) {
+ base = pci_ioremap_bar(pdev, bar);
+ if (!base) {
+ dev_err(dev, "failed to read BAR%d\n", bar);
+ WARN_ON(bar == BAR_0);
+ }
+ test->bar[bar] = base;
+ }
+
+ test->base = test->bar[0];
+ if (!test->base) {
+ dev_err(dev, "Cannot perform PCI test without BAR0\n");
+ goto err_iounmap;
+ }
+
+ pci_set_drvdata(pdev, test);
+
+ id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ dev_err(dev, "unable to get id\n");
+ goto err_iounmap;
+ }
+
+ snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
+ misc_device = &test->miscdev;
+ misc_device->minor = MISC_DYNAMIC_MINOR;
+ misc_device->name = name;
+ misc_device->fops = &pci_endpoint_test_fops,
+
+ err = misc_register(misc_device);
+ if (err) {
+ dev_err(dev, "failed to register device\n");
+ goto err_ida_remove;
+ }
+
+ return 0;
+
+err_ida_remove:
+ ida_simple_remove(&pci_endpoint_test_ida, id);
+
+err_iounmap:
+ for (bar = BAR_0; bar <= BAR_5; bar++) {
+ if (test->bar[bar])
+ pci_iounmap(pdev, test->bar[bar]);
+ }
+
+err_disable_msi:
+ pci_disable_msi(pdev);
+ pci_release_regions(pdev);
+
+err_disable_pdev:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void pci_endpoint_test_remove(struct pci_dev *pdev)
+{
+ int id;
+ enum pci_barno bar;
+ struct pci_endpoint_test *test = pci_get_drvdata(pdev);
+ struct miscdevice *misc_device = &test->miscdev;
+
+ if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
+ return;
+
+ misc_deregister(&test->miscdev);
+ ida_simple_remove(&pci_endpoint_test_ida, id);
+ for (bar = BAR_0; bar <= BAR_5; bar++) {
+ if (test->bar[bar])
+ pci_iounmap(pdev, test->bar[bar]);
+ }
+ pci_disable_msi(pdev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+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_DRA72x) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
+
+static struct pci_driver pci_endpoint_test_driver = {
+ .name = DRV_MODULE_NAME,
+ .id_table = pci_endpoint_test_tbl,
+ .probe = pci_endpoint_test_probe,
+ .remove = pci_endpoint_test_remove,
+};
+module_pci_driver(pci_endpoint_test_driver);
+
+MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index c862cd4583cc..b8069eec18cb 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -309,6 +309,9 @@ static inline enum xp_retval
xpc_send(short partid, int ch_number, u32 flags, void *payload,
u16 payload_size)
{
+ if (!xpc_interface.send)
+ return xpNotLoaded;
+
return xpc_interface.send(partid, ch_number, flags, payload,
payload_size);
}
@@ -317,6 +320,9 @@ static inline enum xp_retval
xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
u16 payload_size, xpc_notify_func func, void *key)
{
+ if (!xpc_interface.send_notify)
+ return xpNotLoaded;
+
return xpc_interface.send_notify(partid, ch_number, flags, payload,
payload_size, func, key);
}
@@ -324,12 +330,16 @@ xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
static inline void
xpc_received(short partid, int ch_number, void *payload)
{
- return xpc_interface.received(partid, ch_number, payload);
+ if (xpc_interface.received)
+ xpc_interface.received(partid, ch_number, payload);
}
static inline enum xp_retval
xpc_partid_to_nasids(short partid, void *nasids)
{
+ if (!xpc_interface.partid_to_nasids)
+ return xpNotLoaded;
+
return xpc_interface.partid_to_nasids(partid, nasids);
}
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 01be66d02ca8..6d7f557fd1c1 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -69,23 +69,9 @@ struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
EXPORT_SYMBOL_GPL(xpc_registrations);
/*
- * Initialize the XPC interface to indicate that XPC isn't loaded.
+ * Initialize the XPC interface to NULL to indicate that XPC isn't loaded.
*/
-static enum xp_retval
-xpc_notloaded(void)
-{
- return xpNotLoaded;
-}
-
-struct xpc_interface xpc_interface = {
- (void (*)(int))xpc_notloaded,
- (void (*)(int))xpc_notloaded,
- (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
- (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
- void *))xpc_notloaded,
- (void (*)(short, int, void *))xpc_notloaded,
- (enum xp_retval(*)(short, void *))xpc_notloaded
-};
+struct xpc_interface xpc_interface = { };
EXPORT_SYMBOL_GPL(xpc_interface);
/*
@@ -115,17 +101,7 @@ EXPORT_SYMBOL_GPL(xpc_set_interface);
void
xpc_clear_interface(void)
{
- xpc_interface.connect = (void (*)(int))xpc_notloaded;
- xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
- xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
- xpc_notloaded;
- xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
- u16, xpc_notify_func,
- void *))xpc_notloaded;
- xpc_interface.received = (void (*)(short, int, void *))
- xpc_notloaded;
- xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
- xpc_notloaded;
+ memset(&xpc_interface, 0, sizeof(xpc_interface));
}
EXPORT_SYMBOL_GPL(xpc_clear_interface);
@@ -188,7 +164,8 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
mutex_unlock(&registration->mutex);
- xpc_interface.connect(ch_number);
+ if (xpc_interface.connect)
+ xpc_interface.connect(ch_number);
return xpSuccess;
}
@@ -237,7 +214,8 @@ xpc_disconnect(int ch_number)
registration->assigned_limit = 0;
registration->idle_limit = 0;
- xpc_interface.disconnect(ch_number);
+ if (xpc_interface.disconnect)
+ xpc_interface.disconnect(ch_number);
mutex_unlock(&registration->mutex);
diff --git a/drivers/misc/sram-exec.c b/drivers/misc/sram-exec.c
index ac522417c462..3d528a13b8fc 100644
--- a/drivers/misc/sram-exec.c
+++ b/drivers/misc/sram-exec.c
@@ -16,9 +16,10 @@
#include <linux/device.h>
#include <linux/genalloc.h>
+#include <linux/mm.h>
#include <linux/sram.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
#include "sram.h"
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 498c0854305f..06c4974ee8dd 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -298,8 +298,11 @@ static void *qp_alloc_queue(u64 size, u32 flags)
size_t pas_size;
size_t vas_size;
size_t queue_size = sizeof(*queue) + sizeof(*queue->kernel_if);
- const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+ u64 num_pages;
+ if (size > SIZE_MAX - PAGE_SIZE)
+ return NULL;
+ num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
if (num_pages >
(SIZE_MAX - queue_size) /
(sizeof(*queue->kernel_if->u.g.pas) +
@@ -624,9 +627,12 @@ static struct vmci_queue *qp_host_alloc_queue(u64 size)
{
struct vmci_queue *queue;
size_t queue_page_size;
- const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+ u64 num_pages;
const size_t queue_size = sizeof(*queue) + sizeof(*(queue->kernel_if));
+ if (size > SIZE_MAX - PAGE_SIZE)
+ return NULL;
+ num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
if (num_pages > (SIZE_MAX - queue_size) /
sizeof(*queue->kernel_if->u.h.page))
return NULL;
OpenPOWER on IntegriCloud