<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi,<br>
    </p>
    <div class="moz-cite-prefix">On 2023/7/17 17:51, suijingfeng wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <p>Hi,<br>
      </p>
      <p><br>
      </p>
      <div class="moz-cite-prefix">On 2023/7/11 21:43, Sui Jingfeng
        wrote:<br>
      </div>
      <blockquote type="cite"
        cite="mid:20230711134354.755966-3-sui.jingfeng@linux.dev">
        <pre class="moz-quote-pre" wrap="">From: Sui Jingfeng <a class="moz-txt-link-rfc2396E" href="mailto:suijingfeng@loongson.cn" moz-do-not-send="true"><suijingfeng@loongson.cn></a>

Currently, vgaarb only cares about PCI VGA-compatible class devices.

While vga_arbiter_del_pci_device() gets called unbalanced when some PCI
device is about to be removed. This happens even during the boot process.

Another reason is that the vga_arb_device_init() function is not efficient.
Since we only care about VGA-compatible devices (pdev->class == 0x030000),
We could filter the unqualified devices out in the vga_arb_device_init()
function. While the current implementation is to search all PCI devices
in a system, this is not necessary.

Reviewed-by: Mario Limonciello <a class="moz-txt-link-rfc2396E" href="mailto:mario.limonciello@amd.com" moz-do-not-send="true"><mario.limonciello@amd.com></a>
Signed-off-by: Sui Jingfeng <a class="moz-txt-link-rfc2396E" href="mailto:suijingfeng@loongson.cn" moz-do-not-send="true"><suijingfeng@loongson.cn></a>
---
 drivers/pci/vgaarb.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c
index c1bc6c983932..021116ed61cb 100644
--- a/drivers/pci/vgaarb.c
+++ b/drivers/pci/vgaarb.c
@@ -754,10 +754,6 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
        struct pci_dev *bridge;
        u16 cmd;
 
-       /* Only deal with VGA class devices */
-       if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-               return false;
-
        /* Allocate structure */
        vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
        if (vgadev == NULL) {
@@ -1502,6 +1498,10 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
 
        vgaarb_dbg(dev, "%s\n", __func__);
 
+       /* Deal with VGA compatible devices only */
+       if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+               return 0;
+
        /* For now we're only intereted in devices added and removed. I didn't
         * test this thing here, so someone needs to double check for the
         * cases of hotplugable vga cards. */
@@ -1534,8 +1534,8 @@ static struct miscdevice vga_arb_device = {
 
 static int __init vga_arb_device_init(void)
 {
+       struct pci_dev *pdev = NULL;
        int rc;
-       struct pci_dev *pdev;
 
        rc = misc_register(&vga_arb_device);
        if (rc < 0)
@@ -1543,13 +1543,14 @@ static int __init vga_arb_device_init(void)
 
        bus_register_notifier(&pci_bus_type, &pci_notifier);
 
-       /* We add all PCI devices satisfying VGA class in the arbiter by
-        * default */
-       pdev = NULL;
-       while ((pdev =
-               pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-                              PCI_ANY_ID, pdev)) != NULL)
-               vga_arbiter_add_pci_device(pdev);
+       /*
+        * We add all PCI VGA compatible devices in the arbiter by default
+        */
+       do {
+               pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev);
+               if (pdev)
+                       vga_arbiter_add_pci_device(pdev);
+       } while (pdev);
</pre>
      </blockquote>
      <pre id="b">I suddenly remember one more thing that I forget to explain.

In a previous thread[1] of previous version of this series,

Maciej seems argue that PCI_CLASS_NOT_DEFINED_VGA should be handled also.

But, even I try to handled PCI_CLASS_NOT_DEFINED_VGA at here,

this card still will not be annotate as boot_vga,

because the pci_dev_attrs_are_visible() function only consider VGA compatible devices

which (pdev->class >> 8 == PCI_CLASS_DISPLAY_VGA) is true. See [2].


Intel integrated GPU is more intelligent,

which could change their class of the PCI(e) device to 0x038000 when

multiple GPU co-exist. Even though the GPU can display. This is configurable by

the firmware, but this is trying to escape the arbitration by changing is PCI id. 
</pre>
    </blockquote>
    <pre id="b">"by changing is PCI id" -> "by changing its PCI(e) class number".

For example, the intel GPU will change their PCI class number from 0x030000 to 0x038000,

if a user choose the dGPU as primary by setting their UEFI firmware from the BIOS.


But other GPUs may not support to change their PCI class number.

</pre>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <pre id="b">

So, PCI devices belong to the PCI_CLASS_DISPLAY_OTHER, PCI_CLASS_DISPLAY_3D and PCI_CLASS_DISPLAY_XGA

can not participate in the arbitration. They are all will be get filtered. </pre>
    </blockquote>
    <p>I means that PCI devices with their PCI class number equal  to</p>
    <p>PCI_CLASS_DISPLAY_OTHER, PCI_CLASS_DISPLAY_3D and
      PCI_CLASS_DISPLAY_XGA</p>
    <p>will get ignored by vgaarb currently.</p>
    <p>Even we throw other devices(DISPLAY_OTHER, DISPLAY_3D,
      DISPLAY_XGA) into the arbitrator,<br>
    </p>
    <p>We still not make a meaningful progress, I need also to change
      the code in link [2]</p>
    <p>to make the boot_vga visible to userspace. Because X server is
      the end consumer.<br>
    </p>
    <p>This already form an ABI.  So change the code here alone is not
      enough to expand vgaarb.<br>
    </p>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <pre id="b">

So, this is a limitation of the vgaarb itself.

While I could help to improve it in the future, what do you think?</pre>
    </blockquote>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <pre id="b">
Is my express clear?
</pre>
    </blockquote>
    Am I express my thoughts clearly ?<br>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <pre id="b">
</pre>
      <p>[1]
        <a class="moz-txt-link-freetext"
href="https://lkml.kernel.org/nouveau/alpine.DEB.2.21.2306190339590.14084@angie.orcam.me.uk/#t"
          moz-do-not-send="true">https://lkml.kernel.org/nouveau/alpine.DEB.2.21.2306190339590.14084@angie.orcam.me.uk/#t</a></p>
      <p>[2]
        <a class="moz-txt-link-freetext"
href="https://elixir.bootlin.com/linux/latest/source/drivers/pci/pci-sysfs.c#L1544"
          moz-do-not-send="true">https://elixir.bootlin.com/linux/latest/source/drivers/pci/pci-sysfs.c#L1544</a><br>
      </p>
    </blockquote>
    <pre id="b">
Alex acclaims that "we won't need vgaarb if the platform has no VGA devices", see [3].

while this is not 100% correct, because X server is the primary consumer of the boot_vga flag,

the convention usage of the userspace and the kernel space is already established.

So without we can craft something new easily without significant change.



[3] <a class="moz-txt-link-freetext" href="https://lkml.kernel.org/nouveau/CADnq5_PFoM2O8mCd6+VFfu9Nc-Hg_HTnwEMxrq0FGRpva1kKiA@mail.gmail.com/">https://lkml.kernel.org/nouveau/CADnq5_PFoM2O8mCd6+VFfu9Nc-Hg_HTnwEMxrq0FGRpva1kKiA@mail.gmail.com/</a>
</pre>
    <p></p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:6b4ff3d5-293e-7bf3-f5df-babc14661c44@loongson.cn">
      <p> </p>
      <blockquote type="cite"
        cite="mid:20230711134354.755966-3-sui.jingfeng@linux.dev">
        <pre class="moz-quote-pre" wrap=""> 
        pr_info("loaded\n");
        return rc;
</pre>
      </blockquote>
    </blockquote>
  </body>
</html>