aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2017-11-14 13:11:21 -0500
committerBjorn Helgaas <bhelgaas@google.com>2017-11-14 13:11:21 -0500
commit1a03bac30341dcf98c0d7d181c52edcff7e248c5 (patch)
tree60eeeb67e254c425892acfcd7c37d6ba4ed2d352
parent9c42da50c068bd3f54cd6248efd9c92d118918ed (diff)
parentb7636e816adcb52bc96b6fb7bc9d141cbfd17ddb (diff)
Merge branch 'pci/endpoint' into next
* pci/endpoint: misc: pci_endpoint_test: Fix BUG_ON error during pci_disable_msi() misc: pci_endpoint_test: Fix pci_endpoint_test not releasing resources on remove misc: pci_endpoint_test: Fix failure path return values in probe misc: pci_endpoint_test: Avoid triggering a BUG() misc: pci_endpoint_test: Prevent some integer overflows
-rw-r--r--drivers/misc/pci_endpoint_test.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index deb203026496..320276f42653 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -92,6 +92,7 @@ struct pci_endpoint_test {
92 void __iomem *bar[6]; 92 void __iomem *bar[6];
93 struct completion irq_raised; 93 struct completion irq_raised;
94 int last_irq; 94 int last_irq;
95 int num_irqs;
95 /* mutex to protect the ioctls */ 96 /* mutex to protect the ioctls */
96 struct mutex mutex; 97 struct mutex mutex;
97 struct miscdevice miscdev; 98 struct miscdevice miscdev;
@@ -226,6 +227,9 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
226 u32 src_crc32; 227 u32 src_crc32;
227 u32 dst_crc32; 228 u32 dst_crc32;
228 229
230 if (size > SIZE_MAX - alignment)
231 goto err;
232
229 orig_src_addr = dma_alloc_coherent(dev, size + alignment, 233 orig_src_addr = dma_alloc_coherent(dev, size + alignment,
230 &orig_src_phys_addr, GFP_KERNEL); 234 &orig_src_phys_addr, GFP_KERNEL);
231 if (!orig_src_addr) { 235 if (!orig_src_addr) {
@@ -311,6 +315,9 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
311 size_t alignment = test->alignment; 315 size_t alignment = test->alignment;
312 u32 crc32; 316 u32 crc32;
313 317
318 if (size > SIZE_MAX - alignment)
319 goto err;
320
314 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 321 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
315 GFP_KERNEL); 322 GFP_KERNEL);
316 if (!orig_addr) { 323 if (!orig_addr) {
@@ -369,6 +376,9 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
369 size_t alignment = test->alignment; 376 size_t alignment = test->alignment;
370 u32 crc32; 377 u32 crc32;
371 378
379 if (size > SIZE_MAX - alignment)
380 goto err;
381
372 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 382 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
373 GFP_KERNEL); 383 GFP_KERNEL);
374 if (!orig_addr) { 384 if (!orig_addr) {
@@ -504,6 +514,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
504 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 514 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
505 if (irq < 0) 515 if (irq < 0)
506 dev_err(dev, "failed to get MSI interrupts\n"); 516 dev_err(dev, "failed to get MSI interrupts\n");
517 test->num_irqs = irq;
507 } 518 }
508 519
509 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, 520 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
@@ -533,6 +544,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
533 544
534 test->base = test->bar[test_reg_bar]; 545 test->base = test->bar[test_reg_bar];
535 if (!test->base) { 546 if (!test->base) {
547 err = -ENOMEM;
536 dev_err(dev, "Cannot perform PCI test without BAR%d\n", 548 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
537 test_reg_bar); 549 test_reg_bar);
538 goto err_iounmap; 550 goto err_iounmap;
@@ -542,6 +554,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
542 554
543 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL); 555 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
544 if (id < 0) { 556 if (id < 0) {
557 err = id;
545 dev_err(dev, "unable to get id\n"); 558 dev_err(dev, "unable to get id\n");
546 goto err_iounmap; 559 goto err_iounmap;
547 } 560 }
@@ -549,17 +562,24 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
549 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); 562 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
550 misc_device = &test->miscdev; 563 misc_device = &test->miscdev;
551 misc_device->minor = MISC_DYNAMIC_MINOR; 564 misc_device->minor = MISC_DYNAMIC_MINOR;
552 misc_device->name = name; 565 misc_device->name = kstrdup(name, GFP_KERNEL);
566 if (!misc_device->name) {
567 err = -ENOMEM;
568 goto err_ida_remove;
569 }
553 misc_device->fops = &pci_endpoint_test_fops, 570 misc_device->fops = &pci_endpoint_test_fops,
554 571
555 err = misc_register(misc_device); 572 err = misc_register(misc_device);
556 if (err) { 573 if (err) {
557 dev_err(dev, "failed to register device\n"); 574 dev_err(dev, "failed to register device\n");
558 goto err_ida_remove; 575 goto err_kfree_name;
559 } 576 }
560 577
561 return 0; 578 return 0;
562 579
580err_kfree_name:
581 kfree(misc_device->name);
582
563err_ida_remove: 583err_ida_remove:
564 ida_simple_remove(&pci_endpoint_test_ida, id); 584 ida_simple_remove(&pci_endpoint_test_ida, id);
565 585
@@ -569,6 +589,9 @@ err_iounmap:
569 pci_iounmap(pdev, test->bar[bar]); 589 pci_iounmap(pdev, test->bar[bar]);
570 } 590 }
571 591
592 for (i = 0; i < irq; i++)
593 devm_free_irq(dev, pdev->irq + i, test);
594
572err_disable_msi: 595err_disable_msi:
573 pci_disable_msi(pdev); 596 pci_disable_msi(pdev);
574 pci_release_regions(pdev); 597 pci_release_regions(pdev);
@@ -582,19 +605,25 @@ err_disable_pdev:
582static void pci_endpoint_test_remove(struct pci_dev *pdev) 605static void pci_endpoint_test_remove(struct pci_dev *pdev)
583{ 606{
584 int id; 607 int id;
608 int i;
585 enum pci_barno bar; 609 enum pci_barno bar;
586 struct pci_endpoint_test *test = pci_get_drvdata(pdev); 610 struct pci_endpoint_test *test = pci_get_drvdata(pdev);
587 struct miscdevice *misc_device = &test->miscdev; 611 struct miscdevice *misc_device = &test->miscdev;
588 612
589 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1) 613 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
590 return; 614 return;
615 if (id < 0)
616 return;
591 617
592 misc_deregister(&test->miscdev); 618 misc_deregister(&test->miscdev);
619 kfree(misc_device->name);
593 ida_simple_remove(&pci_endpoint_test_ida, id); 620 ida_simple_remove(&pci_endpoint_test_ida, id);
594 for (bar = BAR_0; bar <= BAR_5; bar++) { 621 for (bar = BAR_0; bar <= BAR_5; bar++) {
595 if (test->bar[bar]) 622 if (test->bar[bar])
596 pci_iounmap(pdev, test->bar[bar]); 623 pci_iounmap(pdev, test->bar[bar]);
597 } 624 }
625 for (i = 0; i < test->num_irqs; i++)
626 devm_free_irq(&pdev->dev, pdev->irq + i, test);
598 pci_disable_msi(pdev); 627 pci_disable_msi(pdev);
599 pci_release_regions(pdev); 628 pci_release_regions(pdev);
600 pci_disable_device(pdev); 629 pci_disable_device(pdev);