xsk: Add overflow check for u64 division, stored into u32
[linux/fpc-iii.git] / drivers / misc / pci_endpoint_test.c
blob727dc6ec427dda9b801de108873b7bc27d53bb39
1 /**
2 * Host side test driver to test endpoint functionality
4 * Copyright (C) 2017 Texas Instruments
5 * Author: Kishon Vijay Abraham I <kishon@ti.com>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 of
9 * the License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/crc32.h>
21 #include <linux/delay.h>
22 #include <linux/fs.h>
23 #include <linux/io.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/miscdevice.h>
27 #include <linux/module.h>
28 #include <linux/mutex.h>
29 #include <linux/random.h>
30 #include <linux/slab.h>
31 #include <linux/pci.h>
32 #include <linux/pci_ids.h>
34 #include <linux/pci_regs.h>
36 #include <uapi/linux/pcitest.h>
38 #define DRV_MODULE_NAME "pci-endpoint-test"
40 #define IRQ_TYPE_UNDEFINED -1
41 #define IRQ_TYPE_LEGACY 0
42 #define IRQ_TYPE_MSI 1
43 #define IRQ_TYPE_MSIX 2
45 #define PCI_ENDPOINT_TEST_MAGIC 0x0
47 #define PCI_ENDPOINT_TEST_COMMAND 0x4
48 #define COMMAND_RAISE_LEGACY_IRQ BIT(0)
49 #define COMMAND_RAISE_MSI_IRQ BIT(1)
50 #define COMMAND_RAISE_MSIX_IRQ BIT(2)
51 #define COMMAND_READ BIT(3)
52 #define COMMAND_WRITE BIT(4)
53 #define COMMAND_COPY BIT(5)
55 #define PCI_ENDPOINT_TEST_STATUS 0x8
56 #define STATUS_READ_SUCCESS BIT(0)
57 #define STATUS_READ_FAIL BIT(1)
58 #define STATUS_WRITE_SUCCESS BIT(2)
59 #define STATUS_WRITE_FAIL BIT(3)
60 #define STATUS_COPY_SUCCESS BIT(4)
61 #define STATUS_COPY_FAIL BIT(5)
62 #define STATUS_IRQ_RAISED BIT(6)
63 #define STATUS_SRC_ADDR_INVALID BIT(7)
64 #define STATUS_DST_ADDR_INVALID BIT(8)
66 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c
67 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
69 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14
70 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18
72 #define PCI_ENDPOINT_TEST_SIZE 0x1c
73 #define PCI_ENDPOINT_TEST_CHECKSUM 0x20
75 #define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24
76 #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28
78 static DEFINE_IDA(pci_endpoint_test_ida);
80 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
81 miscdev)
83 static bool no_msi;
84 module_param(no_msi, bool, 0444);
85 MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
87 static int irq_type = IRQ_TYPE_MSI;
88 module_param(irq_type, int, 0444);
89 MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)");
91 enum pci_barno {
92 BAR_0,
93 BAR_1,
94 BAR_2,
95 BAR_3,
96 BAR_4,
97 BAR_5,
100 struct pci_endpoint_test {
101 struct pci_dev *pdev;
102 void __iomem *base;
103 void __iomem *bar[6];
104 struct completion irq_raised;
105 int last_irq;
106 int num_irqs;
107 int irq_type;
108 /* mutex to protect the ioctls */
109 struct mutex mutex;
110 struct miscdevice miscdev;
111 enum pci_barno test_reg_bar;
112 size_t alignment;
115 struct pci_endpoint_test_data {
116 enum pci_barno test_reg_bar;
117 size_t alignment;
118 int irq_type;
121 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
122 u32 offset)
124 return readl(test->base + offset);
127 static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
128 u32 offset, u32 value)
130 writel(value, test->base + offset);
133 static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
134 int bar, int offset)
136 return readl(test->bar[bar] + offset);
139 static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
140 int bar, u32 offset, u32 value)
142 writel(value, test->bar[bar] + offset);
145 static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
147 struct pci_endpoint_test *test = dev_id;
148 u32 reg;
150 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
151 if (reg & STATUS_IRQ_RAISED) {
152 test->last_irq = irq;
153 complete(&test->irq_raised);
154 reg &= ~STATUS_IRQ_RAISED;
156 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
157 reg);
159 return IRQ_HANDLED;
162 static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
164 struct pci_dev *pdev = test->pdev;
166 pci_free_irq_vectors(pdev);
167 test->irq_type = IRQ_TYPE_UNDEFINED;
170 static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
171 int type)
173 int irq = -1;
174 struct pci_dev *pdev = test->pdev;
175 struct device *dev = &pdev->dev;
176 bool res = true;
178 switch (type) {
179 case IRQ_TYPE_LEGACY:
180 irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY);
181 if (irq < 0)
182 dev_err(dev, "Failed to get Legacy interrupt\n");
183 break;
184 case IRQ_TYPE_MSI:
185 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
186 if (irq < 0)
187 dev_err(dev, "Failed to get MSI interrupts\n");
188 break;
189 case IRQ_TYPE_MSIX:
190 irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX);
191 if (irq < 0)
192 dev_err(dev, "Failed to get MSI-X interrupts\n");
193 break;
194 default:
195 dev_err(dev, "Invalid IRQ type selected\n");
198 if (irq < 0) {
199 irq = 0;
200 res = false;
203 test->irq_type = type;
204 test->num_irqs = irq;
206 return res;
209 static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test)
211 int i;
212 struct pci_dev *pdev = test->pdev;
213 struct device *dev = &pdev->dev;
215 for (i = 0; i < test->num_irqs; i++)
216 devm_free_irq(dev, pci_irq_vector(pdev, i), test);
218 test->num_irqs = 0;
221 static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
223 int i;
224 int err;
225 struct pci_dev *pdev = test->pdev;
226 struct device *dev = &pdev->dev;
228 for (i = 0; i < test->num_irqs; i++) {
229 err = devm_request_irq(dev, pci_irq_vector(pdev, i),
230 pci_endpoint_test_irqhandler,
231 IRQF_SHARED, DRV_MODULE_NAME, test);
232 if (err)
233 goto fail;
236 return true;
238 fail:
239 switch (irq_type) {
240 case IRQ_TYPE_LEGACY:
241 dev_err(dev, "Failed to request IRQ %d for Legacy\n",
242 pci_irq_vector(pdev, i));
243 break;
244 case IRQ_TYPE_MSI:
245 dev_err(dev, "Failed to request IRQ %d for MSI %d\n",
246 pci_irq_vector(pdev, i),
247 i + 1);
248 break;
249 case IRQ_TYPE_MSIX:
250 dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n",
251 pci_irq_vector(pdev, i),
252 i + 1);
253 break;
256 return false;
259 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
260 enum pci_barno barno)
262 int j;
263 u32 val;
264 int size;
265 struct pci_dev *pdev = test->pdev;
267 if (!test->bar[barno])
268 return false;
270 size = pci_resource_len(pdev, barno);
272 if (barno == test->test_reg_bar)
273 size = 0x4;
275 for (j = 0; j < size; j += 4)
276 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
278 for (j = 0; j < size; j += 4) {
279 val = pci_endpoint_test_bar_readl(test, barno, j);
280 if (val != 0xA0A0A0A0)
281 return false;
284 return true;
287 static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
289 u32 val;
291 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
292 IRQ_TYPE_LEGACY);
293 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0);
294 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
295 COMMAND_RAISE_LEGACY_IRQ);
296 val = wait_for_completion_timeout(&test->irq_raised,
297 msecs_to_jiffies(1000));
298 if (!val)
299 return false;
301 return true;
304 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
305 u16 msi_num, bool msix)
307 u32 val;
308 struct pci_dev *pdev = test->pdev;
310 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
311 msix == false ? IRQ_TYPE_MSI :
312 IRQ_TYPE_MSIX);
313 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num);
314 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
315 msix == false ? COMMAND_RAISE_MSI_IRQ :
316 COMMAND_RAISE_MSIX_IRQ);
317 val = wait_for_completion_timeout(&test->irq_raised,
318 msecs_to_jiffies(1000));
319 if (!val)
320 return false;
322 if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq)
323 return true;
325 return false;
328 static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
330 bool ret = false;
331 void *src_addr;
332 void *dst_addr;
333 dma_addr_t src_phys_addr;
334 dma_addr_t dst_phys_addr;
335 struct pci_dev *pdev = test->pdev;
336 struct device *dev = &pdev->dev;
337 void *orig_src_addr;
338 dma_addr_t orig_src_phys_addr;
339 void *orig_dst_addr;
340 dma_addr_t orig_dst_phys_addr;
341 size_t offset;
342 size_t alignment = test->alignment;
343 int irq_type = test->irq_type;
344 u32 src_crc32;
345 u32 dst_crc32;
347 if (size > SIZE_MAX - alignment)
348 goto err;
350 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
351 dev_err(dev, "Invalid IRQ type option\n");
352 goto err;
355 orig_src_addr = dma_alloc_coherent(dev, size + alignment,
356 &orig_src_phys_addr, GFP_KERNEL);
357 if (!orig_src_addr) {
358 dev_err(dev, "Failed to allocate source buffer\n");
359 ret = false;
360 goto err;
363 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
364 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
365 offset = src_phys_addr - orig_src_phys_addr;
366 src_addr = orig_src_addr + offset;
367 } else {
368 src_phys_addr = orig_src_phys_addr;
369 src_addr = orig_src_addr;
372 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
373 lower_32_bits(src_phys_addr));
375 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
376 upper_32_bits(src_phys_addr));
378 get_random_bytes(src_addr, size);
379 src_crc32 = crc32_le(~0, src_addr, size);
381 orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
382 &orig_dst_phys_addr, GFP_KERNEL);
383 if (!orig_dst_addr) {
384 dev_err(dev, "Failed to allocate destination address\n");
385 ret = false;
386 goto err_orig_src_addr;
389 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
390 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
391 offset = dst_phys_addr - orig_dst_phys_addr;
392 dst_addr = orig_dst_addr + offset;
393 } else {
394 dst_phys_addr = orig_dst_phys_addr;
395 dst_addr = orig_dst_addr;
398 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
399 lower_32_bits(dst_phys_addr));
400 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
401 upper_32_bits(dst_phys_addr));
403 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
404 size);
406 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
407 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
408 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
409 COMMAND_COPY);
411 wait_for_completion(&test->irq_raised);
413 dst_crc32 = crc32_le(~0, dst_addr, size);
414 if (dst_crc32 == src_crc32)
415 ret = true;
417 dma_free_coherent(dev, size + alignment, orig_dst_addr,
418 orig_dst_phys_addr);
420 err_orig_src_addr:
421 dma_free_coherent(dev, size + alignment, orig_src_addr,
422 orig_src_phys_addr);
424 err:
425 return ret;
428 static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
430 bool ret = false;
431 u32 reg;
432 void *addr;
433 dma_addr_t phys_addr;
434 struct pci_dev *pdev = test->pdev;
435 struct device *dev = &pdev->dev;
436 void *orig_addr;
437 dma_addr_t orig_phys_addr;
438 size_t offset;
439 size_t alignment = test->alignment;
440 int irq_type = test->irq_type;
441 u32 crc32;
443 if (size > SIZE_MAX - alignment)
444 goto err;
446 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
447 dev_err(dev, "Invalid IRQ type option\n");
448 goto err;
451 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
452 GFP_KERNEL);
453 if (!orig_addr) {
454 dev_err(dev, "Failed to allocate address\n");
455 ret = false;
456 goto err;
459 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
460 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
461 offset = phys_addr - orig_phys_addr;
462 addr = orig_addr + offset;
463 } else {
464 phys_addr = orig_phys_addr;
465 addr = orig_addr;
468 get_random_bytes(addr, size);
470 crc32 = crc32_le(~0, addr, size);
471 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
472 crc32);
474 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
475 lower_32_bits(phys_addr));
476 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
477 upper_32_bits(phys_addr));
479 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
481 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
482 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
483 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
484 COMMAND_READ);
486 wait_for_completion(&test->irq_raised);
488 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
489 if (reg & STATUS_READ_SUCCESS)
490 ret = true;
492 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
494 err:
495 return ret;
498 static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
500 bool ret = false;
501 void *addr;
502 dma_addr_t phys_addr;
503 struct pci_dev *pdev = test->pdev;
504 struct device *dev = &pdev->dev;
505 void *orig_addr;
506 dma_addr_t orig_phys_addr;
507 size_t offset;
508 size_t alignment = test->alignment;
509 int irq_type = test->irq_type;
510 u32 crc32;
512 if (size > SIZE_MAX - alignment)
513 goto err;
515 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) {
516 dev_err(dev, "Invalid IRQ type option\n");
517 goto err;
520 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
521 GFP_KERNEL);
522 if (!orig_addr) {
523 dev_err(dev, "Failed to allocate destination address\n");
524 ret = false;
525 goto err;
528 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
529 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
530 offset = phys_addr - orig_phys_addr;
531 addr = orig_addr + offset;
532 } else {
533 phys_addr = orig_phys_addr;
534 addr = orig_addr;
537 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
538 lower_32_bits(phys_addr));
539 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
540 upper_32_bits(phys_addr));
542 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
544 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
545 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
546 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
547 COMMAND_WRITE);
549 wait_for_completion(&test->irq_raised);
551 crc32 = crc32_le(~0, addr, size);
552 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
553 ret = true;
555 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
556 err:
557 return ret;
560 static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
561 int req_irq_type)
563 struct pci_dev *pdev = test->pdev;
564 struct device *dev = &pdev->dev;
566 if (req_irq_type < IRQ_TYPE_LEGACY || req_irq_type > IRQ_TYPE_MSIX) {
567 dev_err(dev, "Invalid IRQ type option\n");
568 return false;
571 if (test->irq_type == req_irq_type)
572 return true;
574 pci_endpoint_test_release_irq(test);
575 pci_endpoint_test_free_irq_vectors(test);
577 if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type))
578 goto err;
580 if (!pci_endpoint_test_request_irq(test))
581 goto err;
583 return true;
585 err:
586 pci_endpoint_test_free_irq_vectors(test);
587 return false;
590 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
591 unsigned long arg)
593 int ret = -EINVAL;
594 enum pci_barno bar;
595 struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
597 mutex_lock(&test->mutex);
598 switch (cmd) {
599 case PCITEST_BAR:
600 bar = arg;
601 if (bar < 0 || bar > 5)
602 goto ret;
603 ret = pci_endpoint_test_bar(test, bar);
604 break;
605 case PCITEST_LEGACY_IRQ:
606 ret = pci_endpoint_test_legacy_irq(test);
607 break;
608 case PCITEST_MSI:
609 case PCITEST_MSIX:
610 ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX);
611 break;
612 case PCITEST_WRITE:
613 ret = pci_endpoint_test_write(test, arg);
614 break;
615 case PCITEST_READ:
616 ret = pci_endpoint_test_read(test, arg);
617 break;
618 case PCITEST_COPY:
619 ret = pci_endpoint_test_copy(test, arg);
620 break;
621 case PCITEST_SET_IRQTYPE:
622 ret = pci_endpoint_test_set_irq(test, arg);
623 break;
624 case PCITEST_GET_IRQTYPE:
625 ret = irq_type;
626 break;
629 ret:
630 mutex_unlock(&test->mutex);
631 return ret;
634 static const struct file_operations pci_endpoint_test_fops = {
635 .owner = THIS_MODULE,
636 .unlocked_ioctl = pci_endpoint_test_ioctl,
639 static int pci_endpoint_test_probe(struct pci_dev *pdev,
640 const struct pci_device_id *ent)
642 int err;
643 int id;
644 char name[24];
645 enum pci_barno bar;
646 void __iomem *base;
647 struct device *dev = &pdev->dev;
648 struct pci_endpoint_test *test;
649 struct pci_endpoint_test_data *data;
650 enum pci_barno test_reg_bar = BAR_0;
651 struct miscdevice *misc_device;
653 if (pci_is_bridge(pdev))
654 return -ENODEV;
656 test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
657 if (!test)
658 return -ENOMEM;
660 test->test_reg_bar = 0;
661 test->alignment = 0;
662 test->pdev = pdev;
663 test->irq_type = IRQ_TYPE_UNDEFINED;
665 if (no_msi)
666 irq_type = IRQ_TYPE_LEGACY;
668 data = (struct pci_endpoint_test_data *)ent->driver_data;
669 if (data) {
670 test_reg_bar = data->test_reg_bar;
671 test->test_reg_bar = test_reg_bar;
672 test->alignment = data->alignment;
673 irq_type = data->irq_type;
676 init_completion(&test->irq_raised);
677 mutex_init(&test->mutex);
679 err = pci_enable_device(pdev);
680 if (err) {
681 dev_err(dev, "Cannot enable PCI device\n");
682 return err;
685 err = pci_request_regions(pdev, DRV_MODULE_NAME);
686 if (err) {
687 dev_err(dev, "Cannot obtain PCI resources\n");
688 goto err_disable_pdev;
691 pci_set_master(pdev);
693 if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type))
694 goto err_disable_irq;
696 if (!pci_endpoint_test_request_irq(test))
697 goto err_disable_irq;
699 for (bar = BAR_0; bar <= BAR_5; bar++) {
700 if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
701 base = pci_ioremap_bar(pdev, bar);
702 if (!base) {
703 dev_err(dev, "Failed to read BAR%d\n", bar);
704 WARN_ON(bar == test_reg_bar);
706 test->bar[bar] = base;
710 test->base = test->bar[test_reg_bar];
711 if (!test->base) {
712 err = -ENOMEM;
713 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
714 test_reg_bar);
715 goto err_iounmap;
718 pci_set_drvdata(pdev, test);
720 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
721 if (id < 0) {
722 err = id;
723 dev_err(dev, "Unable to get id\n");
724 goto err_iounmap;
727 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
728 misc_device = &test->miscdev;
729 misc_device->minor = MISC_DYNAMIC_MINOR;
730 misc_device->name = kstrdup(name, GFP_KERNEL);
731 if (!misc_device->name) {
732 err = -ENOMEM;
733 goto err_ida_remove;
735 misc_device->fops = &pci_endpoint_test_fops,
737 err = misc_register(misc_device);
738 if (err) {
739 dev_err(dev, "Failed to register device\n");
740 goto err_kfree_name;
743 return 0;
745 err_kfree_name:
746 kfree(misc_device->name);
748 err_ida_remove:
749 ida_simple_remove(&pci_endpoint_test_ida, id);
751 err_iounmap:
752 for (bar = BAR_0; bar <= BAR_5; bar++) {
753 if (test->bar[bar])
754 pci_iounmap(pdev, test->bar[bar]);
756 pci_endpoint_test_release_irq(test);
758 err_disable_irq:
759 pci_endpoint_test_free_irq_vectors(test);
760 pci_release_regions(pdev);
762 err_disable_pdev:
763 pci_disable_device(pdev);
765 return err;
768 static void pci_endpoint_test_remove(struct pci_dev *pdev)
770 int id;
771 enum pci_barno bar;
772 struct pci_endpoint_test *test = pci_get_drvdata(pdev);
773 struct miscdevice *misc_device = &test->miscdev;
775 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
776 return;
777 if (id < 0)
778 return;
780 misc_deregister(&test->miscdev);
781 kfree(misc_device->name);
782 ida_simple_remove(&pci_endpoint_test_ida, id);
783 for (bar = BAR_0; bar <= BAR_5; bar++) {
784 if (test->bar[bar])
785 pci_iounmap(pdev, test->bar[bar]);
788 pci_endpoint_test_release_irq(test);
789 pci_endpoint_test_free_irq_vectors(test);
791 pci_release_regions(pdev);
792 pci_disable_device(pdev);
795 static const struct pci_device_id pci_endpoint_test_tbl[] = {
796 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
797 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
798 { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, 0xedda) },
801 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
803 static struct pci_driver pci_endpoint_test_driver = {
804 .name = DRV_MODULE_NAME,
805 .id_table = pci_endpoint_test_tbl,
806 .probe = pci_endpoint_test_probe,
807 .remove = pci_endpoint_test_remove,
809 module_pci_driver(pci_endpoint_test_driver);
811 MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
812 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
813 MODULE_LICENSE("GPL v2");