16b1baefeSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21aa3f2b0SRandy Dunlap /*
32c156ac7SKishon Vijay Abraham I * Host side test driver to test endpoint functionality
42c156ac7SKishon Vijay Abraham I *
52c156ac7SKishon Vijay Abraham I * Copyright (C) 2017 Texas Instruments
62c156ac7SKishon Vijay Abraham I * Author: Kishon Vijay Abraham I <kishon@ti.com>
72c156ac7SKishon Vijay Abraham I */
82c156ac7SKishon Vijay Abraham I
92c156ac7SKishon Vijay Abraham I #include <linux/crc32.h>
102c156ac7SKishon Vijay Abraham I #include <linux/delay.h>
112c156ac7SKishon Vijay Abraham I #include <linux/fs.h>
122c156ac7SKishon Vijay Abraham I #include <linux/io.h>
132c156ac7SKishon Vijay Abraham I #include <linux/interrupt.h>
142c156ac7SKishon Vijay Abraham I #include <linux/irq.h>
152c156ac7SKishon Vijay Abraham I #include <linux/miscdevice.h>
162c156ac7SKishon Vijay Abraham I #include <linux/module.h>
172c156ac7SKishon Vijay Abraham I #include <linux/mutex.h>
182c156ac7SKishon Vijay Abraham I #include <linux/random.h>
192c156ac7SKishon Vijay Abraham I #include <linux/slab.h>
20cf376b4bSKishon Vijay Abraham I #include <linux/uaccess.h>
212c156ac7SKishon Vijay Abraham I #include <linux/pci.h>
222c156ac7SKishon Vijay Abraham I #include <linux/pci_ids.h>
232c156ac7SKishon Vijay Abraham I
242c156ac7SKishon Vijay Abraham I #include <linux/pci_regs.h>
252c156ac7SKishon Vijay Abraham I
262c156ac7SKishon Vijay Abraham I #include <uapi/linux/pcitest.h>
272c156ac7SKishon Vijay Abraham I
282c156ac7SKishon Vijay Abraham I #define DRV_MODULE_NAME "pci-endpoint-test"
292c156ac7SKishon Vijay Abraham I
30e0332712SGustavo Pimentel #define IRQ_TYPE_UNDEFINED -1
31e8817de7SGustavo Pimentel #define IRQ_TYPE_LEGACY 0
32e8817de7SGustavo Pimentel #define IRQ_TYPE_MSI 1
33c2e00e31SGustavo Pimentel #define IRQ_TYPE_MSIX 2
34e8817de7SGustavo Pimentel
352c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_MAGIC 0x0
362c156ac7SKishon Vijay Abraham I
372c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_COMMAND 0x4
382c156ac7SKishon Vijay Abraham I #define COMMAND_RAISE_LEGACY_IRQ BIT(0)
392c156ac7SKishon Vijay Abraham I #define COMMAND_RAISE_MSI_IRQ BIT(1)
40c2e00e31SGustavo Pimentel #define COMMAND_RAISE_MSIX_IRQ BIT(2)
41e8817de7SGustavo Pimentel #define COMMAND_READ BIT(3)
42e8817de7SGustavo Pimentel #define COMMAND_WRITE BIT(4)
43e8817de7SGustavo Pimentel #define COMMAND_COPY BIT(5)
442c156ac7SKishon Vijay Abraham I
452c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_STATUS 0x8
462c156ac7SKishon Vijay Abraham I #define STATUS_READ_SUCCESS BIT(0)
472c156ac7SKishon Vijay Abraham I #define STATUS_READ_FAIL BIT(1)
482c156ac7SKishon Vijay Abraham I #define STATUS_WRITE_SUCCESS BIT(2)
492c156ac7SKishon Vijay Abraham I #define STATUS_WRITE_FAIL BIT(3)
502c156ac7SKishon Vijay Abraham I #define STATUS_COPY_SUCCESS BIT(4)
512c156ac7SKishon Vijay Abraham I #define STATUS_COPY_FAIL BIT(5)
522c156ac7SKishon Vijay Abraham I #define STATUS_IRQ_RAISED BIT(6)
532c156ac7SKishon Vijay Abraham I #define STATUS_SRC_ADDR_INVALID BIT(7)
542c156ac7SKishon Vijay Abraham I #define STATUS_DST_ADDR_INVALID BIT(8)
552c156ac7SKishon Vijay Abraham I
56e8817de7SGustavo Pimentel #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c
572c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
582c156ac7SKishon Vijay Abraham I
592c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14
602c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18
612c156ac7SKishon Vijay Abraham I
622c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_SIZE 0x1c
632c156ac7SKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_CHECKSUM 0x20
642c156ac7SKishon Vijay Abraham I
65e8817de7SGustavo Pimentel #define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24
66e8817de7SGustavo Pimentel #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28
67e8817de7SGustavo Pimentel
68cf376b4bSKishon Vijay Abraham I #define PCI_ENDPOINT_TEST_FLAGS 0x2c
69cf376b4bSKishon Vijay Abraham I #define FLAG_USE_DMA BIT(0)
70cf376b4bSKishon Vijay Abraham I
715bb04b19SKishon Vijay Abraham I #define PCI_DEVICE_ID_TI_AM654 0xb00c
727c52009dSKishon Vijay Abraham I #define PCI_DEVICE_ID_TI_J7200 0xb00f
737c52009dSKishon Vijay Abraham I #define PCI_DEVICE_ID_TI_AM64 0xb010
74be3e3ab5SSiddharth Vadapalli #define PCI_DEVICE_ID_TI_J721S2 0xb013
756b8ab421SXiaowei Bao #define PCI_DEVICE_ID_LS1088A 0x80c0
7601ea5edeSRichard Zhu #define PCI_DEVICE_ID_IMX8 0x0808
775bb04b19SKishon Vijay Abraham I
785bb04b19SKishon Vijay Abraham I #define is_am654_pci_dev(pdev) \
795bb04b19SKishon Vijay Abraham I ((pdev)->device == PCI_DEVICE_ID_TI_AM654)
805bb04b19SKishon Vijay Abraham I
81cfb824ddSLad Prabhakar #define PCI_DEVICE_ID_RENESAS_R8A774A1 0x0028
82cfb824ddSLad Prabhakar #define PCI_DEVICE_ID_RENESAS_R8A774B1 0x002b
83b03025c5SLad Prabhakar #define PCI_DEVICE_ID_RENESAS_R8A774C0 0x002d
84a63c5f3dSLad Prabhakar #define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025
85*f22145b5SYoshihiro Shimoda #define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031
86b03025c5SLad Prabhakar
872c156ac7SKishon Vijay Abraham I static DEFINE_IDA(pci_endpoint_test_ida);
882c156ac7SKishon Vijay Abraham I
892c156ac7SKishon Vijay Abraham I #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
902c156ac7SKishon Vijay Abraham I miscdev)
910c8a5f9dSKishon Vijay Abraham I
920c8a5f9dSKishon Vijay Abraham I static bool no_msi;
930c8a5f9dSKishon Vijay Abraham I module_param(no_msi, bool, 0444);
940c8a5f9dSKishon Vijay Abraham I MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
950c8a5f9dSKishon Vijay Abraham I
969133e394SGustavo Pimentel static int irq_type = IRQ_TYPE_MSI;
979133e394SGustavo Pimentel module_param(irq_type, int, 0444);
98c2e00e31SGustavo Pimentel MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)");
999133e394SGustavo Pimentel
1002c156ac7SKishon Vijay Abraham I enum pci_barno {
1012c156ac7SKishon Vijay Abraham I BAR_0,
1022c156ac7SKishon Vijay Abraham I BAR_1,
1032c156ac7SKishon Vijay Abraham I BAR_2,
1042c156ac7SKishon Vijay Abraham I BAR_3,
1052c156ac7SKishon Vijay Abraham I BAR_4,
1062c156ac7SKishon Vijay Abraham I BAR_5,
1072c156ac7SKishon Vijay Abraham I };
1082c156ac7SKishon Vijay Abraham I
1092c156ac7SKishon Vijay Abraham I struct pci_endpoint_test {
1102c156ac7SKishon Vijay Abraham I struct pci_dev *pdev;
1112c156ac7SKishon Vijay Abraham I void __iomem *base;
112c9c13ba4SDenis Efremov void __iomem *bar[PCI_STD_NUM_BARS];
1132c156ac7SKishon Vijay Abraham I struct completion irq_raised;
1142c156ac7SKishon Vijay Abraham I int last_irq;
115b7636e81SKishon Vijay Abraham I int num_irqs;
116b2ba9225SKishon Vijay Abraham I int irq_type;
1172c156ac7SKishon Vijay Abraham I /* mutex to protect the ioctls */
1182c156ac7SKishon Vijay Abraham I struct mutex mutex;
1192c156ac7SKishon Vijay Abraham I struct miscdevice miscdev;
120834b9051SKishon Vijay Abraham I enum pci_barno test_reg_bar;
12113107c60SKishon Vijay Abraham I size_t alignment;
122c2be14abSKishon Vijay Abraham I const char *name;
1232c156ac7SKishon Vijay Abraham I };
1242c156ac7SKishon Vijay Abraham I
125834b9051SKishon Vijay Abraham I struct pci_endpoint_test_data {
126834b9051SKishon Vijay Abraham I enum pci_barno test_reg_bar;
12713107c60SKishon Vijay Abraham I size_t alignment;
1289133e394SGustavo Pimentel int irq_type;
129834b9051SKishon Vijay Abraham I };
130834b9051SKishon Vijay Abraham I
pci_endpoint_test_readl(struct pci_endpoint_test * test,u32 offset)1312c156ac7SKishon Vijay Abraham I static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
1322c156ac7SKishon Vijay Abraham I u32 offset)
1332c156ac7SKishon Vijay Abraham I {
1342c156ac7SKishon Vijay Abraham I return readl(test->base + offset);
1352c156ac7SKishon Vijay Abraham I }
1362c156ac7SKishon Vijay Abraham I
pci_endpoint_test_writel(struct pci_endpoint_test * test,u32 offset,u32 value)1372c156ac7SKishon Vijay Abraham I static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
1382c156ac7SKishon Vijay Abraham I u32 offset, u32 value)
1392c156ac7SKishon Vijay Abraham I {
1402c156ac7SKishon Vijay Abraham I writel(value, test->base + offset);
1412c156ac7SKishon Vijay Abraham I }
1422c156ac7SKishon Vijay Abraham I
pci_endpoint_test_bar_readl(struct pci_endpoint_test * test,int bar,int offset)1432c156ac7SKishon Vijay Abraham I static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
1442c156ac7SKishon Vijay Abraham I int bar, int offset)
1452c156ac7SKishon Vijay Abraham I {
1462c156ac7SKishon Vijay Abraham I return readl(test->bar[bar] + offset);
1472c156ac7SKishon Vijay Abraham I }
1482c156ac7SKishon Vijay Abraham I
pci_endpoint_test_bar_writel(struct pci_endpoint_test * test,int bar,u32 offset,u32 value)1492c156ac7SKishon Vijay Abraham I static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
1502c156ac7SKishon Vijay Abraham I int bar, u32 offset, u32 value)
1512c156ac7SKishon Vijay Abraham I {
1522c156ac7SKishon Vijay Abraham I writel(value, test->bar[bar] + offset);
1532c156ac7SKishon Vijay Abraham I }
1542c156ac7SKishon Vijay Abraham I
pci_endpoint_test_irqhandler(int irq,void * dev_id)1552c156ac7SKishon Vijay Abraham I static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
1562c156ac7SKishon Vijay Abraham I {
1572c156ac7SKishon Vijay Abraham I struct pci_endpoint_test *test = dev_id;
1582c156ac7SKishon Vijay Abraham I u32 reg;
1592c156ac7SKishon Vijay Abraham I
1602c156ac7SKishon Vijay Abraham I reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
1612c156ac7SKishon Vijay Abraham I if (reg & STATUS_IRQ_RAISED) {
1622c156ac7SKishon Vijay Abraham I test->last_irq = irq;
1632c156ac7SKishon Vijay Abraham I complete(&test->irq_raised);
1642c156ac7SKishon Vijay Abraham I }
1652c156ac7SKishon Vijay Abraham I
1662c156ac7SKishon Vijay Abraham I return IRQ_HANDLED;
1672c156ac7SKishon Vijay Abraham I }
1682c156ac7SKishon Vijay Abraham I
pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test * test)169e0332712SGustavo Pimentel static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
170e0332712SGustavo Pimentel {
171e0332712SGustavo Pimentel struct pci_dev *pdev = test->pdev;
172e0332712SGustavo Pimentel
173e0332712SGustavo Pimentel pci_free_irq_vectors(pdev);
174b2ba9225SKishon Vijay Abraham I test->irq_type = IRQ_TYPE_UNDEFINED;
175e0332712SGustavo Pimentel }
176e0332712SGustavo Pimentel
pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test * test,int type)177e0332712SGustavo Pimentel static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
178e0332712SGustavo Pimentel int type)
179e0332712SGustavo Pimentel {
180e0332712SGustavo Pimentel int irq = -1;
181e0332712SGustavo Pimentel struct pci_dev *pdev = test->pdev;
182e0332712SGustavo Pimentel struct device *dev = &pdev->dev;
183e0332712SGustavo Pimentel bool res = true;
184e0332712SGustavo Pimentel
185e0332712SGustavo Pimentel switch (type) {
186e0332712SGustavo Pimentel case IRQ_TYPE_LEGACY:
187e0332712SGustavo Pimentel irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY);
188e0332712SGustavo Pimentel if (irq < 0)
189e0332712SGustavo Pimentel dev_err(dev, "Failed to get Legacy interrupt\n");
190e0332712SGustavo Pimentel break;
191e0332712SGustavo Pimentel case IRQ_TYPE_MSI:
192e0332712SGustavo Pimentel irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
193e0332712SGustavo Pimentel if (irq < 0)
194e0332712SGustavo Pimentel dev_err(dev, "Failed to get MSI interrupts\n");
195e0332712SGustavo Pimentel break;
196e0332712SGustavo Pimentel case IRQ_TYPE_MSIX:
197e0332712SGustavo Pimentel irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX);
198e0332712SGustavo Pimentel if (irq < 0)
199e0332712SGustavo Pimentel dev_err(dev, "Failed to get MSI-X interrupts\n");
200e0332712SGustavo Pimentel break;
201e0332712SGustavo Pimentel default:
202e0332712SGustavo Pimentel dev_err(dev, "Invalid IRQ type selected\n");
203e0332712SGustavo Pimentel }
204e0332712SGustavo Pimentel
205e0332712SGustavo Pimentel if (irq < 0) {
206e0332712SGustavo Pimentel irq = 0;
207e0332712SGustavo Pimentel res = false;
208e0332712SGustavo Pimentel }
209b2ba9225SKishon Vijay Abraham I
210b2ba9225SKishon Vijay Abraham I test->irq_type = type;
211e0332712SGustavo Pimentel test->num_irqs = irq;
212e0332712SGustavo Pimentel
213e0332712SGustavo Pimentel return res;
214e0332712SGustavo Pimentel }
215e0332712SGustavo Pimentel
pci_endpoint_test_release_irq(struct pci_endpoint_test * test)216e0332712SGustavo Pimentel static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test)
217e0332712SGustavo Pimentel {
218e0332712SGustavo Pimentel int i;
219e0332712SGustavo Pimentel struct pci_dev *pdev = test->pdev;
220e0332712SGustavo Pimentel struct device *dev = &pdev->dev;
221e0332712SGustavo Pimentel
222e0332712SGustavo Pimentel for (i = 0; i < test->num_irqs; i++)
223e0332712SGustavo Pimentel devm_free_irq(dev, pci_irq_vector(pdev, i), test);
224e0332712SGustavo Pimentel
225e0332712SGustavo Pimentel test->num_irqs = 0;
226e0332712SGustavo Pimentel }
227e0332712SGustavo Pimentel
pci_endpoint_test_request_irq(struct pci_endpoint_test * test)228e0332712SGustavo Pimentel static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
229e0332712SGustavo Pimentel {
230e0332712SGustavo Pimentel int i;
231e0332712SGustavo Pimentel int err;
232e0332712SGustavo Pimentel struct pci_dev *pdev = test->pdev;
233e0332712SGustavo Pimentel struct device *dev = &pdev->dev;
234e0332712SGustavo Pimentel
235e0332712SGustavo Pimentel for (i = 0; i < test->num_irqs; i++) {
236e0332712SGustavo Pimentel err = devm_request_irq(dev, pci_irq_vector(pdev, i),
237e0332712SGustavo Pimentel pci_endpoint_test_irqhandler,
238c2be14abSKishon Vijay Abraham I IRQF_SHARED, test->name, test);
239e0332712SGustavo Pimentel if (err)
240e0332712SGustavo Pimentel goto fail;
241e0332712SGustavo Pimentel }
242e0332712SGustavo Pimentel
243e0332712SGustavo Pimentel return true;
244e0332712SGustavo Pimentel
245e0332712SGustavo Pimentel fail:
246e0332712SGustavo Pimentel switch (irq_type) {
247e0332712SGustavo Pimentel case IRQ_TYPE_LEGACY:
248e0332712SGustavo Pimentel dev_err(dev, "Failed to request IRQ %d for Legacy\n",
249e0332712SGustavo Pimentel pci_irq_vector(pdev, i));
250e0332712SGustavo Pimentel break;
251e0332712SGustavo Pimentel case IRQ_TYPE_MSI:
252e0332712SGustavo Pimentel dev_err(dev, "Failed to request IRQ %d for MSI %d\n",
253e0332712SGustavo Pimentel pci_irq_vector(pdev, i),
254e0332712SGustavo Pimentel i + 1);
255e0332712SGustavo Pimentel break;
256e0332712SGustavo Pimentel case IRQ_TYPE_MSIX:
257e0332712SGustavo Pimentel dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n",
258e0332712SGustavo Pimentel pci_irq_vector(pdev, i),
259e0332712SGustavo Pimentel i + 1);
260e0332712SGustavo Pimentel break;
261e0332712SGustavo Pimentel }
262e0332712SGustavo Pimentel
263e0332712SGustavo Pimentel return false;
264e0332712SGustavo Pimentel }
265e0332712SGustavo Pimentel
pci_endpoint_test_bar(struct pci_endpoint_test * test,enum pci_barno barno)2662c156ac7SKishon Vijay Abraham I static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
2672c156ac7SKishon Vijay Abraham I enum pci_barno barno)
2682c156ac7SKishon Vijay Abraham I {
2692c156ac7SKishon Vijay Abraham I int j;
2702c156ac7SKishon Vijay Abraham I u32 val;
2712c156ac7SKishon Vijay Abraham I int size;
272cda370ecSKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
2732c156ac7SKishon Vijay Abraham I
2742c156ac7SKishon Vijay Abraham I if (!test->bar[barno])
2752c156ac7SKishon Vijay Abraham I return false;
2762c156ac7SKishon Vijay Abraham I
277cda370ecSKishon Vijay Abraham I size = pci_resource_len(pdev, barno);
2782c156ac7SKishon Vijay Abraham I
279834b9051SKishon Vijay Abraham I if (barno == test->test_reg_bar)
280834b9051SKishon Vijay Abraham I size = 0x4;
281834b9051SKishon Vijay Abraham I
2822c156ac7SKishon Vijay Abraham I for (j = 0; j < size; j += 4)
2832c156ac7SKishon Vijay Abraham I pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
2842c156ac7SKishon Vijay Abraham I
2852c156ac7SKishon Vijay Abraham I for (j = 0; j < size; j += 4) {
2862c156ac7SKishon Vijay Abraham I val = pci_endpoint_test_bar_readl(test, barno, j);
2872c156ac7SKishon Vijay Abraham I if (val != 0xA0A0A0A0)
2882c156ac7SKishon Vijay Abraham I return false;
2892c156ac7SKishon Vijay Abraham I }
2902c156ac7SKishon Vijay Abraham I
2912c156ac7SKishon Vijay Abraham I return true;
2922c156ac7SKishon Vijay Abraham I }
2932c156ac7SKishon Vijay Abraham I
pci_endpoint_test_legacy_irq(struct pci_endpoint_test * test)2942c156ac7SKishon Vijay Abraham I static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
2952c156ac7SKishon Vijay Abraham I {
2962c156ac7SKishon Vijay Abraham I u32 val;
2972c156ac7SKishon Vijay Abraham I
298e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
299e8817de7SGustavo Pimentel IRQ_TYPE_LEGACY);
300e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0);
3012c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
3022c156ac7SKishon Vijay Abraham I COMMAND_RAISE_LEGACY_IRQ);
3032c156ac7SKishon Vijay Abraham I val = wait_for_completion_timeout(&test->irq_raised,
3042c156ac7SKishon Vijay Abraham I msecs_to_jiffies(1000));
3052c156ac7SKishon Vijay Abraham I if (!val)
3062c156ac7SKishon Vijay Abraham I return false;
3072c156ac7SKishon Vijay Abraham I
3082c156ac7SKishon Vijay Abraham I return true;
3092c156ac7SKishon Vijay Abraham I }
3102c156ac7SKishon Vijay Abraham I
pci_endpoint_test_msi_irq(struct pci_endpoint_test * test,u16 msi_num,bool msix)3112c156ac7SKishon Vijay Abraham I static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
312c2e00e31SGustavo Pimentel u16 msi_num, bool msix)
3132c156ac7SKishon Vijay Abraham I {
3142c156ac7SKishon Vijay Abraham I u32 val;
3152c156ac7SKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
3162c156ac7SKishon Vijay Abraham I
317e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
3184c50f933SDamien Le Moal msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI);
319e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num);
3202c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
3214c50f933SDamien Le Moal msix ? COMMAND_RAISE_MSIX_IRQ :
3224c50f933SDamien Le Moal COMMAND_RAISE_MSI_IRQ);
3232c156ac7SKishon Vijay Abraham I val = wait_for_completion_timeout(&test->irq_raised,
3242c156ac7SKishon Vijay Abraham I msecs_to_jiffies(1000));
3252c156ac7SKishon Vijay Abraham I if (!val)
3262c156ac7SKishon Vijay Abraham I return false;
3272c156ac7SKishon Vijay Abraham I
3284c50f933SDamien Le Moal return pci_irq_vector(pdev, msi_num - 1) == test->last_irq;
3292c156ac7SKishon Vijay Abraham I }
3302c156ac7SKishon Vijay Abraham I
pci_endpoint_test_validate_xfer_params(struct device * dev,struct pci_endpoint_test_xfer_param * param,size_t alignment)3313e42deaaSShunsuke Mie static int pci_endpoint_test_validate_xfer_params(struct device *dev,
3323e42deaaSShunsuke Mie struct pci_endpoint_test_xfer_param *param, size_t alignment)
3333e42deaaSShunsuke Mie {
3348e30538eSShunsuke Mie if (!param->size) {
3358e30538eSShunsuke Mie dev_dbg(dev, "Data size is zero\n");
3368e30538eSShunsuke Mie return -EINVAL;
3378e30538eSShunsuke Mie }
3388e30538eSShunsuke Mie
3393e42deaaSShunsuke Mie if (param->size > SIZE_MAX - alignment) {
3403e42deaaSShunsuke Mie dev_dbg(dev, "Maximum transfer data size exceeded\n");
3413e42deaaSShunsuke Mie return -EINVAL;
3423e42deaaSShunsuke Mie }
3433e42deaaSShunsuke Mie
3443e42deaaSShunsuke Mie return 0;
3453e42deaaSShunsuke Mie }
3463e42deaaSShunsuke Mie
pci_endpoint_test_copy(struct pci_endpoint_test * test,unsigned long arg)347cf376b4bSKishon Vijay Abraham I static bool pci_endpoint_test_copy(struct pci_endpoint_test *test,
348cf376b4bSKishon Vijay Abraham I unsigned long arg)
3492c156ac7SKishon Vijay Abraham I {
350cf376b4bSKishon Vijay Abraham I struct pci_endpoint_test_xfer_param param;
3512c156ac7SKishon Vijay Abraham I bool ret = false;
3522c156ac7SKishon Vijay Abraham I void *src_addr;
3532c156ac7SKishon Vijay Abraham I void *dst_addr;
354cf376b4bSKishon Vijay Abraham I u32 flags = 0;
355cf376b4bSKishon Vijay Abraham I bool use_dma;
356cf376b4bSKishon Vijay Abraham I size_t size;
3572c156ac7SKishon Vijay Abraham I dma_addr_t src_phys_addr;
3582c156ac7SKishon Vijay Abraham I dma_addr_t dst_phys_addr;
3592c156ac7SKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
3602c156ac7SKishon Vijay Abraham I struct device *dev = &pdev->dev;
36113107c60SKishon Vijay Abraham I void *orig_src_addr;
36213107c60SKishon Vijay Abraham I dma_addr_t orig_src_phys_addr;
36313107c60SKishon Vijay Abraham I void *orig_dst_addr;
36413107c60SKishon Vijay Abraham I dma_addr_t orig_dst_phys_addr;
36513107c60SKishon Vijay Abraham I size_t offset;
36613107c60SKishon Vijay Abraham I size_t alignment = test->alignment;
367b2ba9225SKishon Vijay Abraham I int irq_type = test->irq_type;
3682c156ac7SKishon Vijay Abraham I u32 src_crc32;
3692c156ac7SKishon Vijay Abraham I u32 dst_crc32;
370cf376b4bSKishon Vijay Abraham I int err;
3712c156ac7SKishon Vijay Abraham I
372cf376b4bSKishon Vijay Abraham I err = copy_from_user(¶m, (void __user *)arg, sizeof(param));
373cf376b4bSKishon Vijay Abraham I if (err) {
374cf376b4bSKishon Vijay Abraham I dev_err(dev, "Failed to get transfer param\n");
375cf376b4bSKishon Vijay Abraham I return false;
376cf376b4bSKishon Vijay Abraham I }
377cf376b4bSKishon Vijay Abraham I
3783e42deaaSShunsuke Mie err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment);
3793e42deaaSShunsuke Mie if (err)
3803e42deaaSShunsuke Mie return false;
3813e42deaaSShunsuke Mie
382cf376b4bSKishon Vijay Abraham I size = param.size;
383343dc693SDan Carpenter
384cf376b4bSKishon Vijay Abraham I use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA);
385cf376b4bSKishon Vijay Abraham I if (use_dma)
386cf376b4bSKishon Vijay Abraham I flags |= FLAG_USE_DMA;
387cf376b4bSKishon Vijay Abraham I
388e0332712SGustavo Pimentel if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
389e0332712SGustavo Pimentel dev_err(dev, "Invalid IRQ type option\n");
390e0332712SGustavo Pimentel goto err;
391e0332712SGustavo Pimentel }
392e0332712SGustavo Pimentel
3930a121f9bSKishon Vijay Abraham I orig_src_addr = kzalloc(size + alignment, GFP_KERNEL);
39413107c60SKishon Vijay Abraham I if (!orig_src_addr) {
3950e52ea61SGustavo Pimentel dev_err(dev, "Failed to allocate source buffer\n");
3962c156ac7SKishon Vijay Abraham I ret = false;
3972c156ac7SKishon Vijay Abraham I goto err;
3982c156ac7SKishon Vijay Abraham I }
3992c156ac7SKishon Vijay Abraham I
4000a121f9bSKishon Vijay Abraham I get_random_bytes(orig_src_addr, size + alignment);
4010a121f9bSKishon Vijay Abraham I orig_src_phys_addr = dma_map_single(dev, orig_src_addr,
4020a121f9bSKishon Vijay Abraham I size + alignment, DMA_TO_DEVICE);
4030a121f9bSKishon Vijay Abraham I if (dma_mapping_error(dev, orig_src_phys_addr)) {
4040a121f9bSKishon Vijay Abraham I dev_err(dev, "failed to map source buffer address\n");
4050a121f9bSKishon Vijay Abraham I ret = false;
4060a121f9bSKishon Vijay Abraham I goto err_src_phys_addr;
4070a121f9bSKishon Vijay Abraham I }
4080a121f9bSKishon Vijay Abraham I
40913107c60SKishon Vijay Abraham I if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
41013107c60SKishon Vijay Abraham I src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
41113107c60SKishon Vijay Abraham I offset = src_phys_addr - orig_src_phys_addr;
41213107c60SKishon Vijay Abraham I src_addr = orig_src_addr + offset;
41313107c60SKishon Vijay Abraham I } else {
41413107c60SKishon Vijay Abraham I src_phys_addr = orig_src_phys_addr;
41513107c60SKishon Vijay Abraham I src_addr = orig_src_addr;
41613107c60SKishon Vijay Abraham I }
41713107c60SKishon Vijay Abraham I
4182c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
4192c156ac7SKishon Vijay Abraham I lower_32_bits(src_phys_addr));
4202c156ac7SKishon Vijay Abraham I
4212c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
4222c156ac7SKishon Vijay Abraham I upper_32_bits(src_phys_addr));
4232c156ac7SKishon Vijay Abraham I
4242c156ac7SKishon Vijay Abraham I src_crc32 = crc32_le(~0, src_addr, size);
4252c156ac7SKishon Vijay Abraham I
4260a121f9bSKishon Vijay Abraham I orig_dst_addr = kzalloc(size + alignment, GFP_KERNEL);
42713107c60SKishon Vijay Abraham I if (!orig_dst_addr) {
4280e52ea61SGustavo Pimentel dev_err(dev, "Failed to allocate destination address\n");
4292c156ac7SKishon Vijay Abraham I ret = false;
4300a121f9bSKishon Vijay Abraham I goto err_dst_addr;
4310a121f9bSKishon Vijay Abraham I }
4320a121f9bSKishon Vijay Abraham I
4330a121f9bSKishon Vijay Abraham I orig_dst_phys_addr = dma_map_single(dev, orig_dst_addr,
4340a121f9bSKishon Vijay Abraham I size + alignment, DMA_FROM_DEVICE);
4350a121f9bSKishon Vijay Abraham I if (dma_mapping_error(dev, orig_dst_phys_addr)) {
4360a121f9bSKishon Vijay Abraham I dev_err(dev, "failed to map destination buffer address\n");
4370a121f9bSKishon Vijay Abraham I ret = false;
4380a121f9bSKishon Vijay Abraham I goto err_dst_phys_addr;
43913107c60SKishon Vijay Abraham I }
44013107c60SKishon Vijay Abraham I
44113107c60SKishon Vijay Abraham I if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
44213107c60SKishon Vijay Abraham I dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
44313107c60SKishon Vijay Abraham I offset = dst_phys_addr - orig_dst_phys_addr;
44413107c60SKishon Vijay Abraham I dst_addr = orig_dst_addr + offset;
44513107c60SKishon Vijay Abraham I } else {
44613107c60SKishon Vijay Abraham I dst_phys_addr = orig_dst_phys_addr;
44713107c60SKishon Vijay Abraham I dst_addr = orig_dst_addr;
4482c156ac7SKishon Vijay Abraham I }
4492c156ac7SKishon Vijay Abraham I
4502c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
4512c156ac7SKishon Vijay Abraham I lower_32_bits(dst_phys_addr));
4522c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
4532c156ac7SKishon Vijay Abraham I upper_32_bits(dst_phys_addr));
4542c156ac7SKishon Vijay Abraham I
4552c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
4562c156ac7SKishon Vijay Abraham I size);
4572c156ac7SKishon Vijay Abraham I
458cf376b4bSKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags);
4599133e394SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
460e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
4612c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
462e8817de7SGustavo Pimentel COMMAND_COPY);
4632c156ac7SKishon Vijay Abraham I
4642c156ac7SKishon Vijay Abraham I wait_for_completion(&test->irq_raised);
4652c156ac7SKishon Vijay Abraham I
4660a121f9bSKishon Vijay Abraham I dma_unmap_single(dev, orig_dst_phys_addr, size + alignment,
4670a121f9bSKishon Vijay Abraham I DMA_FROM_DEVICE);
4680a121f9bSKishon Vijay Abraham I
4692c156ac7SKishon Vijay Abraham I dst_crc32 = crc32_le(~0, dst_addr, size);
4702c156ac7SKishon Vijay Abraham I if (dst_crc32 == src_crc32)
4712c156ac7SKishon Vijay Abraham I ret = true;
4722c156ac7SKishon Vijay Abraham I
4730a121f9bSKishon Vijay Abraham I err_dst_phys_addr:
4740a121f9bSKishon Vijay Abraham I kfree(orig_dst_addr);
4752c156ac7SKishon Vijay Abraham I
4760a121f9bSKishon Vijay Abraham I err_dst_addr:
4770a121f9bSKishon Vijay Abraham I dma_unmap_single(dev, orig_src_phys_addr, size + alignment,
4780a121f9bSKishon Vijay Abraham I DMA_TO_DEVICE);
4790a121f9bSKishon Vijay Abraham I
4800a121f9bSKishon Vijay Abraham I err_src_phys_addr:
4810a121f9bSKishon Vijay Abraham I kfree(orig_src_addr);
4822c156ac7SKishon Vijay Abraham I
4832c156ac7SKishon Vijay Abraham I err:
4842c156ac7SKishon Vijay Abraham I return ret;
4852c156ac7SKishon Vijay Abraham I }
4862c156ac7SKishon Vijay Abraham I
pci_endpoint_test_write(struct pci_endpoint_test * test,unsigned long arg)487cf376b4bSKishon Vijay Abraham I static bool pci_endpoint_test_write(struct pci_endpoint_test *test,
488cf376b4bSKishon Vijay Abraham I unsigned long arg)
4892c156ac7SKishon Vijay Abraham I {
490cf376b4bSKishon Vijay Abraham I struct pci_endpoint_test_xfer_param param;
4912c156ac7SKishon Vijay Abraham I bool ret = false;
492cf376b4bSKishon Vijay Abraham I u32 flags = 0;
493cf376b4bSKishon Vijay Abraham I bool use_dma;
4942c156ac7SKishon Vijay Abraham I u32 reg;
4952c156ac7SKishon Vijay Abraham I void *addr;
4962c156ac7SKishon Vijay Abraham I dma_addr_t phys_addr;
4972c156ac7SKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
4982c156ac7SKishon Vijay Abraham I struct device *dev = &pdev->dev;
49913107c60SKishon Vijay Abraham I void *orig_addr;
50013107c60SKishon Vijay Abraham I dma_addr_t orig_phys_addr;
50113107c60SKishon Vijay Abraham I size_t offset;
50213107c60SKishon Vijay Abraham I size_t alignment = test->alignment;
503b2ba9225SKishon Vijay Abraham I int irq_type = test->irq_type;
504cf376b4bSKishon Vijay Abraham I size_t size;
5052c156ac7SKishon Vijay Abraham I u32 crc32;
506cf376b4bSKishon Vijay Abraham I int err;
5072c156ac7SKishon Vijay Abraham I
508cf376b4bSKishon Vijay Abraham I err = copy_from_user(¶m, (void __user *)arg, sizeof(param));
509cf376b4bSKishon Vijay Abraham I if (err != 0) {
510cf376b4bSKishon Vijay Abraham I dev_err(dev, "Failed to get transfer param\n");
511cf376b4bSKishon Vijay Abraham I return false;
512cf376b4bSKishon Vijay Abraham I }
513cf376b4bSKishon Vijay Abraham I
5143e42deaaSShunsuke Mie err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment);
5153e42deaaSShunsuke Mie if (err)
5163e42deaaSShunsuke Mie return false;
5173e42deaaSShunsuke Mie
518cf376b4bSKishon Vijay Abraham I size = param.size;
519343dc693SDan Carpenter
520cf376b4bSKishon Vijay Abraham I use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA);
521cf376b4bSKishon Vijay Abraham I if (use_dma)
522cf376b4bSKishon Vijay Abraham I flags |= FLAG_USE_DMA;
523cf376b4bSKishon Vijay Abraham I
524e0332712SGustavo Pimentel if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
525e0332712SGustavo Pimentel dev_err(dev, "Invalid IRQ type option\n");
526e0332712SGustavo Pimentel goto err;
527e0332712SGustavo Pimentel }
528e0332712SGustavo Pimentel
5290a121f9bSKishon Vijay Abraham I orig_addr = kzalloc(size + alignment, GFP_KERNEL);
53013107c60SKishon Vijay Abraham I if (!orig_addr) {
5310e52ea61SGustavo Pimentel dev_err(dev, "Failed to allocate address\n");
5322c156ac7SKishon Vijay Abraham I ret = false;
5332c156ac7SKishon Vijay Abraham I goto err;
5342c156ac7SKishon Vijay Abraham I }
5352c156ac7SKishon Vijay Abraham I
5360a121f9bSKishon Vijay Abraham I get_random_bytes(orig_addr, size + alignment);
5370a121f9bSKishon Vijay Abraham I
5380a121f9bSKishon Vijay Abraham I orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment,
5390a121f9bSKishon Vijay Abraham I DMA_TO_DEVICE);
5400a121f9bSKishon Vijay Abraham I if (dma_mapping_error(dev, orig_phys_addr)) {
5410a121f9bSKishon Vijay Abraham I dev_err(dev, "failed to map source buffer address\n");
5420a121f9bSKishon Vijay Abraham I ret = false;
5430a121f9bSKishon Vijay Abraham I goto err_phys_addr;
5440a121f9bSKishon Vijay Abraham I }
5450a121f9bSKishon Vijay Abraham I
54613107c60SKishon Vijay Abraham I if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
54713107c60SKishon Vijay Abraham I phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
54813107c60SKishon Vijay Abraham I offset = phys_addr - orig_phys_addr;
54913107c60SKishon Vijay Abraham I addr = orig_addr + offset;
55013107c60SKishon Vijay Abraham I } else {
55113107c60SKishon Vijay Abraham I phys_addr = orig_phys_addr;
55213107c60SKishon Vijay Abraham I addr = orig_addr;
55313107c60SKishon Vijay Abraham I }
55413107c60SKishon Vijay Abraham I
5552c156ac7SKishon Vijay Abraham I crc32 = crc32_le(~0, addr, size);
5562c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
5572c156ac7SKishon Vijay Abraham I crc32);
5582c156ac7SKishon Vijay Abraham I
5592c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
5602c156ac7SKishon Vijay Abraham I lower_32_bits(phys_addr));
5612c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
5622c156ac7SKishon Vijay Abraham I upper_32_bits(phys_addr));
5632c156ac7SKishon Vijay Abraham I
5642c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
5652c156ac7SKishon Vijay Abraham I
566cf376b4bSKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags);
5679133e394SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
568e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
5692c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
570e8817de7SGustavo Pimentel COMMAND_READ);
5712c156ac7SKishon Vijay Abraham I
5722c156ac7SKishon Vijay Abraham I wait_for_completion(&test->irq_raised);
5732c156ac7SKishon Vijay Abraham I
5742c156ac7SKishon Vijay Abraham I reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
5752c156ac7SKishon Vijay Abraham I if (reg & STATUS_READ_SUCCESS)
5762c156ac7SKishon Vijay Abraham I ret = true;
5772c156ac7SKishon Vijay Abraham I
5780a121f9bSKishon Vijay Abraham I dma_unmap_single(dev, orig_phys_addr, size + alignment,
5790a121f9bSKishon Vijay Abraham I DMA_TO_DEVICE);
5800a121f9bSKishon Vijay Abraham I
5810a121f9bSKishon Vijay Abraham I err_phys_addr:
5820a121f9bSKishon Vijay Abraham I kfree(orig_addr);
5832c156ac7SKishon Vijay Abraham I
5842c156ac7SKishon Vijay Abraham I err:
5852c156ac7SKishon Vijay Abraham I return ret;
5862c156ac7SKishon Vijay Abraham I }
5872c156ac7SKishon Vijay Abraham I
pci_endpoint_test_read(struct pci_endpoint_test * test,unsigned long arg)588cf376b4bSKishon Vijay Abraham I static bool pci_endpoint_test_read(struct pci_endpoint_test *test,
589cf376b4bSKishon Vijay Abraham I unsigned long arg)
5902c156ac7SKishon Vijay Abraham I {
591cf376b4bSKishon Vijay Abraham I struct pci_endpoint_test_xfer_param param;
5922c156ac7SKishon Vijay Abraham I bool ret = false;
593cf376b4bSKishon Vijay Abraham I u32 flags = 0;
594cf376b4bSKishon Vijay Abraham I bool use_dma;
595cf376b4bSKishon Vijay Abraham I size_t size;
5962c156ac7SKishon Vijay Abraham I void *addr;
5972c156ac7SKishon Vijay Abraham I dma_addr_t phys_addr;
5982c156ac7SKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
5992c156ac7SKishon Vijay Abraham I struct device *dev = &pdev->dev;
60013107c60SKishon Vijay Abraham I void *orig_addr;
60113107c60SKishon Vijay Abraham I dma_addr_t orig_phys_addr;
60213107c60SKishon Vijay Abraham I size_t offset;
60313107c60SKishon Vijay Abraham I size_t alignment = test->alignment;
604b2ba9225SKishon Vijay Abraham I int irq_type = test->irq_type;
6052c156ac7SKishon Vijay Abraham I u32 crc32;
606cf376b4bSKishon Vijay Abraham I int err;
6072c156ac7SKishon Vijay Abraham I
608cf376b4bSKishon Vijay Abraham I err = copy_from_user(¶m, (void __user *)arg, sizeof(param));
609cf376b4bSKishon Vijay Abraham I if (err) {
610cf376b4bSKishon Vijay Abraham I dev_err(dev, "Failed to get transfer param\n");
611cf376b4bSKishon Vijay Abraham I return false;
612cf376b4bSKishon Vijay Abraham I }
613cf376b4bSKishon Vijay Abraham I
6143e42deaaSShunsuke Mie err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment);
6153e42deaaSShunsuke Mie if (err)
6163e42deaaSShunsuke Mie return false;
6173e42deaaSShunsuke Mie
618cf376b4bSKishon Vijay Abraham I size = param.size;
619343dc693SDan Carpenter
620cf376b4bSKishon Vijay Abraham I use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA);
621cf376b4bSKishon Vijay Abraham I if (use_dma)
622cf376b4bSKishon Vijay Abraham I flags |= FLAG_USE_DMA;
623cf376b4bSKishon Vijay Abraham I
624e0332712SGustavo Pimentel if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
625e0332712SGustavo Pimentel dev_err(dev, "Invalid IRQ type option\n");
626e0332712SGustavo Pimentel goto err;
627e0332712SGustavo Pimentel }
628e0332712SGustavo Pimentel
6290a121f9bSKishon Vijay Abraham I orig_addr = kzalloc(size + alignment, GFP_KERNEL);
63013107c60SKishon Vijay Abraham I if (!orig_addr) {
6310e52ea61SGustavo Pimentel dev_err(dev, "Failed to allocate destination address\n");
6322c156ac7SKishon Vijay Abraham I ret = false;
6332c156ac7SKishon Vijay Abraham I goto err;
6342c156ac7SKishon Vijay Abraham I }
6352c156ac7SKishon Vijay Abraham I
6360a121f9bSKishon Vijay Abraham I orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment,
6370a121f9bSKishon Vijay Abraham I DMA_FROM_DEVICE);
6380a121f9bSKishon Vijay Abraham I if (dma_mapping_error(dev, orig_phys_addr)) {
6390a121f9bSKishon Vijay Abraham I dev_err(dev, "failed to map source buffer address\n");
6400a121f9bSKishon Vijay Abraham I ret = false;
6410a121f9bSKishon Vijay Abraham I goto err_phys_addr;
6420a121f9bSKishon Vijay Abraham I }
6430a121f9bSKishon Vijay Abraham I
64413107c60SKishon Vijay Abraham I if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
64513107c60SKishon Vijay Abraham I phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
64613107c60SKishon Vijay Abraham I offset = phys_addr - orig_phys_addr;
64713107c60SKishon Vijay Abraham I addr = orig_addr + offset;
64813107c60SKishon Vijay Abraham I } else {
64913107c60SKishon Vijay Abraham I phys_addr = orig_phys_addr;
65013107c60SKishon Vijay Abraham I addr = orig_addr;
65113107c60SKishon Vijay Abraham I }
65213107c60SKishon Vijay Abraham I
6532c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
6542c156ac7SKishon Vijay Abraham I lower_32_bits(phys_addr));
6552c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
6562c156ac7SKishon Vijay Abraham I upper_32_bits(phys_addr));
6572c156ac7SKishon Vijay Abraham I
6582c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
6592c156ac7SKishon Vijay Abraham I
660cf376b4bSKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags);
6619133e394SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
662e8817de7SGustavo Pimentel pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
6632c156ac7SKishon Vijay Abraham I pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
664e8817de7SGustavo Pimentel COMMAND_WRITE);
6652c156ac7SKishon Vijay Abraham I
6662c156ac7SKishon Vijay Abraham I wait_for_completion(&test->irq_raised);
6672c156ac7SKishon Vijay Abraham I
6680a121f9bSKishon Vijay Abraham I dma_unmap_single(dev, orig_phys_addr, size + alignment,
6690a121f9bSKishon Vijay Abraham I DMA_FROM_DEVICE);
6700a121f9bSKishon Vijay Abraham I
6712c156ac7SKishon Vijay Abraham I crc32 = crc32_le(~0, addr, size);
6722c156ac7SKishon Vijay Abraham I if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
6732c156ac7SKishon Vijay Abraham I ret = true;
6742c156ac7SKishon Vijay Abraham I
6750a121f9bSKishon Vijay Abraham I err_phys_addr:
6760a121f9bSKishon Vijay Abraham I kfree(orig_addr);
6772c156ac7SKishon Vijay Abraham I err:
6782c156ac7SKishon Vijay Abraham I return ret;
6792c156ac7SKishon Vijay Abraham I }
6802c156ac7SKishon Vijay Abraham I
pci_endpoint_test_clear_irq(struct pci_endpoint_test * test)681475007f9SKishon Vijay Abraham I static bool pci_endpoint_test_clear_irq(struct pci_endpoint_test *test)
682475007f9SKishon Vijay Abraham I {
683475007f9SKishon Vijay Abraham I pci_endpoint_test_release_irq(test);
684475007f9SKishon Vijay Abraham I pci_endpoint_test_free_irq_vectors(test);
685475007f9SKishon Vijay Abraham I return true;
686475007f9SKishon Vijay Abraham I }
687475007f9SKishon Vijay Abraham I
pci_endpoint_test_set_irq(struct pci_endpoint_test * test,int req_irq_type)688e0332712SGustavo Pimentel static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
689e0332712SGustavo Pimentel int req_irq_type)
690e0332712SGustavo Pimentel {
691e0332712SGustavo Pimentel struct pci_dev *pdev = test->pdev;
692e0332712SGustavo Pimentel struct device *dev = &pdev->dev;
693e0332712SGustavo Pimentel
694e0332712SGustavo Pimentel if (req_irq_type < IRQ_TYPE_LEGACY || req_irq_type > IRQ_TYPE_MSIX) {
695e0332712SGustavo Pimentel dev_err(dev, "Invalid IRQ type option\n");
696e0332712SGustavo Pimentel return false;
697e0332712SGustavo Pimentel }
698e0332712SGustavo Pimentel
699b2ba9225SKishon Vijay Abraham I if (test->irq_type == req_irq_type)
700e0332712SGustavo Pimentel return true;
701e0332712SGustavo Pimentel
702e0332712SGustavo Pimentel pci_endpoint_test_release_irq(test);
703e0332712SGustavo Pimentel pci_endpoint_test_free_irq_vectors(test);
704e0332712SGustavo Pimentel
705e0332712SGustavo Pimentel if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type))
706e0332712SGustavo Pimentel goto err;
707e0332712SGustavo Pimentel
708e0332712SGustavo Pimentel if (!pci_endpoint_test_request_irq(test))
709e0332712SGustavo Pimentel goto err;
710e0332712SGustavo Pimentel
711e0332712SGustavo Pimentel return true;
712e0332712SGustavo Pimentel
713e0332712SGustavo Pimentel err:
714e0332712SGustavo Pimentel pci_endpoint_test_free_irq_vectors(test);
715e0332712SGustavo Pimentel return false;
716e0332712SGustavo Pimentel }
717e0332712SGustavo Pimentel
pci_endpoint_test_ioctl(struct file * file,unsigned int cmd,unsigned long arg)7182c156ac7SKishon Vijay Abraham I static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
7192c156ac7SKishon Vijay Abraham I unsigned long arg)
7202c156ac7SKishon Vijay Abraham I {
7212c156ac7SKishon Vijay Abraham I int ret = -EINVAL;
7222c156ac7SKishon Vijay Abraham I enum pci_barno bar;
7232c156ac7SKishon Vijay Abraham I struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
7245bb04b19SKishon Vijay Abraham I struct pci_dev *pdev = test->pdev;
7252c156ac7SKishon Vijay Abraham I
7262c156ac7SKishon Vijay Abraham I mutex_lock(&test->mutex);
727fb620ae7SDamien Le Moal
728fb620ae7SDamien Le Moal reinit_completion(&test->irq_raised);
729fb620ae7SDamien Le Moal test->last_irq = -ENODATA;
730fb620ae7SDamien Le Moal
7312c156ac7SKishon Vijay Abraham I switch (cmd) {
7322c156ac7SKishon Vijay Abraham I case PCITEST_BAR:
7332c156ac7SKishon Vijay Abraham I bar = arg;
73433fcc549SGustavo Pimentel if (bar > BAR_5)
7352c156ac7SKishon Vijay Abraham I goto ret;
7365bb04b19SKishon Vijay Abraham I if (is_am654_pci_dev(pdev) && bar == BAR_0)
7375bb04b19SKishon Vijay Abraham I goto ret;
7382c156ac7SKishon Vijay Abraham I ret = pci_endpoint_test_bar(test, bar);
7392c156ac7SKishon Vijay Abraham I break;
7402c156ac7SKishon Vijay Abraham I case PCITEST_LEGACY_IRQ:
7412c156ac7SKishon Vijay Abraham I ret = pci_endpoint_test_legacy_irq(test);
7422c156ac7SKishon Vijay Abraham I break;
7432c156ac7SKishon Vijay Abraham I case PCITEST_MSI:
744c2e00e31SGustavo Pimentel case PCITEST_MSIX:
745c2e00e31SGustavo Pimentel ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX);
7462c156ac7SKishon Vijay Abraham I break;
7472c156ac7SKishon Vijay Abraham I case PCITEST_WRITE:
7482c156ac7SKishon Vijay Abraham I ret = pci_endpoint_test_write(test, arg);
7492c156ac7SKishon Vijay Abraham I break;
7502c156ac7SKishon Vijay Abraham I case PCITEST_READ:
7512c156ac7SKishon Vijay Abraham I ret = pci_endpoint_test_read(test, arg);
7522c156ac7SKishon Vijay Abraham I break;
7532c156ac7SKishon Vijay Abraham I case PCITEST_COPY:
7542c156ac7SKishon Vijay Abraham I ret = pci_endpoint_test_copy(test, arg);
7552c156ac7SKishon Vijay Abraham I break;
756e0332712SGustavo Pimentel case PCITEST_SET_IRQTYPE:
757e0332712SGustavo Pimentel ret = pci_endpoint_test_set_irq(test, arg);
758e0332712SGustavo Pimentel break;
759e0332712SGustavo Pimentel case PCITEST_GET_IRQTYPE:
760e0332712SGustavo Pimentel ret = irq_type;
761e0332712SGustavo Pimentel break;
762475007f9SKishon Vijay Abraham I case PCITEST_CLEAR_IRQ:
763475007f9SKishon Vijay Abraham I ret = pci_endpoint_test_clear_irq(test);
764475007f9SKishon Vijay Abraham I break;
7652c156ac7SKishon Vijay Abraham I }
7662c156ac7SKishon Vijay Abraham I
7672c156ac7SKishon Vijay Abraham I ret:
7682c156ac7SKishon Vijay Abraham I mutex_unlock(&test->mutex);
7692c156ac7SKishon Vijay Abraham I return ret;
7702c156ac7SKishon Vijay Abraham I }
7712c156ac7SKishon Vijay Abraham I
7722c156ac7SKishon Vijay Abraham I static const struct file_operations pci_endpoint_test_fops = {
7732c156ac7SKishon Vijay Abraham I .owner = THIS_MODULE,
7742c156ac7SKishon Vijay Abraham I .unlocked_ioctl = pci_endpoint_test_ioctl,
7752c156ac7SKishon Vijay Abraham I };
7762c156ac7SKishon Vijay Abraham I
pci_endpoint_test_probe(struct pci_dev * pdev,const struct pci_device_id * ent)7772c156ac7SKishon Vijay Abraham I static int pci_endpoint_test_probe(struct pci_dev *pdev,
7782c156ac7SKishon Vijay Abraham I const struct pci_device_id *ent)
7792c156ac7SKishon Vijay Abraham I {
7802c156ac7SKishon Vijay Abraham I int err;
7812c156ac7SKishon Vijay Abraham I int id;
7826b443e5cSKishon Vijay Abraham I char name[24];
7832c156ac7SKishon Vijay Abraham I enum pci_barno bar;
7842c156ac7SKishon Vijay Abraham I void __iomem *base;
7852c156ac7SKishon Vijay Abraham I struct device *dev = &pdev->dev;
7862c156ac7SKishon Vijay Abraham I struct pci_endpoint_test *test;
787834b9051SKishon Vijay Abraham I struct pci_endpoint_test_data *data;
788834b9051SKishon Vijay Abraham I enum pci_barno test_reg_bar = BAR_0;
7892c156ac7SKishon Vijay Abraham I struct miscdevice *misc_device;
7902c156ac7SKishon Vijay Abraham I
7912c156ac7SKishon Vijay Abraham I if (pci_is_bridge(pdev))
7922c156ac7SKishon Vijay Abraham I return -ENODEV;
7932c156ac7SKishon Vijay Abraham I
7942c156ac7SKishon Vijay Abraham I test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
7952c156ac7SKishon Vijay Abraham I if (!test)
7962c156ac7SKishon Vijay Abraham I return -ENOMEM;
7972c156ac7SKishon Vijay Abraham I
798834b9051SKishon Vijay Abraham I test->test_reg_bar = 0;
79913107c60SKishon Vijay Abraham I test->alignment = 0;
8002c156ac7SKishon Vijay Abraham I test->pdev = pdev;
801b2ba9225SKishon Vijay Abraham I test->irq_type = IRQ_TYPE_UNDEFINED;
802834b9051SKishon Vijay Abraham I
8039133e394SGustavo Pimentel if (no_msi)
8049133e394SGustavo Pimentel irq_type = IRQ_TYPE_LEGACY;
8059133e394SGustavo Pimentel
806834b9051SKishon Vijay Abraham I data = (struct pci_endpoint_test_data *)ent->driver_data;
80713107c60SKishon Vijay Abraham I if (data) {
808834b9051SKishon Vijay Abraham I test_reg_bar = data->test_reg_bar;
8098f220664SKishon Vijay Abraham I test->test_reg_bar = test_reg_bar;
81013107c60SKishon Vijay Abraham I test->alignment = data->alignment;
8119133e394SGustavo Pimentel irq_type = data->irq_type;
81213107c60SKishon Vijay Abraham I }
813834b9051SKishon Vijay Abraham I
8142c156ac7SKishon Vijay Abraham I init_completion(&test->irq_raised);
8152c156ac7SKishon Vijay Abraham I mutex_init(&test->mutex);
8162c156ac7SKishon Vijay Abraham I
8170a121f9bSKishon Vijay Abraham I if ((dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)) != 0) &&
8180a121f9bSKishon Vijay Abraham I dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
8190a121f9bSKishon Vijay Abraham I dev_err(dev, "Cannot set DMA mask\n");
8200a121f9bSKishon Vijay Abraham I return -EINVAL;
8210a121f9bSKishon Vijay Abraham I }
8220a121f9bSKishon Vijay Abraham I
8232c156ac7SKishon Vijay Abraham I err = pci_enable_device(pdev);
8242c156ac7SKishon Vijay Abraham I if (err) {
8252c156ac7SKishon Vijay Abraham I dev_err(dev, "Cannot enable PCI device\n");
8262c156ac7SKishon Vijay Abraham I return err;
8272c156ac7SKishon Vijay Abraham I }
8282c156ac7SKishon Vijay Abraham I
8292c156ac7SKishon Vijay Abraham I err = pci_request_regions(pdev, DRV_MODULE_NAME);
8302c156ac7SKishon Vijay Abraham I if (err) {
8312c156ac7SKishon Vijay Abraham I dev_err(dev, "Cannot obtain PCI resources\n");
8322c156ac7SKishon Vijay Abraham I goto err_disable_pdev;
8332c156ac7SKishon Vijay Abraham I }
8342c156ac7SKishon Vijay Abraham I
8352c156ac7SKishon Vijay Abraham I pci_set_master(pdev);
8362c156ac7SKishon Vijay Abraham I
8371749c904SXiongfeng Wang if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) {
8381749c904SXiongfeng Wang err = -EINVAL;
839e0332712SGustavo Pimentel goto err_disable_irq;
8401749c904SXiongfeng Wang }
8412c156ac7SKishon Vijay Abraham I
842c9c13ba4SDenis Efremov for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
84316b17cadSNiklas Cassel if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
8442c156ac7SKishon Vijay Abraham I base = pci_ioremap_bar(pdev, bar);
8452c156ac7SKishon Vijay Abraham I if (!base) {
8460e52ea61SGustavo Pimentel dev_err(dev, "Failed to read BAR%d\n", bar);
847834b9051SKishon Vijay Abraham I WARN_ON(bar == test_reg_bar);
8482c156ac7SKishon Vijay Abraham I }
8492c156ac7SKishon Vijay Abraham I test->bar[bar] = base;
8502c156ac7SKishon Vijay Abraham I }
85116b17cadSNiklas Cassel }
8522c156ac7SKishon Vijay Abraham I
853834b9051SKishon Vijay Abraham I test->base = test->bar[test_reg_bar];
8542c156ac7SKishon Vijay Abraham I if (!test->base) {
85580068c93SKishon Vijay Abraham I err = -ENOMEM;
856834b9051SKishon Vijay Abraham I dev_err(dev, "Cannot perform PCI test without BAR%d\n",
857834b9051SKishon Vijay Abraham I test_reg_bar);
8582c156ac7SKishon Vijay Abraham I goto err_iounmap;
8592c156ac7SKishon Vijay Abraham I }
8602c156ac7SKishon Vijay Abraham I
8612c156ac7SKishon Vijay Abraham I pci_set_drvdata(pdev, test);
8622c156ac7SKishon Vijay Abraham I
8632c156ac7SKishon Vijay Abraham I id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
8642c156ac7SKishon Vijay Abraham I if (id < 0) {
86580068c93SKishon Vijay Abraham I err = id;
8660e52ea61SGustavo Pimentel dev_err(dev, "Unable to get id\n");
8672c156ac7SKishon Vijay Abraham I goto err_iounmap;
8682c156ac7SKishon Vijay Abraham I }
8692c156ac7SKishon Vijay Abraham I
8702c156ac7SKishon Vijay Abraham I snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
871c2be14abSKishon Vijay Abraham I test->name = kstrdup(name, GFP_KERNEL);
872c2be14abSKishon Vijay Abraham I if (!test->name) {
873c2be14abSKishon Vijay Abraham I err = -ENOMEM;
874c2be14abSKishon Vijay Abraham I goto err_ida_remove;
875c2be14abSKishon Vijay Abraham I }
876c2be14abSKishon Vijay Abraham I
8771749c904SXiongfeng Wang if (!pci_endpoint_test_request_irq(test)) {
8781749c904SXiongfeng Wang err = -EINVAL;
879c2be14abSKishon Vijay Abraham I goto err_kfree_test_name;
8801749c904SXiongfeng Wang }
881c2be14abSKishon Vijay Abraham I
8822c156ac7SKishon Vijay Abraham I misc_device = &test->miscdev;
8832c156ac7SKishon Vijay Abraham I misc_device->minor = MISC_DYNAMIC_MINOR;
884139838ffSKishon Vijay Abraham I misc_device->name = kstrdup(name, GFP_KERNEL);
885139838ffSKishon Vijay Abraham I if (!misc_device->name) {
886139838ffSKishon Vijay Abraham I err = -ENOMEM;
887c2be14abSKishon Vijay Abraham I goto err_release_irq;
888139838ffSKishon Vijay Abraham I }
88974a03c20SRichard Weinberger misc_device->parent = &pdev->dev;
890560dbc46SMing Wang misc_device->fops = &pci_endpoint_test_fops;
8912c156ac7SKishon Vijay Abraham I
8922c156ac7SKishon Vijay Abraham I err = misc_register(misc_device);
8932c156ac7SKishon Vijay Abraham I if (err) {
8940e52ea61SGustavo Pimentel dev_err(dev, "Failed to register device\n");
895139838ffSKishon Vijay Abraham I goto err_kfree_name;
8962c156ac7SKishon Vijay Abraham I }
8972c156ac7SKishon Vijay Abraham I
8982c156ac7SKishon Vijay Abraham I return 0;
8992c156ac7SKishon Vijay Abraham I
900139838ffSKishon Vijay Abraham I err_kfree_name:
901139838ffSKishon Vijay Abraham I kfree(misc_device->name);
902139838ffSKishon Vijay Abraham I
903c2be14abSKishon Vijay Abraham I err_release_irq:
904c2be14abSKishon Vijay Abraham I pci_endpoint_test_release_irq(test);
905c2be14abSKishon Vijay Abraham I
906c2be14abSKishon Vijay Abraham I err_kfree_test_name:
907c2be14abSKishon Vijay Abraham I kfree(test->name);
908c2be14abSKishon Vijay Abraham I
9092c156ac7SKishon Vijay Abraham I err_ida_remove:
9102c156ac7SKishon Vijay Abraham I ida_simple_remove(&pci_endpoint_test_ida, id);
9112c156ac7SKishon Vijay Abraham I
9122c156ac7SKishon Vijay Abraham I err_iounmap:
913c9c13ba4SDenis Efremov for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
9142c156ac7SKishon Vijay Abraham I if (test->bar[bar])
9152c156ac7SKishon Vijay Abraham I pci_iounmap(pdev, test->bar[bar]);
9162c156ac7SKishon Vijay Abraham I }
9172c156ac7SKishon Vijay Abraham I
918e0332712SGustavo Pimentel err_disable_irq:
919e0332712SGustavo Pimentel pci_endpoint_test_free_irq_vectors(test);
9202c156ac7SKishon Vijay Abraham I pci_release_regions(pdev);
9212c156ac7SKishon Vijay Abraham I
9222c156ac7SKishon Vijay Abraham I err_disable_pdev:
9232c156ac7SKishon Vijay Abraham I pci_disable_device(pdev);
9242c156ac7SKishon Vijay Abraham I
9252c156ac7SKishon Vijay Abraham I return err;
9262c156ac7SKishon Vijay Abraham I }
9272c156ac7SKishon Vijay Abraham I
pci_endpoint_test_remove(struct pci_dev * pdev)9282c156ac7SKishon Vijay Abraham I static void pci_endpoint_test_remove(struct pci_dev *pdev)
9292c156ac7SKishon Vijay Abraham I {
9302c156ac7SKishon Vijay Abraham I int id;
9312c156ac7SKishon Vijay Abraham I enum pci_barno bar;
9322c156ac7SKishon Vijay Abraham I struct pci_endpoint_test *test = pci_get_drvdata(pdev);
9332c156ac7SKishon Vijay Abraham I struct miscdevice *misc_device = &test->miscdev;
9342c156ac7SKishon Vijay Abraham I
9352c156ac7SKishon Vijay Abraham I if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
9362c156ac7SKishon Vijay Abraham I return;
937a2db2663SDan Carpenter if (id < 0)
938a2db2663SDan Carpenter return;
9392c156ac7SKishon Vijay Abraham I
940f61b7634SDamien Le Moal pci_endpoint_test_release_irq(test);
941f61b7634SDamien Le Moal pci_endpoint_test_free_irq_vectors(test);
942f61b7634SDamien Le Moal
9432c156ac7SKishon Vijay Abraham I misc_deregister(&test->miscdev);
944139838ffSKishon Vijay Abraham I kfree(misc_device->name);
945c2be14abSKishon Vijay Abraham I kfree(test->name);
9462c156ac7SKishon Vijay Abraham I ida_simple_remove(&pci_endpoint_test_ida, id);
947c9c13ba4SDenis Efremov for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
9482c156ac7SKishon Vijay Abraham I if (test->bar[bar])
9492c156ac7SKishon Vijay Abraham I pci_iounmap(pdev, test->bar[bar]);
9502c156ac7SKishon Vijay Abraham I }
951e0332712SGustavo Pimentel
9522c156ac7SKishon Vijay Abraham I pci_release_regions(pdev);
9532c156ac7SKishon Vijay Abraham I pci_disable_device(pdev);
9542c156ac7SKishon Vijay Abraham I }
9552c156ac7SKishon Vijay Abraham I
9560a121f9bSKishon Vijay Abraham I static const struct pci_endpoint_test_data default_data = {
9570a121f9bSKishon Vijay Abraham I .test_reg_bar = BAR_0,
9580a121f9bSKishon Vijay Abraham I .alignment = SZ_4K,
9590a121f9bSKishon Vijay Abraham I .irq_type = IRQ_TYPE_MSI,
9600a121f9bSKishon Vijay Abraham I };
9610a121f9bSKishon Vijay Abraham I
9625bb04b19SKishon Vijay Abraham I static const struct pci_endpoint_test_data am654_data = {
9635bb04b19SKishon Vijay Abraham I .test_reg_bar = BAR_2,
9645bb04b19SKishon Vijay Abraham I .alignment = SZ_64K,
9655bb04b19SKishon Vijay Abraham I .irq_type = IRQ_TYPE_MSI,
9665bb04b19SKishon Vijay Abraham I };
9675bb04b19SKishon Vijay Abraham I
9686546ae29SKishon Vijay Abraham I static const struct pci_endpoint_test_data j721e_data = {
9696546ae29SKishon Vijay Abraham I .alignment = 256,
9706546ae29SKishon Vijay Abraham I .irq_type = IRQ_TYPE_MSI,
9716546ae29SKishon Vijay Abraham I };
9726546ae29SKishon Vijay Abraham I
9732c156ac7SKishon Vijay Abraham I static const struct pci_device_id pci_endpoint_test_tbl[] = {
9740a121f9bSKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x),
9750a121f9bSKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&default_data,
9760a121f9bSKishon Vijay Abraham I },
9770a121f9bSKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x),
9780a121f9bSKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&default_data,
9790a121f9bSKishon Vijay Abraham I },
98009fb37b3SHou Zhiqiang { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0),
98109fb37b3SHou Zhiqiang .driver_data = (kernel_ulong_t)&default_data,
98209fb37b3SHou Zhiqiang },
98301ea5edeSRichard Zhu { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_IMX8),},
98409fb37b3SHou Zhiqiang { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A),
98509fb37b3SHou Zhiqiang .driver_data = (kernel_ulong_t)&default_data,
98609fb37b3SHou Zhiqiang },
9871f418f46SGustavo Pimentel { PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
9885bb04b19SKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
9895bb04b19SKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&am654_data
9905bb04b19SKishon Vijay Abraham I },
991cfb824ddSLad Prabhakar { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774A1),},
992cfb824ddSLad Prabhakar { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774B1),},
993cfb824ddSLad Prabhakar { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774C0),},
994a63c5f3dSLad Prabhakar { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774E1),},
995*f22145b5SYoshihiro Shimoda { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A779F0),
996*f22145b5SYoshihiro Shimoda .driver_data = (kernel_ulong_t)&default_data,
997*f22145b5SYoshihiro Shimoda },
9986546ae29SKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721E),
9996546ae29SKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&j721e_data,
10006546ae29SKishon Vijay Abraham I },
10017c52009dSKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J7200),
10027c52009dSKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&j721e_data,
10037c52009dSKishon Vijay Abraham I },
10047c52009dSKishon Vijay Abraham I { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM64),
10057c52009dSKishon Vijay Abraham I .driver_data = (kernel_ulong_t)&j721e_data,
10067c52009dSKishon Vijay Abraham I },
1007be3e3ab5SSiddharth Vadapalli { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721S2),
1008be3e3ab5SSiddharth Vadapalli .driver_data = (kernel_ulong_t)&j721e_data,
1009be3e3ab5SSiddharth Vadapalli },
10102c156ac7SKishon Vijay Abraham I { }
10112c156ac7SKishon Vijay Abraham I };
10122c156ac7SKishon Vijay Abraham I MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
10132c156ac7SKishon Vijay Abraham I
10142c156ac7SKishon Vijay Abraham I static struct pci_driver pci_endpoint_test_driver = {
10152c156ac7SKishon Vijay Abraham I .name = DRV_MODULE_NAME,
10162c156ac7SKishon Vijay Abraham I .id_table = pci_endpoint_test_tbl,
10172c156ac7SKishon Vijay Abraham I .probe = pci_endpoint_test_probe,
10182c156ac7SKishon Vijay Abraham I .remove = pci_endpoint_test_remove,
1019489b1f41SKishon Vijay Abraham I .sriov_configure = pci_sriov_configure_simple,
10202c156ac7SKishon Vijay Abraham I };
10212c156ac7SKishon Vijay Abraham I module_pci_driver(pci_endpoint_test_driver);
10222c156ac7SKishon Vijay Abraham I
10232c156ac7SKishon Vijay Abraham I MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
10242c156ac7SKishon Vijay Abraham I MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
10252c156ac7SKishon Vijay Abraham I MODULE_LICENSE("GPL v2");
1026