Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

of: unittest: Add pci_dt_testdrv pci driver

pci_dt_testdrv is bound to QEMU PCI Test Device. It reads
overlay_pci_node fdt fragment and apply it to Test Device. Then it
calls of_platform_default_populate() to populate the platform
devices.

Tested-by: Herve Codina <herve.codina@bootlin.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://lore.kernel.org/r/1692120000-46900-6-git-send-email-lizhi.hou@amd.com
Signed-off-by: Rob Herring <robh@kernel.org>

authored by

Lizhi Hou and committed by
Rob Herring
26409dd0 47284862

+214 -1
+2 -1
drivers/of/unittest-data/Makefile
··· 32 32 overlay_gpio_02b.dtbo.o \ 33 33 overlay_gpio_03.dtbo.o \ 34 34 overlay_gpio_04a.dtbo.o \ 35 - overlay_gpio_04b.dtbo.o 35 + overlay_gpio_04b.dtbo.o \ 36 + overlay_pci_node.dtbo.o 36 37 37 38 # enable creation of __symbols__ node 38 39 DTC_FLAGS_overlay += -@
+22
drivers/of/unittest-data/overlay_pci_node.dtso
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + / { 4 + fragment@0 { 5 + target-path=""; 6 + __overlay__ { 7 + #address-cells = <3>; 8 + #size-cells = <2>; 9 + pci-ep-bus@0 { 10 + compatible = "simple-bus"; 11 + #address-cells = <1>; 12 + #size-cells = <1>; 13 + ranges = <0x0 0x0 0x0 0x0 0x1000>; 14 + reg = <0 0 0 0 0>; 15 + unittest-pci@100 { 16 + compatible = "unittest-pci"; 17 + reg = <0x100 0x200>; 18 + }; 19 + }; 20 + }; 21 + }; 22 + };
+189
drivers/of/unittest.c
··· 22 22 #include <linux/slab.h> 23 23 #include <linux/device.h> 24 24 #include <linux/platform_device.h> 25 + #include <linux/pci.h> 25 26 #include <linux/kernel.h> 26 27 27 28 #include <linux/i2c.h> ··· 3327 3326 OVERLAY_INFO_EXTERN(overlay_gpio_03); 3328 3327 OVERLAY_INFO_EXTERN(overlay_gpio_04a); 3329 3328 OVERLAY_INFO_EXTERN(overlay_gpio_04b); 3329 + OVERLAY_INFO_EXTERN(overlay_pci_node); 3330 3330 OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node); 3331 3331 OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop); 3332 3332 OVERLAY_INFO_EXTERN(overlay_bad_phandle); ··· 3363 3361 OVERLAY_INFO(overlay_gpio_03, 0), 3364 3362 OVERLAY_INFO(overlay_gpio_04a, 0), 3365 3363 OVERLAY_INFO(overlay_gpio_04b, 0), 3364 + OVERLAY_INFO(overlay_pci_node, 0), 3366 3365 OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL), 3367 3366 OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL), 3368 3367 OVERLAY_INFO(overlay_bad_phandle, -EINVAL), ··· 3734 3731 3735 3732 #endif 3736 3733 3734 + #ifdef CONFIG_PCI_DYNAMIC_OF_NODES 3735 + 3736 + static int of_unittest_pci_dev_num; 3737 + static int of_unittest_pci_child_num; 3738 + 3739 + /* 3740 + * PCI device tree node test driver 3741 + */ 3742 + static const struct pci_device_id testdrv_pci_ids[] = { 3743 + { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, 0x5), }, /* PCI_VENDOR_ID_REDHAT */ 3744 + { 0, } 3745 + }; 3746 + 3747 + static int testdrv_probe(struct pci_dev *pdev, const struct pci_device_id *id) 3748 + { 3749 + struct overlay_info *info; 3750 + struct device_node *dn; 3751 + int ret, ovcs_id; 3752 + u32 size; 3753 + 3754 + dn = pdev->dev.of_node; 3755 + if (!dn) { 3756 + dev_err(&pdev->dev, "does not find bus endpoint"); 3757 + return -EINVAL; 3758 + } 3759 + 3760 + for (info = overlays; info && info->name; info++) { 3761 + if (!strcmp(info->name, "overlay_pci_node")) 3762 + break; 3763 + } 3764 + if (!info || !info->name) { 3765 + dev_err(&pdev->dev, "no overlay data for overlay_pci_node"); 3766 + return -ENODEV; 3767 + } 3768 + 3769 + size = info->dtbo_end - info->dtbo_begin; 3770 + ret = of_overlay_fdt_apply(info->dtbo_begin, size, &ovcs_id, dn); 3771 + of_node_put(dn); 3772 + if (ret) 3773 + return ret; 3774 + 3775 + of_platform_default_populate(dn, NULL, &pdev->dev); 3776 + pci_set_drvdata(pdev, (void *)(uintptr_t)ovcs_id); 3777 + 3778 + return 0; 3779 + } 3780 + 3781 + static void testdrv_remove(struct pci_dev *pdev) 3782 + { 3783 + int ovcs_id = (int)(uintptr_t)pci_get_drvdata(pdev); 3784 + 3785 + of_platform_depopulate(&pdev->dev); 3786 + of_overlay_remove(&ovcs_id); 3787 + } 3788 + 3789 + static struct pci_driver testdrv_driver = { 3790 + .name = "pci_dt_testdrv", 3791 + .id_table = testdrv_pci_ids, 3792 + .probe = testdrv_probe, 3793 + .remove = testdrv_remove, 3794 + }; 3795 + 3796 + static int unittest_pci_probe(struct platform_device *pdev) 3797 + { 3798 + struct resource *res; 3799 + struct device *dev; 3800 + u64 exp_addr; 3801 + 3802 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3803 + if (!res) 3804 + return -ENODEV; 3805 + 3806 + dev = &pdev->dev; 3807 + while (dev && !dev_is_pci(dev)) 3808 + dev = dev->parent; 3809 + if (!dev) { 3810 + pr_err("unable to find parent device\n"); 3811 + return -ENODEV; 3812 + } 3813 + 3814 + exp_addr = pci_resource_start(to_pci_dev(dev), 0) + 0x100; 3815 + unittest(res->start == exp_addr, "Incorrect translated address %llx, expected %llx\n", 3816 + (u64)res->start, exp_addr); 3817 + 3818 + of_unittest_pci_child_num++; 3819 + 3820 + return 0; 3821 + } 3822 + 3823 + static const struct of_device_id unittest_pci_of_match[] = { 3824 + { .compatible = "unittest-pci" }, 3825 + { } 3826 + }; 3827 + 3828 + static struct platform_driver unittest_pci_driver = { 3829 + .probe = unittest_pci_probe, 3830 + .driver = { 3831 + .name = "unittest-pci", 3832 + .of_match_table = unittest_pci_of_match, 3833 + }, 3834 + }; 3835 + 3836 + static int of_unittest_pci_node_verify(struct pci_dev *pdev, bool add) 3837 + { 3838 + struct device_node *pnp, *np = NULL; 3839 + struct device *child_dev; 3840 + char *path = NULL; 3841 + const __be32 *reg; 3842 + int rc = 0; 3843 + 3844 + pnp = pdev->dev.of_node; 3845 + unittest(pnp, "Failed creating PCI dt node\n"); 3846 + if (!pnp) 3847 + return -ENODEV; 3848 + 3849 + if (add) { 3850 + path = kasprintf(GFP_KERNEL, "%pOF/pci-ep-bus@0/unittest-pci@100", pnp); 3851 + np = of_find_node_by_path(path); 3852 + unittest(np, "Failed to get unittest-pci node under PCI node\n"); 3853 + if (!np) { 3854 + rc = -ENODEV; 3855 + goto failed; 3856 + } 3857 + 3858 + reg = of_get_property(np, "reg", NULL); 3859 + unittest(reg, "Failed to get reg property\n"); 3860 + if (!reg) 3861 + rc = -ENODEV; 3862 + } else { 3863 + path = kasprintf(GFP_KERNEL, "%pOF/pci-ep-bus@0", pnp); 3864 + np = of_find_node_by_path(path); 3865 + unittest(!np, "Child device tree node is not removed\n"); 3866 + child_dev = device_find_any_child(&pdev->dev); 3867 + unittest(!child_dev, "Child device is not removed\n"); 3868 + } 3869 + 3870 + failed: 3871 + kfree(path); 3872 + if (np) 3873 + of_node_put(np); 3874 + 3875 + return rc; 3876 + } 3877 + 3878 + static void __init of_unittest_pci_node(void) 3879 + { 3880 + struct pci_dev *pdev = NULL; 3881 + int rc; 3882 + 3883 + rc = pci_register_driver(&testdrv_driver); 3884 + unittest(!rc, "Failed to register pci test driver; rc = %d\n", rc); 3885 + if (rc) 3886 + return; 3887 + 3888 + rc = platform_driver_register(&unittest_pci_driver); 3889 + if (unittest(!rc, "Failed to register unittest pci driver\n")) { 3890 + pci_unregister_driver(&testdrv_driver); 3891 + return; 3892 + } 3893 + 3894 + while ((pdev = pci_get_device(PCI_VENDOR_ID_REDHAT, 0x5, pdev)) != NULL) { 3895 + of_unittest_pci_node_verify(pdev, true); 3896 + of_unittest_pci_dev_num++; 3897 + } 3898 + if (pdev) 3899 + pci_dev_put(pdev); 3900 + 3901 + unittest(of_unittest_pci_dev_num, 3902 + "No test PCI device been found. Please run QEMU with '-device pci-testdev'\n"); 3903 + unittest(of_unittest_pci_dev_num == of_unittest_pci_child_num, 3904 + "Child device number %d is not expected %d", of_unittest_pci_child_num, 3905 + of_unittest_pci_dev_num); 3906 + 3907 + platform_driver_unregister(&unittest_pci_driver); 3908 + pci_unregister_driver(&testdrv_driver); 3909 + 3910 + while ((pdev = pci_get_device(PCI_VENDOR_ID_REDHAT, 0x5, pdev)) != NULL) 3911 + of_unittest_pci_node_verify(pdev, false); 3912 + if (pdev) 3913 + pci_dev_put(pdev); 3914 + } 3915 + #else 3916 + static void __init of_unittest_pci_node(void) { } 3917 + #endif 3918 + 3737 3919 static int __init of_unittest(void) 3738 3920 { 3739 3921 struct device_node *np; ··· 3969 3781 of_unittest_platform_populate(); 3970 3782 of_unittest_overlay(); 3971 3783 of_unittest_lifecycle(); 3784 + of_unittest_pci_node(); 3972 3785 3973 3786 /* Double check linkage after removing testcase data */ 3974 3787 of_unittest_check_tree_linkage();
+1
drivers/pci/quirks.c
··· 6149 6149 */ 6150 6150 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node); 6151 6151 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node); 6152 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node);