PCI, x86: fix default vga ref_count
Subsystems (5)
PATCH 1/1 PCI, x86: fix default vga ref_count
when __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
for static path, vga_default setting is through vga_arbiter_add_pci_device. and for x86 pci_fixup_video, will skip that.
because subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device.
for hotplug path, even vga_arbiter_add_pci_device is called via notifier, but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path. So x86 pci_fixup_video will take over to call vga_set_default_device().
We need to hold one dev reference there.
otherwise vga_arbiter_del_pci_device that does not check VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to decrease extra. that will have that device get deleted early wrongly.
--- arch/x86/pci/fixup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/x86/pci/fixup.c +5 -1
@@ -349,8 +349,12 @@ static void __devinit pci_fixup_video(stif (config & (PCI_COMMAND_IO |PCI_COMMAND_MEMORY )) { pdev->resource[PCI_ROM_RESOURCE ].flags |=IORESOURCE_ROM_SHADOW ;dev_printk (KERN_DEBUG , &pdev->dev,"Boot video device\n" ); -if (!vga_default_device ()) +if (!vga_default_device ()) { +#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE + pdev =pci_dev_get (pdev); +#endif vga_set_default_device (pdev); + } } } DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
PATCH 1/1 PCI, x86: clear initial value for root info resources
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.
That invalid value cause it pass through check __release_pci_root_info and panic in release_resource.
Try to use kzalloc instead.
--- arch/x86/pci/acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86/pci/acpi.c +1 -2
@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acp res->flags = flags; res->start = start; res->end = end; - res->child =NULL ;if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info size =sizeof (*info->res) * info->res_num; info->res_num =0 ; - info->res =kmalloc (size,GFP_KERNEL ); + info->res =kzalloc (size,GFP_KERNEL );if (!info->res)return ;
Bjorn Helgaas
maintainerRe: [PATCH] PCI, x86: clear initial value for root info resources
Quoted 11 lines · Yinghai Lu
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.That invalid value cause it pass through check
__release_pci_root_infoand panic inrelease_resource.Try to use kzalloc instead.
Don't we need the same fix for ia64 in pci_acpi_scan_root()? Here's what it does:
if (windows) {
controller->window =
kmalloc_node(sizeof(*controller->window) * windows,
GFP_KERNEL, controller->node);Quoted 28 lines
Signed-off-by Yinghai Lu <[email protected]>--- arch/x86/pci/acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)Index:
linux-2.6/arch/x86/pci/acpi.c
===================================================================arch/x86/pci/acpi.c +1
-2@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acp res->flags = flags; res->start = start; res->end = end; - res->child =NULL ;if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev,@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info size =sizeof (*info->res) * info->res_num; info->res_num =0 ; - info->res =kmalloc (size,GFP_KERNEL ); + info->res =kzalloc (size,GFP_KERNEL );if (!info->res)return ;
Re: [PATCH] PCI, x86: clear initial value for root info resources
Quoted 13 lines · Bjorn Helgaas
Quoted 11 lines · Yinghai Lu
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.That invalid value cause it pass through check
__release_pci_root_infoand panic inrelease_resource.Try to use kzalloc instead.
Quoted 8 lines
Don't we need the same fix for ia64 in
pci_acpi_scan_root()? Here's what it does:if (windows) { controller->window = kmalloc_node(sizeof(*controller->window) * windows, GFP_KERNEL, controller->node);
yes, but they don't support pci_set_host_bridge_release yet. so they should not meet this problem yet.
Thanks
Yinghai
Bjorn Helgaas
maintainerRe: [PATCH] PCI, x86: clear initial value for root info resources
Quoted 24 lines · Yinghai Lu
Quoted 13 lines · Bjorn Helgaas
Quoted 11 lines · Yinghai Lu
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.That invalid value cause it pass through check
__release_pci_root_infoand panic inrelease_resource.Try to use kzalloc instead.
Quoted 8 lines
Don't we need the same fix for ia64 in
pci_acpi_scan_root()? Here's what it does:if (windows) { controller->window = kmalloc_node(sizeof(*controller->window) * windows, GFP_KERNEL, controller->node);
Quoted 2 lines
yes, but they don't support
pci_set_host_bridge_releaseyet. so they should not meet this problem yet.
Why should we wait to fix that bug until later? I'm not interested in debugging this in the future. If you fix a bug, you should always try to fix other occurrences of the same bug at the same time.
Re: [PATCH] PCI, x86: clear initial value for root info resources
Quoted 6 lines · Bjorn Helgaas
Quoted 2 lines
yes, but they don't support
pci_set_host_bridge_releaseyet. so they should not meet this problem yet.Why should we wait to fix that bug until later? I'm not interested in debugging this in the future. If you fix a bug, you should always try to fix other occurrences of the same bug at the same time.
ok, will update the patch.
PATCH 1/1 PCI, x86: clear initial value for root info resources
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.
That invalid value cause it pass through check __release_pci_root_info and panic in release_resource.
Try to use kzalloc instead.
--- arch/x86/pci/acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86/pci/acpi.c +1 -2
@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acp res->flags = flags; res->start = start; res->end = end; - res->child =NULL ;if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info size =sizeof (*info->res) * info->res_num; info->res_num =0 ; - info->res =kmalloc (size,GFP_KERNEL ); + info->res =kzalloc (size,GFP_KERNEL );if (!info->res)return ;
PATCH 1/1 PCI, ia64: clear initial value for root info resources
after
PCI, ia64: clear initial value for root info resources
change ia64 code accordingly, because later ia64 will support root bus removal too.
--- arch/ia64/pci/pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
Index: linux-2.6/arch/ia64/pci/pci.c =================================--- linux-2.6.orig/arch/ia64/pci/pci.c +++ linux-2.6/arch/ia64/pci/pci.c
@@ -295,7 +295,6 @@ static __devinit acpi_status add_window(
window->resource.flags = flags;
window->resource.start = addr.minimum + offset; window->resource.end = window->resource.start + addr.address_length - 1;
- window->resource.child = NULL;
window->offset = offset;
if (insert_resource(root, &window->resource)) {
@@ -357,7 +356,7 @@ pci_acpi_scan_root(struct acpi_pci_root
&windows);
if (windows) {
controller->window - kmalloc_node(sizeof(*controller->window) * windows,
+ kzalloc_node(sizeof(*controller->window) * windows,
GFP_KERNEL, controller->node);
if (!controller->window)
goto out2;
Re: [PATCH] PCI, x86: clear initial value for root info resources
In reply to Yinghai LuQuoted 1 line · Yinghai Lu
Found one system one root bus hot remove get panic.
Boy, this is mangled.
Can you include the name of the system? Perhaps you can rephrase this to say:
"On XYZ removing the root bus (through ACPI unplug) causes a panic."
Quoted 1 line
Panic happens when try to release hostbridge resource.
Can you include the stack trace?
Quoted 3 lines
It turns out that resource get reject during put into resource tree because of conflicts.
Come again? Are you saying:
"The reason for this is that the resources was never initialized properly because of .. (what type of conflict?)"?
Quoted 6 lines
Also that resource parent pointer have random value.
That invalid value cause it pass through check
__release_pci_root_infoand panic inrelease_resource.Try to use kzalloc instead.
It is not just try, it _is_ using that now.
Quoted 35 lines
Signed-off-by Yinghai Lu <[email protected]>--- arch/x86/pci/acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)Index:
linux-2.6/arch/x86/pci/acpi.c
===================================================================arch/x86/pci/acpi.c +1
-3@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acp res->flags = flags; res->start = start; res->end = end; - res->child =NULL ;if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev,@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info size =sizeof (*info->res) * info->res_num; info->res_num =0 ; - info->res =kmalloc (size,GFP_KERNEL ); + info->res =kzalloc (size,GFP_KERNEL );if (!info->res)return ; --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
A message that is not in the archive (sent off-list or not yet received): CAE9FiQV9WK4NG5+aGwVrGO3ueFH3TmmmG5zea+JjwgtQyngNRg@mail.gmail.com
Re: [PATCH] PCI, x86: clear initial value for root info resources
Quoted 73 lines · Yinghai Lu
Quoted 3 lines · Konrad Rzeszutek Wilk
On Wed, Sep 19, 2012 at 10:49:00AM -0700, Yinghai Lu wrote:
Can you include the stack trace?
[ 414.997281] pci_bus 0000:00: freeing pci_bus info [ 415.017221] pci0000:00: freeing pci_host_bridge info [ 415.017468] general protection fault: 0000 [#1] SMP [ 415.036758] Modules linked in: [ 415.036959] CPU 0 [ 415.037051] Pid: 4, comm: kworker/0:0 Not tainted 3.6.0-rc6-yh-03463-gbcab6f1-dirty #303 Oracle Corporation Sun Fire X4800 M2 / [ 415.056989] RIP: 0010:[<ffffffff81075218>] [<ffffffff81075218>] __release_resource+0x11/0x3e [ 415.076854] RSP: 0018:ffff883f4cea39f0 EFLAGS: 00010206 [ 415.077112] RAX: 0d00000000000030 RBX: ffff897ea6cd4070 RCX: 8c6318c6318c6320 [ 415.097000] RDX: ffff883f9d60e190 RSI: ffffffff8265f228 RDI: ffff897ea6cd4070 [ 415.116627] RBP: ffff883f4cea39f0 R08: 0000000000000005 R09: ffffffff810755de [ 415.116953] R10: ffffffff81e2e7df R11: 0000000000000000 R12: 0000000000000002 [ 415.136790] R13: ffff897ea6d18600 R14: ffffffff826f18c0 R15: ffff883f9d60d800 [ 415.156541] FS: 0000000000000000(0000) GS:ffff883f9d600000(0000) knlGS:0000000000000000 [ 415.156953] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 415.176622] CR2: 0000000000619718 CR3: 000000000263f000 CR4: 00000000000007f0 [ 415.196401] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 415.196761] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 415.216702] Process kworker/0:0 (pid: 4, threadinfo ffff883f4cea2000, task ffff883f4cea8000) [ 415.236370] Stack: [ 415.236475] ffff883f4cea3a20 ffffffff810755e6 ffff883f4cea3a60 ffff883f00000000 [ 415.236866] ffffffff824884ad ffff88fea6ce2440 ffff883f4cea3a40 ffffffff81c2cfc5 [ 415.256682] ffff88bf4a1ec800 ffff88bf4a1ec800 ffff883f4cea3a50 ffffffff81c2d023 [ 415.276452] Call Trace: [ 415.276611] [<ffffffff810755e6>] release_resource+0x25/0x3e [ 415.296206] [<ffffffff81c2cfc5>] __release_pci_root_info+0x35/0x7e [ 415.296556] [<ffffffff81c2d023>] release_pci_root_info+0x15/0x1a [ 415.316249] [<ffffffff813f568a>] pci_release_bus_bridge_dev+0x37/0x4f [ 415.316581] [<ffffffff815c04d8>] device_release+0x93/0xcb [ 415.336365] [<ffffffff813d5888>] kobject_release+0x51/0x67 [ 415.336666] [<ffffffff813d579a>] kobject_put+0x4a/0x4e [ 415.361466] [<ffffffff815c026a>] put_device+0x17/0x19 [ 415.361734] [<ffffffff813f75b2>] pci_remove_root_bus+0x5a/0x64 [ 415.376188] [<ffffffff81437dd8>] acpi_pci_root_remove+0xeb/0x114 [ 415.376509] [<ffffffff81434c13>] acpi_device_remove+0x86/0xa5 [ 415.396230] [<ffffffff815c33b6>] __device_release_driver+0x86/0xdc [ 415.396551] [<ffffffff815c3431>] device_release_driver+0x25/0x32 [ 415.416198] [<ffffffff8143658b>] acpi_bus_trim+0x86/0x110 [ 415.416473] [<ffffffff81439ae1>] handle_root_bridge_removal+0x4f/0x118 [ 415.436227] [<ffffffff81439c8b>] _handle_hotplug_event_root+0xe1/0x121 [ 415.455957] [<ffffffff81085515>] process_one_work+0x28a/0x453 [ 415.456228] [<ffffffff81085480>] ? process_one_work+0x1f5/0x453 [ 415.475980] [<ffffffff81439baa>] ? handle_root_bridge_removal+0x118/0x118 [ 415.476311] [<ffffffff81085bd1>] worker_thread+0x12a/0x201 [ 415.495995] [<ffffffff81085aa7>] ? manage_workers+0xed/0xed [ 415.496301] [<ffffffff8108b93a>] kthread+0xe7/0xef [ 415.515957] [<ffffffff81e2ef03>] ? _raw_spin_unlock_irq+0x2e/0x33 [ 415.516257] [<ffffffff81e372e4>] kernel_thread_helper+0x4/0x10 [ 415.535926] [<ffffffff81e2f259>] ? retint_restore_args+0xe/0xe [ 415.536242] [<ffffffff8108b853>] ? __init_kthread_worker+0x5a/0x5a [ 415.555959] [<ffffffff81e372e0>] ? gs_change+0xb/0xb [ 415.556209] Code: 48 89 31 48 89 46 20 31 c0 eb 0d 48 39 7a 08 48 8d 4a 28 72 da 48 89 d0 5d c3 66 66 66 66 90 48 8b 47 20 55 48 89 e5 48 83 c0 30 <48> 8b 10 48 85 d2 74 1e 48 39 fa 75 13 48 8b 57 28 48 89 10 48 [ 415.596509] RIP [<ffffffff81075218>] __release_resource+0x11/0x3e [ 415.615741] RSP <ffff883f4cea39f0> [ 415.616020] ---[ end trace 8bcbc1bea9c3e0bc ]---
Quoted 1 line
whole log is attached.
I meant it (and a filtered with just the valid lines in it) in terms of the patch commit description.
Re: [PATCH] PCI, x86: clear initial value for root info resources
In reply to Yinghai LuQuoted 24 lines · Yinghai Lu
Quoted 13 lines · Bjorn Helgaas
Quoted 11 lines · Yinghai Lu
Found one system one root bus hot remove get panic. Panic happens when try to release hostbridge resource.
It turns out that resource get reject during put into resource tree because of conflicts.
Also that resource parent pointer have random value.That invalid value cause it pass through check
__release_pci_root_infoand panic inrelease_resource.Try to use kzalloc instead.
Quoted 8 lines
Don't we need the same fix for ia64 in
pci_acpi_scan_root()? Here's what it does:if (windows) { controller->window = kmalloc_node(sizeof(*controller->window) * windows, GFP_KERNEL, controller->node);
Quoted 2 lines
yes, but they don't support
pci_set_host_bridge_releaseyet. so they should not meet this problem yet.
Hi Yinghai,
We are trying to add pci_set_host_bridge_release() for IA64, so would
appreciate it if you could help to fix IA64 too.
--Gerry
PATCH 1/1 PCI: Use correct type when freeing bus resource list
In reply to Yinghai LuShould use struct pci_bus_resource instead of struct pci_host_bridge_window
--- drivers/pci/bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/pci/bus.c +5 -1
@@ -87,11 +87,15 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n);void pci_bus_remove_resources (struct pci_bus *bus) {int i; +struct pci_bus_resource *bus_res, *tmp;for (i =0 ; i <PCI_BRIDGE_RESOURCE_NUM ; i++) bus->resource[i] =NULL ; -pci_free_resource_list (&bus->resources); +list_for_each_entry_safe (bus_res, tmp, &bus->resources, list) { +list_del (&bus_res->list); +kfree (bus_res); + } }/**
Bjorn Helgaas
maintainerRe: [PATCH] PCI: Use correct type when freeing bus resource list
Quoted 1 line · Yinghai Lu
Should use struct
pci_bus_resourceinstead of structpci_host_bridge_window
Looks good, and this is all my fault, sorry. Applied to a pci/yinghai-misc branch.
Quoted 27 lines
Signed-off-by Yinghai Lu <[email protected]>--- drivers/pci/bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)Index:
linux-2.6/drivers/pci/bus.c
===================================================================drivers/pci/bus.c +5
-1@@ -87,11 +87,15 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n);void pci_bus_remove_resources (struct pci_bus *bus) {int i; +struct pci_bus_resource *bus_res, *tmp;for (i =0 ; i <PCI_BRIDGE_RESOURCE_NUM ; i++) bus->resource[i] =NULL ; -pci_free_resource_list (&bus->resources); +list_for_each_entry_safe (bus_res, tmp, &bus->resources, list) { +list_del (&bus_res->list); +kfree (bus_res); + } }/**
Bjorn Helgaas
maintainerQuoted 10 lines · Yinghai Lu
when
__ARCH_HAS_VGA_DEFAULT_DEVICEis not defined, aka EFIFB is not used,for static path,
vga_defaultsetting is throughvga_arbiter_add_pci_device. and for x86pci_fixup_video, will skip that.
becausesubsys_initcall(vga_arb_device_init)come first to callvga_arbiter_add_pci_device.for hotplug path, even
vga_arbiter_add_pci_deviceis called via notifier, but it will checkVGA_RSRC_LEGACY_MASKthat is not set for hotplug path. So x86pci_fixup_videowill take over to callvga_set_default_device().
Quoted 5 lines
We need to hold one dev reference there.
otherwise
vga_arbiter_del_pci_devicethat does not checkVGA_RSRC_LEGACY_MASKwill callput_deviceand it will causeref_countto decrease extra. that will have that device get deleted early wrongly.
I'm sure you're fixing a real bug, but this patch is completely unintelligible.
I tried to decipher the changelog and I failed. I tried to figure out the PCI reference counting from the vgaarb code, and I failed there too.
Apparently the reference is connected with the vga_default device, since that's what vga_arbiter_del_pci_device() checks, but vga_set_default_device() is blissfully ignorant of references (and it isn't used consistently anyway).
If you can do some rework to make this all make more sense, that would be great.
While you're at it, look at both the x86 and ia64 versions of pci_fixup_video(). They are 90% identical, and it's not clear why they should be different. In fact, it's not clear why there's a fixup for x86 and ia64 but not for any other architecture with PCI.
Quoted 25 lines
Signed-off-by Yinghai Lu <[email protected]>--- arch/x86/pci/fixup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)Index:
linux-2.6/arch/x86/pci/fixup.c
===================================================================arch/x86/pci/fixup.c +5
-1@@ -349,8 +349,12 @@ static void __devinit pci_fixup_video(stif (config & (PCI_COMMAND_IO |PCI_COMMAND_MEMORY )) { pdev->resource[PCI_ROM_RESOURCE ].flags |=IORESOURCE_ROM_SHADOW ;dev_printk (KERN_DEBUG , &pdev->dev,"Boot video device\n" ); -if (!vga_default_device ()) +if (!vga_default_device ()) { +#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE + pdev =pci_dev_get (pdev); +#endif vga_set_default_device (pdev); + } } } DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
Quoted 11 lines · Bjorn Helgaas
Quoted 10 lines · Yinghai Lu
when
__ARCH_HAS_VGA_DEFAULT_DEVICEis not defined, aka EFIFB is not used,for static path,
vga_defaultsetting is throughvga_arbiter_add_pci_device. and for x86pci_fixup_video, will skip that.
becausesubsys_initcall(vga_arb_device_init)come first to callvga_arbiter_add_pci_device.for hotplug path, even
vga_arbiter_add_pci_deviceis called via notifier, but it will checkVGA_RSRC_LEGACY_MASKthat is not set for hotplug path. So x86pci_fixup_videowill take over to callvga_set_default_device().
Quoted 7 lines
Quoted 5 lines
We need to hold one dev reference there.
otherwise
vga_arbiter_del_pci_devicethat does not checkVGA_RSRC_LEGACY_MASKwill callput_deviceand it will causeref_countto decrease extra. that will have that device get deleted early wrongly.I'm sure you're fixing a real bug, but this patch is completely unintelligible.
yes, only can hit this bug while remove root bus with vga adapater.
or remove bridge with child pci device that is vga adapter.
for root bus removal, the less one ref_count will call that pci device get destroyed too early.
Quoted 9 lines
I tried to decipher the changelog and I failed. I tried to figure out the PCI reference counting from the vgaarb code, and I failed there too.
Apparently the reference is connected with the
vga_defaultdevice, since that's whatvga_arbiter_del_pci_device()checks, butvga_set_default_device()is blissfully ignorant of references (and it isn't used consistently anyway).
yes, could fix vga_set_default_device instead, but it has two versions
- no __ARCH_HAS_VGA_DEFAULT_DEVICE
- EFI version...
also there is one other user for vga switching...
Quoted 7 lines
If you can do some rework to make this all make more sense, that would be great.
While you're at it, look at both the x86 and ia64 versions of
pci_fixup_video(). They are 90% identical, and it's not clear why they should be different. In fact, it's not clear why there's a fixup for x86 and ia64 but not for any other architecture with PCI.
ok, will give it a try.
Thanks
Yinghai
PATCH 1/1 PCI: fix default vga ref_count
In reply to Bjorn Helgaaswhen __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
for static path, vga_default setting is through vga_arbiter_add_pci_device.
and later x86 pci_fixup_video, will skip setting again.
- subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device. It will call pci_get_dev to hold one reference.
for hotplug add path, even vga_arbiter_add_pci_device is called via notifier, but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path. So x86 pci_fixup_video will take over to call vga_set_default_device(). It will not hold one refrence.
Later for hotplug remove path, vga_arbiter_del_pci_device that does not check VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to decrease extra. that will have that pci device get deleted early wrongly.
Need to make get/put balance for both cases.
-v2: According to Bjorn, update vga_set_default_device instead...
--- drivers/gpu/vga/vgaarb.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/gpu/vga/vgaarb.c +9 -5
@@ -141,6 +141,12 @@ EXPORT_SYMBOL_GPL(vga_default_device);void vga_set_default_device (struct pci_dev *pdev) { +if (vga_default) +pci_dev_put (vga_default); + +if (pdev) + pdev =pci_dev_get (pdev); + vga_default = pdev; }#endif
@@ -577,7 +583,7 @@ static bool vga_arbiter_add_pci_device(s#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICEif (vga_default ==NULL && ((vgadev->owns &VGA_RSRC_LEGACY_MASK ) ==VGA_RSRC_LEGACY_MASK )) - vga_default =pci_dev_get (pdev); +vga_set_default_device (pdev);#endif vga_arbiter_check_bridge_sharing (vgadev);
@@ -613,10 +619,8 @@ static bool vga_arbiter_del_pci_device(s }#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE -if (vga_default == pdev) { -pci_dev_put (vga_default); - vga_default =NULL ; - } +if (vga_default == pdev) +vga_set_default_device (NULL );#endif if (vgadev->decodes & (VGA_RSRC_LEGACY_IO |VGA_RSRC_LEGACY_MEM ))
Re: [PATCH] PCI: fix default vga ref_count
drivers/gpu/vga/vgaarb.c EXPORT_SYMBOL_GPL(vga_default_device); · line 150
Quoted 9 lines · Yinghai Lu
void
vga_set_default_device(struct pci_dev *pdev){drivers/gpu/vga/vgaarb.c +6
-0+if (vga_default) +pci_dev_put (vga_default); + +if (pdev) + pdev =pci_dev_get (pdev); + vga_default = pdev;
It shouldn't happen, but do we want to check for the vga_default == pdev case?
Signature · 1 line
Matthew Garrett | [email protected]