mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
PCI: Initialize temporary device in new_id_store()
When setting new_id of a PCI device driver using sysfs a lockdep splat occurs. This is because new_id_store() builds a temporary pci_dev for pci_match_device(), which calls device_match_driver_override(). That depends on the driver_override.lock added bycb3d1049f4("driver core: generalize driver_override in struct device"). The new driver_override.lock was not initialized in the temporary pci_dev, resulting in this lockdep splat. Initialize the temporary pci_dev to fix this. Repro: Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID: # echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator. CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x5d/0x80 register_lock_class+0x77e/0x790 lock_acquire+0xbf/0x2e0 pci_match_device+0x24/0x180 new_id_store+0x189/0x1d0 kernfs_fop_write_iter+0x14f/0x210 vfs_write+0x263/0x5e0 ksys_write+0x79/0xf0 do_syscall_64+0x117/0xf80 Fixes:10a4206a24("PCI: use generic driver_override infrastructure") Fixes:8895d3bcb8("PCI: Fail new_id for vendor/device values already built into driver") Signed-off-by: Samiullah Khawaja <skhawaja@google.com> [bhelgaas: add commit log details and repro, trim backtrace] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260505234327.716630-1-skhawaja@google.com
This commit is contained in:
parent
909f7bf9b0
commit
f45a49a238
|
|
@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void _pci_free_device(struct device *dev)
|
||||
{
|
||||
kfree(to_pci_dev(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* new_id_store - sysfs frontend to pci_add_dynid()
|
||||
* @driver: target device driver
|
||||
|
|
@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf,
|
|||
pdev->subsystem_vendor = subvendor;
|
||||
pdev->subsystem_device = subdevice;
|
||||
pdev->class = class;
|
||||
pdev->dev.release = _pci_free_device;
|
||||
|
||||
device_initialize(&pdev->dev);
|
||||
if (pci_match_device(pdrv, pdev))
|
||||
retval = -EEXIST;
|
||||
|
||||
kfree(pdev);
|
||||
put_device(&pdev->dev);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user